Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«ΠŸΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Windows APIΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 7

Автор А. Π›Π΅Π³Π°Π»ΠΎΠ²

Рис. 1. ΠšΠ»Π°ΡΡΡ‹, Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌΡ‹Π΅ Π² ΠΎΠ±Ρ€Π°Π·Π΅Ρ† проСктирования "Π”ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ".

Π”Π°Π²Π°ΠΉΡ‚Π΅, Π½Π°Ρ‡Π½Π΅ΠΌ с клиСнтского ΠΊΠΎΠ΄Π°. Π’ нашСй ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΌΡ‹ нуТдаСмся Π² Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠΌ ΠΎΠΊΠ½Π΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ позволяСт ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ строку. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ рСсурса, ΠΌΡ‹ создаСм шаблон Π΄ΠΈΠ°Π»ΠΎΠ³Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит срСдства рСдактирования ΠΈ Π΄Π²Π΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ, OK ΠΈ CANCEL. Π˜Π΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ рСсурса (id) этого Π΄ΠΈΠ°Π»ΠΎΠ³Π° – IDD_EDITDIALOG. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ опрСдСляСм наш собствСнный класс списка ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ EditorData ΠΈ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ класс ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ EditorCtrl. Когда ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π²Ρ‹Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΏΡƒΠ½ΠΊΡ‚ мСню Edit, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄:

void Controller::Edit(HWND hwnd) {

 EditorData data(_model.GetText ());

 ControllerFactory<EditorCtrl, EditorData> factory(&data);

 ModalDialog dialog(_hInst, hwnd, IDD_EDITDIALOG, &factory);

 if (dialog.IsOk()) {

  _model.SetText(data.GetName());

  // Force repaint

  InvalidateRect(hwnd, 0, TRUE);

 }

}

Π‘Π½Π°Ρ‡Π°Π»Π° создаСтся ΠΈ инициализируСтся строкой ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ EditorData. Π—Π°Ρ‚Π΅ΠΌ, формируСтся шаблон ControllerFactory. ΠœΡ‹ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΠ·ΡƒΠ΅ΠΌ Π΅Π³ΠΎ двумя клиСнтскими классами EditorCtrl ΠΈ EditorData. ΠžΠ±ΡŠΠ΅ΠΊΡ‚ Ρ„Π°Π±Ρ€ΠΈΠΊΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΌ Π½Π° наши Π΄Π°Π½Π½Ρ‹Π΅. Π—Π°Ρ‚Π΅ΠΌ создаСтся ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ModalDialog. Он ΠΏΠΎΠ»ΡƒΡ‡Π΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π½Π°ΡˆΡƒ Ρ„Π°Π±Ρ€ΠΈΠΊΡƒ Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°. Π­Ρ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° ΠΈ Π²ΠΎΡΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· списка ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ². ПослС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅Π½ΠΎ взаимодСйствиС с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ, ΠΌΡ‹ провСряСм, ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π°Π» Π»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹, наТимая ΠΊΠ½ΠΎΠΏΠΊΡƒ OK, ΠΈ Ссли Ρ‚Π°ΠΊ, Ρ‚ΠΎ ΠΌΡ‹ фиксируСм Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ рСдактирования ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ ΠΈΡ… Π² нашСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅. Π­Ρ‚ΠΎΡ‚ способ создания Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠΊΠ½Π° являСтся Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ Ρ‚ΠΈΠΏΠΈΡ‡Π½Ρ‹ΠΌ.

Класс EditorData Π² нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΏΡ€Π΅Π΄Π΅Π»ΡŒΠ½ΠΎ прост.

class EditorData {

public:

 enum { maxLen = 128 };

 EditorData(char const* name) {

  SetName(name);

 }

 BOOL IsNameOK() { return (_name[0] != '\0'); }

 void SetName(char const *name) {

  strcpy(_name, name);

 }

 char const* GetName() { return _name; }

private:

 char _name[maxLen];

};

Класс ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°, EditorCtrl, содСрТит всС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ. ΠŸΡ€Π΅ΠΆΠ΄Π΅ всСго ΠΎΠ½ встраиваСт Π² сСбя элСмСнт рСдактирования. Π­Ρ‚ΠΎΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ отвСтствСн Π·Π° взаимодСйствиС с элСмСнтом рСдактирования, Π²Π½Π΅Π΄Ρ€Π΅Π½Π½Ρ‹ΠΌ Π² Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ. Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ IDC_NAME_EDIT, заданныйс ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π° рСсурсов. Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ Ρ…Ρ€Π°Π½ΠΈΡ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° EditorData. Π­Ρ‚ΠΎΡ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ взят ΠΈΠ· Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса DlgController. Π’Ρ€ΠΈ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄Π° DlgController Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ пСрСписаны Π² нашСм EditorControl. Π­Ρ‚ΠΎ OnInitDialog, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ вызываСтся Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π΄ΠΈΠ°Π»ΠΎΠ³ Π±Ρ‹Π» ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½, OnCommand, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ вызываСтся всякий Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° любой элСмСнт Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠΊΠ½Π° посылаСт Π½Π°ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ ΠΈ, Π² Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, OnNotify, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π½ΠΎΠ²Ρ‹ΠΌΠΈ элСмСнтами управлСния Windows95.

class EditorCtrl : public DlgController {

public:

 EditorCtrl(HWND hwndDlg, void *argList) : DlgController(argList), _nameEdit(hwndDlg, IDC_NAME_EDIT) {

  _dlgData = (EditorData*)GetArgList();

 }

 void OnInitDialog(HWND hwnd);

 bool OnCommand(HWND hwnd, int ctrlID, int notifyCode);

 bool OnNotify(HWND hwnd, int idCtrl, NMHDR *hdr);

private:

 Edit _nameEdit;

 EditorData *_dlgData;

};

Π’ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ OnInitDialog ΠΌΡ‹ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ строку, которая Π±Ρ‹Π»Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π° Π² EditorData ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π΅Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ элСмСнт рСдактирования.

void EditorCtrl::OnInitDialog(HWND hwnd) {

 char const* name = _dlgData->GetName();

 _nameEdit.SetString(name);

}

OnCommand ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΎΡ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… элСмСнтов. Π­Π»Π΅ΠΌΠ΅Π½Ρ‚Ρ‹ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ ΠΈΡ… ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π°ΠΌΠΈ. НапримСр, Ссли ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ β€” IDC_NAME_EDIT, это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Ρ‡Ρ‚ΠΎ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ с элСмСнтом рСдактирования. Π’ нашСй Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠ°Π»ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, ΠΈ ΠΌΡ‹ Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΠ΅ΠΌ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅, копируя Ρ†Π΅Π»ΡƒΡŽ строку Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ EditorData. Π₯отя Π²ΡΡ‚Ρ€Π΅Ρ‡Π°ΡŽΡ‚ΡΡ случаи, ΠΊΠΎΠ³Π΄Π° Π’Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΡŒ строки ΠΈΠ»ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Π΅Π΅ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΌ элСмСнтС управлСния, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π’Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ€Π΅Π°Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ сообщСниС ΠΎΠ± ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ.

Когда ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π½Π°ΠΆΠΈΠΌΠ°Π΅Ρ‚ ΠΊΠ½ΠΎΠΏΠΊΡƒ OK, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ с ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ IDOK. ΠœΡ‹ провСряСм строку ΠΈ, Ссли ΠΎΠ½Π° ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π°Ρ, Ρ‚ΠΎ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅ΠΌ Π΄ΠΈΠ°Π»ΠΎΠ³, ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‰ΠΈΠΉ TRUE ΠΊΠ°ΠΊ ΠΊΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π°. Когда ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ β€” IDCANCEL (ΠΎΡ‚ ΠΊΠ½ΠΎΠΏΠΊΠΈ Cancel) ΠΌΡ‹ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅ΠΌ Π΄ΠΈΠ°Π»ΠΎΠ³ с ΠΊΠΎΠ΄ΠΎΠΌ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° FALSE.

ΠœΠ΅Ρ‚ΠΎΠ΄ OnNotify Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚ ΠΏΡ€ΠΈ использовании элСмСнтов управлСния, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π²ΡˆΠΈΡ…ΡΡ Π΄ΠΎ Widnows95, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ элСмСнты рСдактирования ΠΈ ΠΊΠ½ΠΎΠΏΠΊΠΈ.

bool EditorCtrl::OnCommand(HWND hwnd, int ctrlID, int notifyCode) {

 switch (ctrlID) {

 case IDC_NAME_EDIT:

  if (_nameEdit.IsChanged(notifyCode)) {

   char nameBuf [EditorData::maxLen];

   int len = _nameEdit.GetLen();

   if (len < EditorData::maxLen) {

    _nameEdit.GetString(nameBuf, sizeof(nameBuf));

    _dlgData->SetName(nameBuf);

   }

   return true;

  }

  break;

 case IDOK:

  if (_dlgData->IsNameOK()) {

   EndDialog(hwnd, TRUE);

  } else {

   MessageBox(hwnd, "Please, enter valid name", "Name Editor", MB_ICONINFORMATION | MB_OK);

  }

  return true;

 case IDCANCEL:

  EndDialog(hwnd, FALSE);

  return true;

 }

 return false;

}


bool EditorCtrl::OnNotify(HWND hwnd, int idCtrl, NMHDR *hdr) {

 return false;

}

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Π’Ρ‹ Π·Π½Π°Π΅Ρ‚Π΅ клиСнтский ΠΊΠΎΠ΄, Π΄Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим ΠΏΠΎΠ»Π½ΡƒΡŽ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΎΠ±Ρ€Π°Π·Ρ†Π° "Π”ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ". Π€Π°Π±Ρ€ΠΈΠΊΠ° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° β€” ΠΎΡ‡Π΅Π½ΡŒ простой шаблон класса. ВсС, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° Π΄Π΅Π»Π°Π΅Ρ‚, это ΠΏΡ€ΠΈΠ΅ΠΌ списка ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΈ сохранСниС Π΅Π³ΠΎ Ρ‡Π΅Ρ€Π΅Π· void-ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ. Волько ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ Π·Π½Π°Π΅Ρ‚, Ρ‡Π΅ΠΌ фактичСски являСтся класс, Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½Π½Ρ‹ΠΉ Π² спискС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ², ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ½ выполняСт ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ (см. конструктор EditorCtrl).

Код, ΠΎΠ±Ρ‰ΠΈΠΉ для всСх Ρ„Π°Π±Ρ€ΠΈΠΊ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ΠΎΠ² ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½ Π² классС CtrlFactory ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ наслСдуСт фактичСский шаблон. Π¨Π°Π±Π»ΠΎΠ½ пСрСопрСдСляСт ΠΌΠ΅Ρ‚ΠΎΠ΄ MakeController, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ для класса ActualCtrl, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ActualCtrl ΠΊΠ°ΠΊ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π΅Π³ΠΎ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ класс DlgController, ΠΈ это β€” всС Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π²ΠΈΠ΄ΠΈΡ‚ ΠΎΡΡ‚Π°Π»ΡŒΠ½Π°Ρ Ρ‡Π°ΡΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

class CtrlFactory {

public:

 CtrlFactory(void *argList) : _argList(argList) {}

 void *GetArgList() { return _argList; }

 virtual DlgController* MakeController(HWND hwndDlg) = 0;

 private: void *_argList;

};


template <class ActualCtrl, class ActualArgList>

class ControllerFactory : public CtrlFactory {

public:

 ControllerFactory(void *argList) : CtrlFactory(argList) {}

 DlgController * MakeController(HWND hwndDlg) {

  return new ActualCtrl(hwndDlg, (ActualArgList*)GetArgList());

 }

};

НиТС приводится ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ абстрактного класса DlgController, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΊΠ°ΠΊ основа для всСх классов ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ΠΎΠ², ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ. ΠœΡ‹ ΡƒΠΆΠ΅ Π²ΠΈΠ΄Π΅Π»ΠΈ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ эти наслСдования Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ клиСнтского класса EditorCtrl.

class DlgController {

public:

 virtual ~DlgController() {} // In case derived class overrides

 virtual void OnInitDialog(HWND hwnd) = 0;

 virtual bool OnCommand(HWND hwnd, int ctrlID, int notifyCode) = 0;

 virtual bool OnNotify(HWND hwnd, int idCtrl, NMHDR *hdr) = 0;

 void *GetArgList() { return _argList; }

protected:

 DlgController(void *argList) : _argList (argList) {}

private:

 void *_argList;

};

Π¦Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½Ρ‹ΠΌ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΎΠΌ для ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎΠ³ΠΎ использования ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния являСтся класс ModalDialog. Он Π΄Π΅Π»Π°Π΅Ρ‚ всю Ρ€Π°Π±ΠΎΡ‚Ρƒ Π² своСм конструкторС, вызывая Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ API DialogBoxParam. ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅ΠΌ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠΌΡƒ ΠΎΠΊΠ½Ρƒ (фактичСски, Π΅Π³ΠΎ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π΅ Π΄ΠΈΠ°Π»ΠΎΠ³Π°) β€” ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Ρ„Π°Π±Ρ€ΠΈΠΊΡƒ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°. ΠŸΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° Π΄ΠΈΠ°Π»ΠΎΠ³Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° ΠΊΠ°ΠΊ статичСский ΠΌΠ΅Ρ‚ΠΎΠ΄ (Π½Π΅ Π½ΡƒΠΆΠ΅Π½ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ: ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° Π΄ΠΈΠ°Π»ΠΎΠ³Π° вызываСтся ΠΈΠ· Windows, поэтому отсутствуСт доступ ΠΏΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŽ).

class ModalDialog {

public:

 ModalDialog(HINSTANCE hInst, HWND hwnd, int dlgResource, CtrlFactory *ctrlFactory) {

  _result = DialogBoxParam(hInst, MAKEINTRESOURCE(dlgResource), hwnd, (DLGPROC)ModalDialogProc, (LPARAM)ctrlFactory);

 }

 static BOOL CALLBACK ModalDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

 bool IsOk() const { return (_result == –1) ? false : _result != 0; }

private:

 int _result;

};

Π’ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° Π΄ΠΈΠ°Π»ΠΎΠ³Π°, общая для всСх Ρ‚ΠΈΠΏΠΎΠ² Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ², Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ Π½Π° Ρ‚Ρ€ΠΈ Π²ΠΈΠ΄Π° сообщСний: WM_INITDIALOG, WM_COMMAND ΠΈ WM_NOTIFY. ЀактичСски, всС ΠΎΠ½ΠΈ Π½Π°ΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ эти сообщСния ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ β€” ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Ρƒ. Он ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° вызывая Π² Π½Π°Ρ‡Π°Π»Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ Ρ„Π°Π±Ρ€ΠΈΠΊΠΈ MakeController.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ, ΠΈΠ· этой Ρ‚ΠΎΡ‡ΠΊΠΈ ΠΌΡ‹ позволяСм Windows, ΠΎΡ‚ΡΠ»Π΅Π΄ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€. ΠœΡ‹ сохраняСм Π΅Π³ΠΎ ΠΊΠ°ΠΊ GWL_USERDATA β€” ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ Π΄Π»ΠΈΠ½Π½Ρ‹ΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ассоциируСтся с ΠΊΠ°ΠΆΠ΄Ρ‹ΠΌ ΠΎΠΊΠ½ΠΎΠΌ, Π² особСнности с нашим Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠΌ, ΠΈ доступСн Ρ‡Π΅Ρ€Π΅Π· Π΅Π³ΠΎ дСскриптор ΠΎΠΊΠ½Π°.

template <class T> inline T

GetWinLong(HWND hwnd, int which = GWL_USERDATA) {

 return reinterpret_cast<T>(::GetWindowLong(hwnd, which));

}


template <class T> inline void

SetWinLong(HWND hwnd, T value, int which = GWL_USERDATA) {