Merge pull request #2152 from anta999/colortest2
[far2l.git] / far2l / src / dialog.cpp
blob1d037aae262dd2ccbecf756ab475fb35ea1b18f2
1 /*
2 dialog.cpp
4 Класс диалога
5 */
6 /*
7 Copyright (c) 1996 Eugene Roshal
8 Copyright (c) 2000 Far Group
9 All rights reserved.
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
13 are met:
14 1. Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in the
18 documentation and/or other materials provided with the distribution.
19 3. The name of the authors may not be used to endorse or promote products
20 derived from this software without specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "headers.hpp"
36 #include "dialog.hpp"
37 #include "lang.hpp"
38 #include "keyboard.hpp"
39 #include "macroopcode.hpp"
40 #include "keys.hpp"
41 #include "ctrlobj.hpp"
42 #include "chgprior.hpp"
43 #include "vmenu.hpp"
44 #include "dlgedit.hpp"
45 #include "help.hpp"
46 #include "scrbuf.hpp"
47 #include "manager.hpp"
48 #include "savescr.hpp"
49 #include "constitle.hpp"
50 #include "lockscrn.hpp"
51 #include "TPreRedrawFunc.hpp"
52 #include "syslog.hpp"
53 #include "interf.hpp"
54 #include "palette.hpp"
55 #include "message.hpp"
56 #include "strmix.hpp"
57 #include "history.hpp"
58 #include "InterThreadCall.hpp"
59 #include <VT256ColorTable.h>
60 #include <cwctype>
61 #include <atomic>
63 #define VTEXT_ADN_SEPARATORS 1
65 // Флаги для функции ConvertItem
66 enum CVTITEMFLAGS
68 CVTITEM_TOPLUGIN = 0,
69 CVTITEM_FROMPLUGIN = 1,
70 CVTITEM_TOPLUGINSHORT = 2,
71 CVTITEM_FROMPLUGINSHORT = 3
74 enum DLGEDITLINEFLAGS
76 DLGEDITLINE_CLEARSELONKILLFOCUS = 0x00000001, // управляет выделением блока при потере фокуса ввода
77 DLGEDITLINE_SELALLGOTFOCUS = 0x00000002, // управляет выделением блока при получении фокуса ввода
78 DLGEDITLINE_NOTSELONGOTFOCUS = 0x00000004, // не восстанавливать выделение строки редактирования при получении фокуса ввода
79 DLGEDITLINE_NEWSELONGOTFOCUS = 0x00000008, // управляет процессом выделения блока при получении фокуса
80 DLGEDITLINE_GOTOEOLGOTFOCUS = 0x00000010, // при получении фокуса ввода переместить курсор в конец строки
83 enum DLGITEMINTERNALFLAGS
85 DLGIIF_LISTREACTIONFOCUS = 0x00000001, // MouseReaction для фокусного элемента
86 DLGIIF_LISTREACTIONNOFOCUS = 0x00000002, // MouseReaction для не фокусного элемента
88 DLGIIF_COMBOBOXNOREDRAWEDIT = 0x00000008, // не прорисовывать строку редактирования при изменениях в комбо
89 DLGIIF_COMBOBOXEVENTKEY = 0x00000010, // посылать события клавиатуры в диалоговую проц. для открытого комбобокса
90 DLGIIF_COMBOBOXEVENTMOUSE = 0x00000020, // посылать события мыши в диалоговую проц. для открытого комбобокса
93 const wchar_t *fmtSavedDialogHistory = L"SavedDialogHistory/";
95 //////////////////////////////////////////////////////////////////////////
97 Функция, определяющая - "Может ли элемент диалога иметь фокус ввода"
99 static inline bool CanGetFocus(int Type)
101 switch (Type) {
102 case DI_EDIT:
103 case DI_FIXEDIT:
104 case DI_PSWEDIT:
105 case DI_COMBOBOX:
106 case DI_BUTTON:
107 case DI_CHECKBOX:
108 case DI_RADIOBUTTON:
109 case DI_LISTBOX:
110 case DI_MEMOEDIT:
111 case DI_USERCONTROL:
112 return true;
113 default:
114 return false;
118 bool IsKeyHighlighted(const wchar_t *Str, FarKey Key, int Translate, int AmpPos)
120 if (AmpPos == -1) {
121 if (!(Str = wcschr(Str, L'&')))
122 return false;
124 AmpPos = 1;
125 } else {
126 if (AmpPos >= StrLength(Str))
127 return false;
129 Str+= AmpPos;
130 AmpPos = 0;
132 if (Str[AmpPos] == L'&')
133 AmpPos++;
136 wchar_t UpperStrKey = Upper(Str[AmpPos]);
138 if (WCHAR_IS_VALID(Key)) {
139 return UpperStrKey == Upper(Key) || (Translate && KeyToKeyLayoutCompare(Upper(Key), UpperStrKey));
142 if (Key & KEY_ALT) {
143 uint32_t AltKey = Key & (~KEY_ALT);
145 if (WCHAR_IS_VALID(AltKey)) {
146 if (iswdigit(AltKey) != 0)
147 return (AltKey == (uint32_t)UpperStrKey);
149 if (AltKey > L' ')
150 // (AltKey=='-' || AltKey=='/' || AltKey==',' || AltKey=='.' ||
151 // AltKey=='\\' || AltKey=='=' || AltKey=='[' || AltKey==']' ||
152 // AltKey==':' || AltKey=='"' || AltKey=='~'))
154 return (UpperStrKey == Upper(AltKey)
155 || (Translate && KeyToKeyLayoutCompare(AltKey, UpperStrKey)));
160 return false;
163 void DialogItemExToDialogItemEx(DialogItemEx *pSrc, DialogItemEx *pDest)
165 pDest->Type = pSrc->Type;
166 pDest->X1 = pSrc->X1;
167 pDest->Y1 = pSrc->Y1;
168 pDest->X2 = pSrc->X2;
169 pDest->Y2 = pSrc->Y2;
170 pDest->Focus = pSrc->Focus;
171 pDest->Reserved = pSrc->Reserved;
172 pDest->strHistory = pSrc->strHistory;
173 pDest->strMask = pSrc->strMask;
174 pDest->Flags = pSrc->Flags;
175 pDest->DefaultButton = pSrc->DefaultButton;
176 pDest->nMaxLength = 0;
177 pDest->strData = pSrc->strData;
178 pDest->ID = pSrc->ID;
179 pDest->IFlags = pSrc->IFlags;
180 pDest->AutoCount = pSrc->AutoCount;
181 pDest->AutoPtr = pSrc->AutoPtr;
182 pDest->UserData = pSrc->UserData;
183 pDest->ObjPtr = pSrc->ObjPtr;
184 pDest->ListPtr = pSrc->ListPtr;
185 pDest->UCData = pSrc->UCData;
186 pDest->SelStart = pSrc->SelStart;
187 pDest->SelEnd = pSrc->SelEnd;
190 void ConvertItemSmall(FarDialogItem *Item, DialogItemEx *Data)
192 Item->Type = Data->Type;
193 Item->X1 = Data->X1;
194 Item->Y1 = Data->Y1;
195 Item->X2 = Data->X2;
196 Item->Y2 = Data->Y2;
197 Item->Focus = Data->Focus;
198 Item->Flags = Data->Flags;
199 Item->DefaultButton = Data->DefaultButton;
200 Item->MaxLen = Data->nMaxLength;
201 Item->PtrData = nullptr;
203 Item->Param.History = nullptr;
204 if (Data->Type == DI_LISTBOX || Data->Type == DI_COMBOBOX) {
205 Item->Param.ListPos = Data->ListPtr ? Data->ListPtr->GetSelectPos() : 0;
207 if ((Data->Type == DI_EDIT || Data->Type == DI_FIXEDIT) && Data->Flags & DIF_HISTORY) {
208 Item->Param.History = Data->strHistory;
209 } else if (Data->Type == DI_FIXEDIT && Data->Flags & DIF_MASKEDIT) {
210 Item->Param.Mask = Data->strMask;
211 } else {
212 Item->Param.Reserved = Data->Reserved;
216 size_t ItemStringAndSize(DialogItemEx *Data, FARString &ItemString)
218 DlgEdit *EditPtr;
219 if (FarIsEdit(Data->Type) && (EditPtr = (DlgEdit *)(Data->ObjPtr)) != nullptr)
220 EditPtr->GetString(ItemString);
221 else
222 ItemString = Data->strData;
224 size_t sz = ItemString.GetLength();
226 if (sz > Data->nMaxLength && Data->nMaxLength > 0)
227 sz = Data->nMaxLength;
229 return sz;
232 bool ConvertItemEx(CVTITEMFLAGS FromPlugin, FarDialogItem *Item, DialogItemEx *Data, unsigned Count)
234 unsigned I;
236 if (!Item || !Data)
237 return false;
239 switch (FromPlugin) {
240 case CVTITEM_TOPLUGIN:
241 case CVTITEM_TOPLUGINSHORT:
243 for (I = 0; I < Count; I++, ++Item, ++Data) {
244 ConvertItemSmall(Item, Data);
246 if (FromPlugin == CVTITEM_TOPLUGIN) {
247 FARString str;
248 size_t sz = ItemStringAndSize(Data, str);
250 wchar_t *p = (wchar_t *)malloc((sz + 1) * sizeof(wchar_t));
251 Item->PtrData = p;
253 if (!p) // TODO: may be needed message?
254 return false;
256 wmemcpy(p, str.CPtr(), sz);
257 p[sz] = L'\0';
262 break;
263 case CVTITEM_FROMPLUGIN:
264 case CVTITEM_FROMPLUGINSHORT:
266 for (I = 0; I < Count; I++, ++Item, ++Data) {
267 Data->X1 = Item->X1;
268 Data->Y1 = Item->Y1;
269 Data->X2 = Item->X2;
270 Data->Y2 = Item->Y2;
271 Data->Focus = Item->Focus;
272 Data->Reserved = 0;
273 if ((Item->Type == DI_EDIT || Item->Type == DI_FIXEDIT) && Item->Flags & DIF_HISTORY) {
274 Data->strHistory = Item->Param.History;
275 } else if (Item->Type == DI_FIXEDIT && Item->Flags & DIF_MASKEDIT) {
276 Data->strMask = Item->Param.Mask;
277 } else {
278 Data->Reserved = Item->Param.Reserved;
280 Data->Flags = Item->Flags;
281 Data->DefaultButton = Item->DefaultButton;
282 Data->Type = Item->Type;
284 if (FromPlugin == CVTITEM_FROMPLUGIN) {
285 Data->strData = Item->PtrData;
286 Data->nMaxLength = Item->MaxLen;
288 if (Data->nMaxLength > 0)
289 Data->strData.Truncate(Data->nMaxLength);
292 Data->ListItems = Item->Param.ListItems;
294 if (Data->X2 < Data->X1)
295 Data->X2 = Data->X1;
297 if (Data->Y2 < Data->Y1)
298 Data->Y2 = Data->Y1;
300 if ((Data->Type == DI_COMBOBOX || Data->Type == DI_LISTBOX) && !IsPtr(Item->Param.ListItems))
301 Data->ListItems = nullptr;
304 break;
307 return true;
310 size_t ConvertItemEx2(FarDialogItem *Item, DialogItemEx *Data)
312 size_t size = sizeof(*Item);
313 FARString str;
314 size_t sz = ItemStringAndSize(Data, str);
315 size+= (sz + 1) * sizeof(wchar_t);
317 if (Item) {
318 ConvertItemSmall(Item, Data);
320 wchar_t *p = (wchar_t *)(Item + 1);
321 Item->PtrData = p;
322 wmemcpy(p, str.CPtr(), sz);
323 p[sz] = L'\0';
326 return size;
329 void DataToItemEx(const DialogDataEx *Data, DialogItemEx *Item, int Count)
331 if (!Item || !Data)
332 return;
334 for (int i = 0; i < Count; i++) {
335 Item[i].Clear();
336 Item[i].ID = static_cast<WORD>(i);
337 Item[i].Type = Data[i].Type;
338 Item[i].X1 = Data[i].X1;
339 Item[i].Y1 = Data[i].Y1;
340 Item[i].X2 = Data[i].X2;
341 Item[i].Y2 = Data[i].Y2;
343 if (Item[i].X2 < Item[i].X1)
344 Item[i].X2 = Item[i].X1;
346 if (Item[i].Y2 < Item[i].Y1)
347 Item[i].Y2 = Item[i].Y1;
349 Item[i].Focus =
350 Item[i].Type != DI_SINGLEBOX && Item[i].Type != DI_DOUBLEBOX && (Data[i].Flags & DIF_FOCUS);
351 if ((Data[i].Type == DI_EDIT || Data[i].Type == DI_FIXEDIT) && Data[i].Flags & DIF_HISTORY) {
352 Item[i].strHistory = Data[i].History;
353 } else if (Data[i].Type == DI_FIXEDIT && Data[i].Flags & DIF_MASKEDIT) {
354 Item[i].strMask = Data[i].Mask;
355 } else {
356 Item[i].Reserved = Data[i].Reserved;
358 Item[i].Flags = Data[i].Flags;
359 Item[i].DefaultButton =
360 Item[i].Type != DI_TEXT && Item[i].Type != DI_VTEXT && (Data[i].Flags & DIF_DEFAULT);
361 Item[i].SelStart = -1;
363 if (!IsPtr(Data[i].Data)) // awful
364 Item[i].strData = FarLangMsg{(int)(DWORD_PTR)Data[i].Data};
365 else
366 Item[i].strData = Data[i].Data;
370 Dialog::Dialog(DialogItemEx *SrcItem, // Набор элементов диалога
371 unsigned SrcItemCount, // Количество элементов
372 FARWINDOWPROC DlgProc, // Диалоговая процедура
373 LONG_PTR InitParam) // Ассоцированные с диалогом данные
375 CMM(MACRO_DIALOG)
377 Dialog::Item = (DialogItemEx **)malloc(sizeof(DialogItemEx *) * SrcItemCount);
379 for (unsigned i = 0; i < SrcItemCount; i++) {
380 Dialog::Item[i] = new DialogItemEx;
381 Dialog::Item[i]->Clear();
382 DialogItemExToDialogItemEx(&SrcItem[i], Dialog::Item[i]);
385 Dialog::ItemCount = SrcItemCount;
386 Dialog::pSaveItemEx = SrcItem;
387 Init(DlgProc, InitParam);
390 Dialog::Dialog(FarDialogItem *SrcItem, // Набор элементов диалога
391 unsigned SrcItemCount, // Количество элементов
392 FARWINDOWPROC DlgProc, // Диалоговая процедура
393 LONG_PTR InitParam) // Ассоцированные с диалогом данные
395 CMM(MACRO_DIALOG)
397 Dialog::Item = (DialogItemEx **)malloc(sizeof(DialogItemEx *) * SrcItemCount);
399 for (unsigned i = 0; i < SrcItemCount; i++) {
400 Dialog::Item[i] = new DialogItemEx;
401 Dialog::Item[i]->Clear();
402 // BUGBUG add error check
403 ConvertItemEx(CVTITEM_FROMPLUGIN, &SrcItem[i], Dialog::Item[i], 1);
406 Dialog::ItemCount = SrcItemCount;
407 Dialog::pSaveItemEx = nullptr;
408 Init(DlgProc, InitParam);
411 void Dialog::Init(FARWINDOWPROC DlgProc, // Диалоговая процедура
412 LONG_PTR InitParam) // Ассоцированные с диалогом данные
414 SetDynamicallyBorn(FALSE); // $OT: По умолчанию все диалоги создаются статически
415 CanLoseFocus = FALSE;
416 HelpTopic = nullptr;
417 // Номер плагина, вызвавшего диалог (-1 = Main)
418 PluginNumber = -1;
419 Dialog::DataDialog = InitParam;
420 DialogMode.Set(DMODE_ISCANMOVE);
421 SetDropDownOpened(FALSE);
422 IsEnableRedraw = 0;
423 InCtlColorDlgItem = 0;
424 FocusPos = (unsigned)-1;
425 PrevFocusPos = (unsigned)-1;
427 if (!DlgProc) // функция должна быть всегда!!!
429 DlgProc = DefDlgProc;
430 // знать диалог в старом стиле - учтем этот факт!
431 DialogMode.Set(DMODE_OLDSTYLE);
434 Dialog::RealDlgProc = DlgProc;
436 //_SVS(SysLog(L"Dialog =%d",CtrlObject->Macro.GetMode()));
437 // запоминаем предыдущий заголовок консоли
438 OldTitle = new ConsoleTitle;
439 IdExist = false;
440 memset(&Id, 0, sizeof(Id));
443 //////////////////////////////////////////////////////////////////////////
445 Public, Virtual:
446 Деструктор класса Dialog
448 Dialog::~Dialog()
450 _tran(SysLog(L"[%p] Dialog::~Dialog()", this));
452 DeleteDialogObjects();
454 Hide();
455 ScrBuf.Flush();
457 if (HelpTopic)
458 delete[] HelpTopic;
460 for (unsigned i = 0; i < ItemCount; i++)
461 delete Item[i];
463 free(Item);
464 delete OldTitle;
466 if (!WinPortTesting()) {
467 INPUT_RECORD rec;
468 PeekInputRecord(&rec);
471 _DIALOG(CleverSysLog CL(L"Destroy Dialog"));
474 void Dialog::CheckDialogCoord()
476 CriticalSectionLock Lock(CS);
478 if (X1 == -1) // задано центрирование диалога по горизонтали?
479 { // X2 при этом = ширине диалога.
480 X1 = (ScrX - X2 + 1) / 2;
482 if (X1 < 0) // ширина диалога больше ширины экрана?
484 X1 = 0;
485 } else {
486 X2+= X1 - 1;
490 if (Y1 == -1) // задано центрирование диалога по вертикали?
491 { // Y2 при этом = высоте диалога.
492 Y1 = (ScrY - Y2 + 1) / 2;
494 if (!DialogMode.Check(DMODE_SMALLDIALOG)) //????
495 if (Y1 > 5)
496 Y1--;
498 if (Y1 < 0) {
499 Y1 = 0;
500 } else {
501 Y2+= Y1 - 1;
506 void Dialog::InitDialog()
508 CriticalSectionLock Lock(CS);
510 if (!DialogMode.Check(DMODE_INITOBJECTS)) // самодостаточный вариант, когда
511 { // элементы инициализируются при первом вызове.
512 CheckDialogCoord();
513 unsigned InitFocus = InitDialogObjects();
514 int Result = (int)DlgProc((HANDLE)this, DN_INITDIALOG, InitFocus, DataDialog);
516 if (ExitCode == -1) {
517 if (Result) {
518 // еще разок, т.к. данные могли быть изменены
519 InitFocus = InitDialogObjects(); // InitFocus=????
522 if (!DialogMode.Check(DMODE_KEEPCONSOLETITLE))
523 ConsoleTitle::SetFarTitle(GetDialogTitle());
526 // все объекты проинициализированы!
527 DialogMode.Set(DMODE_INITOBJECTS);
528 DialogInfo di = {sizeof(di)};
530 if (DlgProc(reinterpret_cast<HANDLE>(this), DN_GETDIALOGINFO, 0, reinterpret_cast<LONG_PTR>(&di))) {
531 Id = di.Id;
532 IdExist = true;
535 DlgProc((HANDLE)this, DN_GOTFOCUS, InitFocus, 0);
539 //////////////////////////////////////////////////////////////////////////
541 Public, Virtual:
542 Расчет значений координат окна диалога и вызов функции
543 ScreenObject::Show() для вывода диалога на экран.
545 void Dialog::Show()
547 CriticalSectionLock Lock(CS);
548 _tran(SysLog(L"[%p] Dialog::Show()", this));
550 if (!DialogMode.Check(DMODE_INITOBJECTS))
551 return;
553 if (!Locked() && DialogMode.Check(DMODE_RESIZED)) {
554 PreRedrawItem preRedrawItem = PreRedraw.Peek();
556 if (preRedrawItem.PreRedrawFunc)
557 preRedrawItem.PreRedrawFunc();
560 DialogMode.Clear(DMODE_RESIZED);
562 if (Locked())
563 return;
565 DialogMode.Set(DMODE_SHOW);
566 ScreenObject::Show();
569 // Цель перехвата данной функции - управление видимостью...
570 void Dialog::Hide()
572 CriticalSectionLock Lock(CS);
573 _tran(SysLog(L"[%p] Dialog::Hide()", this));
575 if (!DialogMode.Check(DMODE_INITOBJECTS))
576 return;
578 DialogMode.Clear(DMODE_SHOW);
579 ScreenObject::Hide();
582 //////////////////////////////////////////////////////////////////////////
584 Private, Virtual:
585 Инициализация объектов и вывод диалога на экран.
587 void Dialog::DisplayObject()
589 CriticalSectionLock Lock(CS);
591 if (DialogMode.Check(DMODE_SHOW)) {
592 ChangePriority ChPriority(ChangePriority::NORMAL);
593 ShowDialog(); // "нарисуем" диалог
597 // пересчитать координаты для элементов с DIF_CENTERGROUP
598 void Dialog::ProcessCenterGroup()
600 CriticalSectionLock Lock(CS);
602 for (unsigned I = 0; I < ItemCount; I++) {
604 Последовательно объявленные элементы с флагом DIF_CENTERGROUP
605 и одинаковой вертикальной позицией будут отцентрированы в диалоге.
606 Их координаты X не важны. Удобно использовать для центрирования
607 групп кнопок.
609 if ((Item[I]->Flags & DIF_CENTERGROUP)
610 && (I == 0 || (Item[I - 1]->Flags & DIF_CENTERGROUP) == 0
611 || Item[I - 1]->Y1 != Item[I]->Y1)) {
612 int Length = 0;
614 for (UINT J = I;
615 J < ItemCount && (Item[J]->Flags & DIF_CENTERGROUP) && Item[J]->Y1 == Item[I]->Y1; J++) {
616 Length+= LenStrItem(J);
618 if (!Item[J]->strData.IsEmpty())
619 switch (Item[J]->Type) {
620 case DI_BUTTON:
621 Length++;
622 break;
623 case DI_CHECKBOX:
624 case DI_RADIOBUTTON:
625 Length+= 5;
626 break;
630 if (!Item[I]->strData.IsEmpty())
631 switch (Item[I]->Type) {
632 case DI_BUTTON:
633 Length--;
634 break;
635 case DI_CHECKBOX:
636 case DI_RADIOBUTTON:
637 // Length-=5;
638 break;
639 } // Бля, це ж ботва какая-то
641 int StartX = Max(0, (X2 - X1 + 1 - Length) / 2);
643 for (UINT J = I;
644 J < ItemCount && (Item[J]->Flags & DIF_CENTERGROUP) && Item[J]->Y1 == Item[I]->Y1; J++) {
645 Item[J]->X1 = StartX;
646 StartX+= LenStrItem(J);
648 if (!Item[J]->strData.IsEmpty())
649 switch (Item[J]->Type) {
650 case DI_BUTTON:
651 StartX++;
652 break;
653 case DI_CHECKBOX:
654 case DI_RADIOBUTTON:
655 StartX+= 5;
656 break;
659 if (StartX == Item[J]->X1)
660 Item[J]->X2 = StartX;
661 else
662 Item[J]->X2 = StartX - 1;
668 //////////////////////////////////////////////////////////////////////////
670 Public:
671 Инициализация элементов диалога.
673 InitDialogObjects возвращает ID элемента с фокусом ввода
674 Параметр - для выборочной реинициализации элементов. ID = -1 - касаемо всех объектов
677 TODO: Необходимо применить ProcessRadioButton для исправления
678 кривых рук некоторых плагинописателей (а надо?)
680 unsigned Dialog::InitDialogObjects(unsigned ID)
682 CriticalSectionLock Lock(CS);
683 unsigned I, J;
684 int Type;
685 DialogItemEx *CurItem;
686 unsigned InitItemCount;
687 DWORD ItemFlags;
688 _DIALOG(CleverSysLog CL(L"Init Dialog"));
690 if (ID == (unsigned)-1) // инициализируем все?
692 ID = 0;
693 InitItemCount = ItemCount;
694 } else if (ID + 1 > ItemCount) {
695 return (unsigned)-1;
696 } else {
697 InitItemCount = ID + 1;
700 // если FocusPos в пределах и элемент задисаблен, то ищем сначала
701 if (FocusPos != (unsigned)-1 && FocusPos < ItemCount
702 && (Item[FocusPos]->Flags & (DIF_DISABLE | DIF_NOFOCUS | DIF_HIDDEN)))
703 FocusPos = (unsigned)-1; // будем искать сначала!
705 // предварительный цикл по поводу кнопок
706 for (I = ID; I < InitItemCount; I++) {
707 CurItem = Item[I];
708 ItemFlags = CurItem->Flags;
709 Type = CurItem->Type;
711 if (Type == DI_BUTTON && ItemFlags & DIF_SETSHIELD) {
712 CurItem->strData = FARString(L"\x2580\x2584 ") + CurItem->strData;
716 для кнопок не имеющи стиля "Показывает заголовок кнопки без скобок"
717 добавим энти самые скобки
719 if (Type == DI_BUTTON && !(ItemFlags & DIF_NOBRACKETS)) {
720 LPCWSTR Brackets[] = {L"[ ", L" ]", L"{ ", L" }"};
721 int Start = (CurItem->DefaultButton ? 2 : 0);
722 if (CurItem->strData.At(0) != *Brackets[Start]) {
723 CurItem->strData = Brackets[Start] + CurItem->strData + Brackets[Start + 1];
726 // предварительный поик фокуса
727 if (FocusPos == (unsigned)-1 && CanGetFocus(Type) && CurItem->Focus
728 && !(ItemFlags & (DIF_DISABLE | DIF_NOFOCUS | DIF_HIDDEN)))
729 FocusPos = I; // запомним первый фокусный элемент
731 CurItem->Focus = 0; // сбросим для всех, чтобы не оказалось,
732 // что фокусов - как у дурочка фантиков
734 // сбросим флаг DIF_CENTERGROUP для редакторов
735 switch (Type) {
736 case DI_BUTTON:
737 case DI_CHECKBOX:
738 case DI_RADIOBUTTON:
739 case DI_TEXT:
740 case DI_VTEXT: // ????
741 break;
742 default:
744 if (ItemFlags & DIF_CENTERGROUP)
745 CurItem->Flags&= ~DIF_CENTERGROUP;
750 Опять про фокус ввода - теперь, если "чудо" забыло выставить
751 хотя бы один, то ставим на первый подходящий
753 if (FocusPos == (unsigned)-1) {
754 for (I = 0; I < ItemCount; I++) // по всем!!!!
756 CurItem = Item[I];
758 if (CanGetFocus(CurItem->Type) && !(CurItem->Flags & (DIF_DISABLE | DIF_NOFOCUS | DIF_HIDDEN))) {
759 FocusPos = I;
760 break;
765 if (FocusPos == (unsigned)-1) // ну ни хрена себе - нет ни одного
766 { // элемента с возможностью фокуса
767 FocusPos = 0; // убится, блин
770 // ну вот и добрались до!
771 Item[FocusPos]->Focus = 1;
772 // а теперь все сначала и по полной программе...
773 ProcessCenterGroup(); // сначала отцентрируем
775 for (I = ID; I < InitItemCount; I++) {
776 CurItem = Item[I];
777 Type = CurItem->Type;
778 ItemFlags = CurItem->Flags;
780 if (Type == DI_LISTBOX) {
781 if (!DialogMode.Check(DMODE_CREATEOBJECTS)) {
782 CurItem->ListPtr = new VMenu(nullptr, nullptr, 0, CurItem->Y2 - CurItem->Y1 + 1,
783 VMENU_ALWAYSSCROLLBAR | VMENU_LISTBOX, nullptr, this);
786 if (CurItem->ListPtr) {
787 VMenu *ListPtr = CurItem->ListPtr;
788 ListPtr->SetVDialogItemID(I);
790 $ 13.09.2000 SVS
791 + Флаг DIF_LISTNOAMPERSAND. По умолчанию для DI_LISTBOX &
792 DI_COMBOBOX выставляется флаг MENU_SHOWAMPERSAND. Этот флаг
793 подавляет такое поведение
795 CurItem->IFlags.Set(DLGIIF_LISTREACTIONFOCUS | DLGIIF_LISTREACTIONNOFOCUS); // всегда!
796 ListPtr->ChangeFlags(VMENU_DISABLED, ItemFlags & DIF_DISABLE);
797 ListPtr->ChangeFlags(VMENU_SHOWAMPERSAND, !(ItemFlags & DIF_LISTNOAMPERSAND));
798 ListPtr->ChangeFlags(VMENU_SHOWNOBOX, ItemFlags & DIF_LISTNOBOX);
799 ListPtr->ChangeFlags(VMENU_WRAPMODE, ItemFlags & DIF_LISTWRAPMODE);
800 ListPtr->ChangeFlags(VMENU_AUTOHIGHLIGHT, ItemFlags & DIF_LISTAUTOHIGHLIGHT);
802 if (ItemFlags & DIF_LISTAUTOHIGHLIGHT)
803 ListPtr->AssignHighlights(FALSE);
805 ListPtr->SetDialogStyle(DialogMode.Check(DMODE_WARNINGSTYLE));
806 ListPtr->SetPosition(X1 + CurItem->X1, Y1 + CurItem->Y1, X1 + CurItem->X2, Y1 + CurItem->Y2);
807 ListPtr->SetBoxType(SHORT_SINGLE_BOX);
809 // поле FarDialogItem.Data для DI_LISTBOX используется как верхний заголовок листа
810 if (!(ItemFlags & DIF_LISTNOBOX) && !DialogMode.Check(DMODE_CREATEOBJECTS)) {
811 ListPtr->SetTitle(CurItem->strData);
814 // удалим все итемы
815 // ListBox->DeleteItems(); //???? А НАДО ЛИ ????
816 if (CurItem->ListItems && !DialogMode.Check(DMODE_CREATEOBJECTS)) {
817 ListPtr->AddItem(CurItem->ListItems);
820 ListPtr->ChangeFlags(VMENU_LISTHASFOCUS, CurItem->Focus);
823 // "редакторы" - разговор особый...
824 else if (FarIsEdit(Type)) {
826 сбросим флаг DIF_EDITOR для строки ввода, отличной от DI_EDIT,
827 DI_FIXEDIT и DI_PSWEDIT
829 if (Type != DI_COMBOBOX)
830 if ((ItemFlags & DIF_EDITOR) && Type != DI_EDIT && Type != DI_FIXEDIT && Type != DI_PSWEDIT)
831 ItemFlags&= ~DIF_EDITOR;
833 if (!DialogMode.Check(DMODE_CREATEOBJECTS)) {
834 CurItem->ObjPtr =
835 new DlgEdit(this, I, Type == DI_MEMOEDIT ? DLGEDIT_MULTILINE : DLGEDIT_SINGLELINE);
837 if (Type == DI_COMBOBOX) {
838 CurItem->ListPtr = new VMenu(L"", nullptr, 0, Opt.Dialogs.CBoxMaxHeight,
839 VMENU_ALWAYSSCROLLBAR | VMENU_NOTCHANGE, nullptr, this);
840 CurItem->ListPtr->SetVDialogItemID(I);
843 CurItem->SelStart = -1;
846 DlgEdit *DialogEdit = (DlgEdit *)CurItem->ObjPtr;
847 // Mantis#58 - символ-маска с кодом 0х0А - пропадает
848 // DialogEdit->SetDialogParent((Type != DI_COMBOBOX && (ItemFlags & DIF_EDITOR) || (CurItem->Type==DI_PSWEDIT || CurItem->Type==DI_FIXEDIT))?
849 // FEDITLINE_PARENT_SINGLELINE:FEDITLINE_PARENT_MULTILINE);
850 DialogEdit->SetDialogParent(
851 Type == DI_MEMOEDIT ? FEDITLINE_PARENT_MULTILINE : FEDITLINE_PARENT_SINGLELINE);
852 DialogEdit->SetReadOnly(0);
854 if (Type == DI_COMBOBOX) {
855 if (CurItem->ListPtr) {
856 VMenu *ListPtr = CurItem->ListPtr;
857 ListPtr->SetBoxType(SHORT_SINGLE_BOX);
858 DialogEdit->SetDropDownBox(ItemFlags & DIF_DROPDOWNLIST);
859 ListPtr->ChangeFlags(VMENU_WRAPMODE, ItemFlags & DIF_LISTWRAPMODE);
860 ListPtr->ChangeFlags(VMENU_DISABLED, ItemFlags & DIF_DISABLE);
861 ListPtr->ChangeFlags(VMENU_SHOWAMPERSAND, !(ItemFlags & DIF_LISTNOAMPERSAND));
862 ListPtr->ChangeFlags(VMENU_AUTOHIGHLIGHT, ItemFlags & DIF_LISTAUTOHIGHLIGHT);
864 if (ItemFlags & DIF_LISTAUTOHIGHLIGHT)
865 ListPtr->AssignHighlights(FALSE);
867 if (CurItem->ListItems && !DialogMode.Check(DMODE_CREATEOBJECTS))
868 ListPtr->AddItem(CurItem->ListItems);
870 ListPtr->SetFlags(VMENU_COMBOBOX);
871 ListPtr->SetDialogStyle(DialogMode.Check(DMODE_WARNINGSTYLE));
876 $ 15.10.2000 tran
877 строка редакторирование должна иметь максимум в 511 символов
878 выставляем максимальный размер в том случае, если он еще не выставлен
881 // BUGBUG
882 if (DialogEdit->GetMaxLength() == -1)
883 DialogEdit->SetMaxLength(CurItem->nMaxLength ? (int)CurItem->nMaxLength : -1);
885 DialogEdit->SetPosition(X1 + CurItem->X1, Y1 + CurItem->Y1, X1 + CurItem->X2, Y1 + CurItem->Y2);
888 DialogEdit->SetObjectColor(
889 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE) ?
890 ((ItemFlags&DIF_DISABLE)?COL_WARNDIALOGEDITDISABLED:COL_WARNDIALOGEDIT):
891 ((ItemFlags&DIF_DISABLE)?COL_DIALOGEDITDISABLED:COL_DIALOGEDIT)),
892 FarColorToReal((ItemFlags&DIF_DISABLE)?COL_DIALOGEDITDISABLED:COL_DIALOGEDITSELECTED)
895 if (CurItem->Type == DI_PSWEDIT) {
896 DialogEdit->SetPasswordMode(TRUE);
897 // ...Что бы небыло повадно... и для повыщения защиты, т.с.
898 ItemFlags&= ~DIF_HISTORY;
901 if (Type == DI_FIXEDIT) {
902 // DIF_HISTORY имеет более высокий приоритет, чем DIF_MASKEDIT
903 if (ItemFlags & DIF_HISTORY)
904 ItemFlags&= ~DIF_MASKEDIT;
907 если DI_FIXEDIT, то курсор сразу ставится на замену...
908 ай-ай - было недокументированно :-)
910 DialogEdit->SetMaxLength(CurItem->X2 - CurItem->X1 + 1
911 + (CurItem->X2 == CurItem->X1 || !(ItemFlags & DIF_HISTORY) ? 0 : 1));
912 DialogEdit->SetOvertypeMode(TRUE);
914 $ 12.08.2000 KM
915 Если тип строки ввода DI_FIXEDIT и установлен флаг DIF_MASKEDIT
916 и непустой параметр CurItem->Mask, то вызываем новую функцию
917 для установки маски в объект DlgEdit.
920 // Маска не должна быть пустой (строка из пробелов не учитывается)!
921 if ((ItemFlags & DIF_MASKEDIT) && !CurItem->strMask.IsEmpty()) {
922 RemoveExternalSpaces(CurItem->strMask);
923 if (!CurItem->strMask.IsEmpty()) {
924 DialogEdit->SetInputMask(CurItem->strMask);
925 } else {
926 ItemFlags&= ~DIF_MASKEDIT;
929 } else
932 "мини-редактор"
933 Последовательно определенные поля ввода (edit controls),
934 имеющие этот флаг группируются в редактор с возможностью
935 вставки и удаления строк
937 if (!(ItemFlags & DIF_EDITOR) && CurItem->Type != DI_COMBOBOX) {
938 DialogEdit->SetEditBeyondEnd(FALSE);
940 if (!DialogMode.Check(DMODE_INITOBJECTS))
941 DialogEdit->SetClearFlag(1);
944 if (CurItem->Type == DI_COMBOBOX)
945 DialogEdit->SetClearFlag(1);
948 $ 01.08.2000 SVS
949 Еже ли стоит флаг DIF_USELASTHISTORY и непустая строка ввода,
950 то подстанавливаем первое значение из History
952 if (CurItem->Type == DI_EDIT
953 && (ItemFlags & (DIF_HISTORY | DIF_USELASTHISTORY))
954 == (DIF_HISTORY | DIF_USELASTHISTORY)) {
955 ProcessLastHistory(CurItem, -1);
958 if ((ItemFlags & DIF_MANUALADDHISTORY) && !(ItemFlags & DIF_HISTORY))
959 ItemFlags&= ~DIF_MANUALADDHISTORY; // сбросим нафиг.
962 $ 18.03.2000 SVS
963 Если это ComBoBox и данные не установлены, то берем из списка
964 при условии, что хоть один из пунктов имеет Selected
967 if (Type == DI_COMBOBOX && CurItem->strData.IsEmpty() && CurItem->ListItems) {
968 FarListItem *ListItems = CurItem->ListItems->Items;
969 unsigned Length = CurItem->ListItems->ItemsNumber;
970 // CurItem->ListPtr->AddItem(CurItem->ListItems);
972 for (J = 0; J < Length; J++) {
973 if (ListItems[J].Flags & LIF_SELECTED) {
974 if (ItemFlags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND))
975 HiText2Str(CurItem->strData, ListItems[J].Text);
976 else
977 CurItem->strData = ListItems[J].Text;
979 break;
984 DialogEdit->SetCallbackState(false);
985 DialogEdit->SetString(CurItem->strData);
986 DialogEdit->SetCallbackState(true);
988 if (Type == DI_FIXEDIT)
989 DialogEdit->SetCurPos(0);
991 // Для обычных строк отрубим постоянные блоки
992 if (!(ItemFlags & DIF_EDITOR))
993 DialogEdit->SetPersistentBlocks(Opt.Dialogs.EditBlock);
995 DialogEdit->SetDelRemovesBlocks(Opt.Dialogs.DelRemovesBlocks);
997 if (ItemFlags & DIF_READONLY)
998 DialogEdit->SetReadOnly(1);
999 } else if (Type == DI_USERCONTROL) {
1000 if (!DialogMode.Check(DMODE_CREATEOBJECTS))
1001 CurItem->UCData = new DlgUserControl;
1004 CurItem->Flags = ItemFlags;
1007 // если будет редактор, то обязательно будет выделен.
1008 SelectOnEntry(FocusPos, TRUE);
1009 // все объекты созданы!
1010 DialogMode.Set(DMODE_CREATEOBJECTS);
1011 return FocusPos;
1014 const wchar_t *Dialog::GetDialogTitle()
1016 CriticalSectionLock Lock(CS);
1017 DialogItemEx *CurItem, *CurItemList = nullptr;
1019 for (unsigned I = 0; I < ItemCount; I++) {
1020 CurItem = Item[I];
1022 // по первому попавшемуся "тексту" установим заголовок консоли!
1023 if ((CurItem->Type == DI_TEXT || CurItem->Type == DI_DOUBLEBOX || CurItem->Type == DI_SINGLEBOX)) {
1024 const wchar_t *Ptr = CurItem->strData;
1026 for (; *Ptr; Ptr++)
1027 if (IsAlpha(*Ptr) || iswdigit(*Ptr))
1028 return (Ptr);
1029 } else if (CurItem->Type == DI_LISTBOX && !I)
1030 CurItemList = CurItem;
1033 if (CurItemList) {
1034 return CurItemList->ListPtr->GetPtrTitle();
1037 return nullptr; //""
1040 void Dialog::ProcessLastHistory(DialogItemEx *CurItem, int MsgIndex)
1042 CriticalSectionLock Lock(CS);
1043 FARString &strData = CurItem->strData;
1045 if (strData.IsEmpty()) {
1046 FARString strRegKey = fmtSavedDialogHistory;
1047 strRegKey+= CurItem->strHistory;
1048 History::ReadLastItem(strRegKey.GetMB().c_str(), strData);
1050 if (MsgIndex != -1) {
1051 // обработка DM_SETHISTORY => надо пропустить изменение текста через
1052 // диалоговую функцию
1053 FarDialogItemData IData;
1054 IData.PtrData = const_cast<wchar_t *>(strData.CPtr());
1055 IData.PtrLength = (int)strData.GetLength();
1056 SendDlgMessage(this, DM_SETTEXT, MsgIndex, (LONG_PTR)&IData);
1062 static int ToRange(int Val, int Min, int Max)
1064 return std::min(std::max(Val, Min), Max);
1067 // Изменение координат и/или размеров итема диалога.
1068 BOOL Dialog::SetItemRect(unsigned ID, SMALL_RECT *aRect)
1070 CriticalSectionLock Lock(CS);
1072 if (ID >= ItemCount)
1073 return FALSE;
1076 auto Rect = *aRect;
1077 Rect.Left = ToRange(Rect.Left, 0, X2-X1);
1078 Rect.Top = ToRange(Rect.Top, 0, Y2-Y1);
1079 Rect.Right = ToRange(Rect.Right, Rect.Left, X2-X1);
1080 Rect.Bottom = ToRange(Rect.Bottom, Rect.Top, Y2-Y1);
1082 DialogItemEx *CurItem = Item[ID];
1083 int Type = CurItem->Type;
1084 CurItem->X1 = Rect.Left;
1085 CurItem->Y1 = (Rect.Top < 0) ? 0 : Rect.Top;
1087 if (FarIsEdit(Type)) {
1088 DlgEdit *DialogEdit = (DlgEdit *)CurItem->ObjPtr;
1089 CurItem->X2 = Rect.Right;
1090 CurItem->Y2 = (Type == DI_MEMOEDIT ? Rect.Bottom : 0);
1091 DialogEdit->SetPosition(X1 + Rect.Left, Y1 + Rect.Top, X1 + Rect.Right, Y1 + Rect.Top);
1092 } else if (Type == DI_LISTBOX) {
1093 CurItem->X2 = Rect.Right;
1094 CurItem->Y2 = Rect.Bottom;
1095 CurItem->ListPtr->SetPosition(X1 + Rect.Left, Y1 + Rect.Top, X1 + Rect.Right, Y1 + Rect.Bottom);
1096 CurItem->ListPtr->SetMaxHeight(CurItem->Y2 - CurItem->Y1 + 1);
1099 switch (Type) {
1100 case DI_TEXT:
1101 CurItem->X2 = Rect.Right;
1102 CurItem->Y2 = 0; // ???
1103 break;
1104 case DI_VTEXT:
1105 CurItem->X2 = 0; // ???
1106 CurItem->Y2 = Rect.Bottom;
1107 case DI_DOUBLEBOX:
1108 case DI_SINGLEBOX:
1109 case DI_USERCONTROL:
1110 CurItem->X2 = Rect.Right;
1111 CurItem->Y2 = Rect.Bottom;
1112 break;
1115 if (DialogMode.Check(DMODE_SHOW)) {
1116 ShowDialog((unsigned)-1);
1117 ScrBuf.Flush();
1120 return TRUE;
1123 BOOL Dialog::GetItemRect(unsigned I, SMALL_RECT &Rect)
1125 CriticalSectionLock Lock(CS);
1127 if (I >= ItemCount)
1128 return FALSE;
1130 DialogItemEx *CurItem = Item[I];
1131 DWORD ItemFlags = CurItem->Flags;
1132 int Type = CurItem->Type;
1133 int Len = 0;
1134 Rect.Left = CurItem->X1;
1135 Rect.Top = CurItem->Y1;
1136 Rect.Right = CurItem->X2;
1137 Rect.Bottom = CurItem->Y2;
1139 switch (Type) {
1140 case DI_COMBOBOX:
1141 case DI_EDIT:
1142 case DI_FIXEDIT:
1143 case DI_PSWEDIT:
1144 case DI_LISTBOX:
1145 case DI_MEMOEDIT:
1146 break;
1147 default:
1148 Len = ((ItemFlags & DIF_SHOWAMPERSAND)
1149 ? (int)CurItem->strData.CellsCount()
1150 : HiStrCellsCount(CurItem->strData));
1151 break;
1154 switch (Type) {
1155 case DI_TEXT:
1157 if (CurItem->X1 == -1)
1158 Rect.Left = (X2 - X1 + 1 - Len) / 2;
1160 if (Rect.Left < 0)
1161 Rect.Left = 0;
1163 if (CurItem->Y1 == -1)
1164 Rect.Top = (Y2 - Y1 + 1) / 2;
1166 if (Rect.Top < 0)
1167 Rect.Top = 0;
1169 Rect.Bottom = Rect.Top;
1171 if (!Rect.Right || Rect.Right == Rect.Left)
1172 Rect.Right = Rect.Left + Len - (Len ? 1 : 0);
1174 if (ItemFlags & (DIF_SEPARATOR | DIF_SEPARATOR2)) {
1175 Rect.Bottom = Rect.Top;
1176 Rect.Left = (!DialogMode.Check(DMODE_SMALLDIALOG) ? 3 : 0); //???
1177 Rect.Right = X2 - X1 - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 5 : 0); //???
1180 break;
1181 case DI_VTEXT:
1183 if (CurItem->X1 == -1)
1184 Rect.Left = (X2 - X1 + 1) / 2;
1186 if (Rect.Left < 0)
1187 Rect.Left = 0;
1189 if (CurItem->Y1 == -1)
1190 Rect.Top = (Y2 - Y1 + 1 - Len) / 2;
1192 if (Rect.Top < 0)
1193 Rect.Top = 0;
1195 Rect.Right = Rect.Left;
1197 // Rect.bottom=Rect.top+Len;
1198 if (!Rect.Bottom || Rect.Bottom == Rect.Top)
1199 Rect.Bottom = Rect.Top + Len - (Len ? 1 : 0);
1201 #if defined(VTEXT_ADN_SEPARATORS)
1203 if (ItemFlags & (DIF_SEPARATOR | DIF_SEPARATOR2)) {
1204 Rect.Right = Rect.Left;
1205 Rect.Top = (!DialogMode.Check(DMODE_SMALLDIALOG) ? 1 : 0); //???
1206 Rect.Bottom = Y2 - Y1 - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 3 : 0); //???
1207 break;
1210 #endif
1211 break;
1212 case DI_BUTTON:
1213 Rect.Bottom = Rect.Top;
1214 Rect.Right = Rect.Left + Len;
1215 break;
1216 case DI_CHECKBOX:
1217 case DI_RADIOBUTTON:
1218 Rect.Bottom = Rect.Top;
1219 Rect.Right = Rect.Left + Len + ((Type == DI_CHECKBOX) ? 4 : (ItemFlags & DIF_MOVESELECT ? 3 : 4));
1220 break;
1221 case DI_COMBOBOX:
1222 case DI_EDIT:
1223 case DI_FIXEDIT:
1224 case DI_PSWEDIT:
1225 Rect.Bottom = Rect.Top;
1226 break;
1229 return TRUE;
1232 bool Dialog::ItemHasDropDownArrow(const DialogItemEx *Item)
1234 return ((!Item->strHistory.IsEmpty() && (Item->Flags & DIF_HISTORY) && Opt.Dialogs.EditHistory)
1235 || (Item->Type == DI_COMBOBOX && Item->ListPtr && Item->ListPtr->GetItemCount() > 0));
1238 //////////////////////////////////////////////////////////////////////////
1240 Private:
1241 Получение данных и удаление "редакторов"
1243 void Dialog::DeleteDialogObjects()
1245 CriticalSectionLock Lock(CS);
1246 DialogItemEx *CurItem;
1248 for (unsigned I = 0; I < ItemCount; I++) {
1249 CurItem = Item[I];
1251 switch (CurItem->Type) {
1252 case DI_EDIT:
1253 case DI_FIXEDIT:
1254 case DI_PSWEDIT:
1255 case DI_COMBOBOX:
1256 case DI_MEMOEDIT:
1258 if (CurItem->ObjPtr)
1259 delete (DlgEdit *)(CurItem->ObjPtr);
1261 case DI_LISTBOX:
1263 if ((CurItem->Type == DI_COMBOBOX || CurItem->Type == DI_LISTBOX) && CurItem->ListPtr)
1264 delete CurItem->ListPtr;
1266 break;
1267 case DI_USERCONTROL:
1269 if (CurItem->UCData)
1270 delete CurItem->UCData;
1272 break;
1275 if (CurItem->Flags & DIF_AUTOMATION)
1276 if (CurItem->AutoPtr)
1277 free(CurItem->AutoPtr);
1281 //////////////////////////////////////////////////////////////////////////
1283 Public:
1284 Сохраняет значение из полей редактирования.
1285 При установленном флаге DIF_HISTORY, сохраняет данные в реестре.
1287 void Dialog::GetDialogObjectsData()
1289 CriticalSectionLock Lock(CS);
1290 int Type;
1291 DialogItemEx *CurItem;
1293 for (unsigned I = 0; I < ItemCount; I++) {
1294 CurItem = Item[I];
1295 DWORD IFlags = CurItem->Flags;
1297 switch (Type = CurItem->Type) {
1298 case DI_MEMOEDIT:
1299 break; //????
1300 case DI_EDIT:
1301 case DI_FIXEDIT:
1302 case DI_PSWEDIT:
1303 case DI_COMBOBOX: {
1304 if (CurItem->ObjPtr) {
1305 FARString strData;
1306 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
1309 подготовим данные
1310 получим данные
1312 EditPtr->GetString(strData);
1314 if (ExitCode >= 0 && (IFlags & DIF_HISTORY) && !(IFlags & DIF_MANUALADDHISTORY) && // при мануале не добавляем
1315 !CurItem->strHistory.IsEmpty() && Opt.Dialogs.EditHistory) {
1316 AddToEditHistory(strData, CurItem->strHistory);
1320 $ 01.08.2000 SVS
1321 ! В History должно заносится значение (для DIF_EXPAND...) перед
1322 расширением среды!
1326 $ 05.07.2000 SVS $
1327 Проверка - этот элемент предполагает расширение переменных среды?
1328 т.к. функция GetDialogObjectsData() может вызываться самостоятельно
1329 Но надо проверить!
1333 $ 04.12.2000 SVS
1334 ! Для DI_PSWEDIT и DI_FIXEDIT обработка DIF_EDITEXPAND не нужна
1335 (DI_FIXEDIT допускается для случая если нету маски)
1338 if ((IFlags & DIF_EDITEXPAND) && Type != DI_PSWEDIT && Type != DI_FIXEDIT) {
1339 apiExpandEnvironmentStrings(strData, strData);
1340 // как бы грязный хак, нам нужно обновить строку чтоб отдавалась правильная строка
1341 // для различных DM_* после закрытия диалога, но ни в коем случае нельзя чтоб
1342 // высылался DN_EDITCHANGE для этого изменения, ибо диалог уже закрыт.
1343 EditPtr->SetCallbackState(false);
1344 EditPtr->SetString(strData);
1345 EditPtr->SetCallbackState(true);
1348 CurItem->strData = strData;
1351 break;
1353 case DI_LISTBOX:
1355 if(CurItem->ListPtr)
1357 CurItem->ListPos=CurItem->ListPtr->GetSelectPos();
1358 break;
1361 break;
1364 #if 0
1366 if ((Type == DI_COMBOBOX || Type == DI_LISTBOX) && CurItem->ListPtr && CurItem->ListItems && DlgProc == DefDlgProc)
1368 int ListPos=CurItem->ListPtr->GetSelectPos();
1370 if (ListPos < CurItem->ListItems->ItemsNumber)
1372 for (int J=0; J < CurItem->ListItems->ItemsNumber; ++J)
1373 CurItem->ListItems->Items[J].Flags&=~LIF_SELECTED;
1375 CurItem->ListItems->Items[ListPos].Flags|=LIF_SELECTED;
1379 #else
1381 if ((Type == DI_COMBOBOX || Type == DI_LISTBOX)) {
1382 CurItem->ListPos = CurItem->ListPtr ? CurItem->ListPtr->GetSelectPos() : 0;
1385 #endif
1389 // Функция формирования и запроса цветов.
1390 DWORD Dialog::CtlColorDlgItem(int ItemPos, const DialogItemEx *CurItem)
1392 CriticalSectionLock Lock(CS);
1393 const int Type = CurItem->Type;
1394 const int Focus = CurItem->Focus;
1395 const int Default = CurItem->DefaultButton;
1396 const DWORD Flags = CurItem->Flags;
1398 const bool DisabledItem = (Flags & DIF_DISABLE) != 0;
1399 DWORD Attr = 0;
1401 switch (Type) {
1402 case DI_SINGLEBOX:
1403 case DI_DOUBLEBOX: {
1404 if (Flags & DIF_SETCOLOR)
1405 Attr = Flags & DIF_COLORMASK;
1406 else {
1407 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1408 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1409 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGBOX);
1412 Attr = MAKELONG(MAKEWORD(FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1413 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOXTITLE)
1414 : (DisabledItem ? COL_DIALOGDISABLED
1415 : COL_DIALOGBOXTITLE)), // Title LOBYTE
1416 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1417 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1418 : COL_WARNDIALOGHIGHLIGHTBOXTITLE)
1419 : (DisabledItem ? COL_DIALOGDISABLED
1420 : COL_DIALOGHIGHLIGHTBOXTITLE))), // HiText HIBYTE
1421 MAKEWORD(FarColorToReal(Attr), // Box LOBYTE
1422 0) // HIBYTE
1424 break;
1426 #if defined(VTEXT_ADN_SEPARATORS)
1427 case DI_VTEXT:
1428 #endif
1429 case DI_TEXT: {
1430 if (Flags & DIF_SETCOLOR)
1431 Attr = Flags & DIF_COLORMASK;
1432 else {
1433 if (Flags & DIF_BOXCOLOR)
1434 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1435 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1436 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGBOX);
1437 else
1438 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1439 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)
1440 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT);
1443 Attr = MAKELONG(MAKEWORD(FarColorToReal(Attr),
1444 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1445 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGHIGHLIGHTTEXT)
1446 : (DisabledItem ? COL_DIALOGDISABLED
1447 : COL_DIALOGHIGHLIGHTTEXT) // HIBYTE HiText
1449 ((Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2)) ? (
1450 MAKEWORD(FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1451 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1452 : (DisabledItem ? COL_DIALOGDISABLED
1453 : COL_DIALOGBOX) // Box LOBYTE
1456 : 0));
1457 break;
1459 #if !defined(VTEXT_ADN_SEPARATORS)
1460 case DI_VTEXT: {
1461 if (Flags & DIF_BOXCOLOR)
1462 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1463 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1464 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGBOX);
1465 else if (Flags & DIF_SETCOLOR)
1466 Attr = (Flags & DIF_COLORMASK);
1467 else
1468 Attr = (DialogMode.Check(DMODE_WARNINGSTYLE)
1469 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)
1470 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT));
1472 Attr = MAKEWORD(MAKEWORD(FarColorToReal(Attr), 0), MAKEWORD(0, 0));
1473 break;
1475 #endif
1476 case DI_CHECKBOX:
1477 case DI_RADIOBUTTON: {
1478 if (Flags & DIF_SETCOLOR)
1479 Attr = (Flags & DIF_COLORMASK);
1480 else
1481 Attr = (DialogMode.Check(DMODE_WARNINGSTYLE)
1482 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)
1483 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT));
1485 Attr = MAKEWORD(FarColorToReal(Attr),
1486 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1487 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGHIGHLIGHTTEXT)
1488 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGHIGHLIGHTTEXT))); // HiText
1489 break;
1491 case DI_BUTTON: {
1492 if (Focus) {
1493 SetCursorType(0, 10);
1494 Attr = MAKEWORD((Flags & DIF_SETCOLOR)
1495 ? (Flags & DIF_COLORMASK)
1496 : FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1497 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1498 : (Default ? COL_WARNDIALOGSELECTEDDEFAULTBUTTON
1499 : COL_WARNDIALOGSELECTEDBUTTON))
1500 : (DisabledItem ? COL_DIALOGDISABLED
1501 : (Default ? COL_DIALOGSELECTEDDEFAULTBUTTON
1502 : COL_DIALOGSELECTEDBUTTON))), // TEXT
1503 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1504 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1505 : (Default ? COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON
1506 : COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON))
1507 : (DisabledItem ? COL_DIALOGDISABLED
1508 : (Default ? COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON
1509 : COL_DIALOGHIGHLIGHTSELECTEDBUTTON)))); // HiText
1510 } else {
1511 Attr = MAKEWORD((Flags & DIF_SETCOLOR)
1512 ? (Flags & DIF_COLORMASK)
1513 : FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1514 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1515 : (Default ? COL_WARNDIALOGDEFAULTBUTTON
1516 : COL_WARNDIALOGBUTTON))
1517 : (DisabledItem ? COL_DIALOGDISABLED
1518 : (Default ? COL_DIALOGDEFAULTBUTTON
1519 : COL_DIALOGBUTTON))), // TEXT
1520 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1521 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1522 : (Default ? COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON
1523 : COL_WARNDIALOGHIGHLIGHTBUTTON))
1524 : (DisabledItem ? COL_DIALOGDISABLED
1525 : (Default ? COL_DIALOGHIGHLIGHTDEFAULTBUTTON
1526 : COL_DIALOGHIGHLIGHTBUTTON)))); // HiText
1529 break;
1531 case DI_EDIT:
1532 case DI_FIXEDIT:
1533 case DI_PSWEDIT:
1534 case DI_COMBOBOX:
1535 case DI_MEMOEDIT: {
1536 if (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST)) {
1537 if (DialogMode.Check(DMODE_WARNINGSTYLE))
1538 Attr = MAKELONG(MAKEWORD( // LOWORD
1539 // LOLO (Text)
1540 FarColorToReal(DisabledItem ? COL_WARNDIALOGEDITDISABLED
1541 : COL_WARNDIALOGEDIT),
1542 // LOHI (Select)
1543 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1544 : COL_DIALOGEDITSELECTED)),
1545 MAKEWORD( // HIWORD
1546 // HILO (Unchanged)
1547 FarColorToReal(DisabledItem ? COL_WARNDIALOGEDITDISABLED
1548 : COL_DIALOGEDITUNCHANGED), //???
1549 // HIHI (History)
1550 FarColorToReal(
1551 DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)));
1552 else
1553 Attr = MAKELONG(MAKEWORD( // LOWORD
1554 // LOLO (Text)
1555 FarColorToReal(DisabledItem
1556 ? COL_DIALOGEDITDISABLED
1557 : (!Focus ? COL_DIALOGEDIT
1558 : COL_DIALOGEDITSELECTED)),
1559 // LOHI (Select)
1560 FarColorToReal(DisabledItem
1561 ? COL_DIALOGEDITDISABLED
1562 : (!Focus ? COL_DIALOGEDIT
1563 : COL_DIALOGEDITSELECTED))),
1564 MAKEWORD( // HIWORD
1565 // HILO (Unchanged)
1566 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1567 : COL_DIALOGEDITUNCHANGED), //???
1568 // HIHI (History)
1569 FarColorToReal(DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT)));
1570 } else {
1571 if (DialogMode.Check(DMODE_WARNINGSTYLE))
1572 Attr = MAKELONG(MAKEWORD( // LOWORD
1573 // LOLO (Text)
1574 FarColorToReal(DisabledItem
1575 ? COL_WARNDIALOGEDITDISABLED
1576 : (Flags & DIF_NOFOCUS ? COL_DIALOGEDITUNCHANGED
1577 : COL_WARNDIALOGEDIT)),
1578 // LOHI (Select)
1579 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1580 : COL_DIALOGEDITSELECTED)),
1581 MAKEWORD( // HIWORD
1582 // HILO (Unchanged)
1583 FarColorToReal(DisabledItem ? COL_WARNDIALOGEDITDISABLED
1584 : COL_DIALOGEDITUNCHANGED), //???
1585 // HIHI (History)
1586 FarColorToReal(
1587 DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)));
1588 else
1589 Attr = MAKELONG(MAKEWORD( // LOWORD
1590 // LOLO (Text)
1591 FarColorToReal(DisabledItem
1592 ? COL_DIALOGEDITDISABLED
1593 : (Flags & DIF_NOFOCUS ? COL_DIALOGEDITUNCHANGED
1594 : COL_DIALOGEDIT)),
1595 // LOHI (Select)
1596 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1597 : COL_DIALOGEDITSELECTED)),
1598 MAKEWORD( // HIWORD
1599 // HILO (Unchanged)
1600 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1601 : COL_DIALOGEDITUNCHANGED), //???
1602 // HIHI (History)
1603 FarColorToReal(DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT)));
1606 break;
1608 case DI_LISTBOX: {
1609 Item[ItemPos]->ListPtr->SetColors(nullptr);
1610 return 0;
1612 default: {
1613 return 0;
1617 ++InCtlColorDlgItem;
1618 DWORD out = DlgProc((HANDLE)this, DN_CTLCOLORDLGITEM, ItemPos, Attr);
1619 --InCtlColorDlgItem;
1620 return out;
1623 static void SetColorNormal(DWORD Attr, const std::unique_ptr<DialogItemTrueColors> &TrueColors)
1625 ComposeAndSetColor(Attr & 0xff, TrueColors ? &TrueColors->Normal : nullptr);
1628 static void SetColorFrame(DWORD Attr, const std::unique_ptr<DialogItemTrueColors> &TrueColors)
1630 ComposeAndSetColor(LOBYTE(HIWORD(Attr)), TrueColors ? &TrueColors->Frame : nullptr);
1634 //////////////////////////////////////////////////////////////////////////
1636 Private:
1637 Отрисовка элементов диалога на экране.
1639 void Dialog::ShowDialog(unsigned ID)
1641 CriticalSectionLock Lock(CS);
1643 if (Locked())
1644 return;
1646 FARString strStr;
1647 DialogItemEx *CurItem;
1648 int X, Y;
1649 unsigned I, DrawItemCount;
1650 DWORD Attr;
1652 // Если не разрешена отрисовка, то вываливаем.
1653 if (IsEnableRedraw || // разрешена прорисовка ?
1654 (ID + 1 > ItemCount) || // а номер в рамках дозволенного?
1655 DialogMode.Check(DMODE_DRAWING) || // диалог рисуется?
1656 !DialogMode.Check(DMODE_SHOW) || // если не видим, то и не отрисовываем.
1657 !DialogMode.Check(DMODE_INITOBJECTS))
1658 return;
1660 DialogMode.Set(DMODE_DRAWING); // диалог рисуется!!!
1661 ChangePriority ChPriority(ChangePriority::NORMAL);
1663 if (ID == (unsigned)-1) // рисуем все?
1665 // Перед прорисовкой диалога посылаем сообщение в обработчик
1666 if (!DlgProc((HANDLE)this, DN_DRAWDIALOG, 0, 0)) {
1667 DialogMode.Clear(DMODE_DRAWING); // конец отрисовки диалога!!!
1668 return;
1671 // перед прорисовкой подложки окна диалога
1672 if (!DialogMode.Check(DMODE_NODRAWSHADOW))
1673 Shadow(DialogMode.Check(DMODE_FULLSHADOW) != FALSE); // "наводим" тень
1675 if (!DialogMode.Check(DMODE_NODRAWPANEL)) {
1676 Attr = (DWORD)DlgProc((HANDLE)this, DN_CTLCOLORDIALOG, 0,
1677 DialogMode.Check(DMODE_WARNINGSTYLE) ? COL_WARNDIALOGTEXT : COL_DIALOGTEXT);
1678 SetScreen(X1, Y1, X2, Y2, L' ', Attr);
1681 ID = 0;
1682 DrawItemCount = ItemCount;
1683 } else {
1684 DrawItemCount = ID + 1;
1688 IFlags.Set(DIMODE_REDRAW)
1689 TODO:
1690 если рисуется контрол и по Z-order`у он пересекается с
1691 другим контролом (по координатам), то для "позднего"
1692 контрола тоже нужна прорисовка.
1695 bool CursorVisible = false;
1696 DWORD CursorSize = 0;
1698 if (ID != (unsigned)-1 && FocusPos != ID) {
1699 if (Item[FocusPos]->Type == DI_USERCONTROL && Item[FocusPos]->UCData->CursorPos.X != -1
1700 && Item[FocusPos]->UCData->CursorPos.Y != -1) {
1701 CursorVisible = Item[FocusPos]->UCData->CursorVisible;
1702 CursorSize = Item[FocusPos]->UCData->CursorSize;
1706 SetCursorType(CursorVisible, CursorSize);
1709 for (I = ID; I < DrawItemCount; I++) {
1710 CurItem = Item[I];
1712 if (CurItem->Flags & DIF_HIDDEN)
1713 continue;
1716 $ 28.07.2000 SVS
1717 Перед прорисовкой каждого элемента посылаем сообщение
1718 посредством функции SendDlgMessage - в ней делается все!
1720 if (!SendDlgMessage((HANDLE)this, DN_DRAWDLGITEM, I, 0))
1721 continue;
1723 int LenText;
1724 short CX1 = CurItem->X1;
1725 short CY1 = CurItem->Y1;
1726 short CX2 = CurItem->X2;
1727 short CY2 = CurItem->Y2;
1729 if (CX2 > X2 - X1)
1730 CX2 = X2 - X1;
1732 if (CY2 > Y2 - Y1)
1733 CY2 = Y2 - Y1;
1735 short CW = CX2 - CX1 + 1;
1736 short CH = CY2 - CY1 + 1;
1737 Attr = CtlColorDlgItem(I, CurItem);
1738 #if 0
1740 // TODO: прежде чем эту строку применять... нужно проверить _ВСЕ_ диалоги на предмет X2, Y2. !!!
1741 if (((CX1 > -1) && (CX2 > 0) && (CX2 > CX1)) &&
1742 ((CY1 > -1) && (CY2 > 0) && (CY2 > CY1)))
1743 SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1745 #endif
1747 switch (CurItem->Type) {
1748 /* ***************************************************************** */
1749 case DI_SINGLEBOX:
1750 case DI_DOUBLEBOX: {
1751 BOOL IsDrawTitle = TRUE;
1752 GotoXY(X1 + CX1, Y1 + CY1);
1753 SetColorFrame(Attr, CurItem->TrueColors);
1755 if (CY1 == CY2) {
1756 DrawLine(CX2 - CX1 + 1, CurItem->Type == DI_SINGLEBOX ? 8 : 9); //???
1757 } else if (CX1 == CX2) {
1758 DrawLine(CY2 - CY1 + 1, CurItem->Type == DI_SINGLEBOX ? 10 : 11);
1759 IsDrawTitle = FALSE;
1760 } else {
1761 Box(X1 + CX1, Y1 + CY1, X1 + CX2, Y1 + CY2, LOBYTE(HIWORD(Attr)),
1762 (CurItem->Type == DI_SINGLEBOX) ? SINGLE_BOX : DOUBLE_BOX);
1765 if (!CurItem->strData.IsEmpty() && IsDrawTitle) {
1766 // ! Пусть диалог сам заботится о ширине собственного заголовка.
1767 strStr = CurItem->strData;
1768 TruncStrFromEnd(strStr, CW - 2); // 5 ???
1769 LenText = LenStrItem(I, strStr);
1771 if (LenText < CW - 2 && !strStr.Begins(L' ') ) {
1772 strStr.Insert(0, L' ');
1773 LenText = LenStrItem(I, strStr);
1776 if (LenText < CW - 2 && !strStr.Ends(L' ') ) { // пробел после текста заголовка и рамкой
1777 strStr.Append(L' ');
1778 LenText = LenStrItem(I, strStr);
1781 X = X1 + CX1 + (CW - LenText) / 2;
1783 if ((CurItem->Flags & DIF_LEFTTEXT) && X1 + CX1 + 1 < X)
1784 X = X1 + CX1 + 1;
1786 SetColorNormal(Attr, CurItem->TrueColors);
1787 GotoXY(X, Y1 + CY1);
1789 if (CurItem->Flags & DIF_SHOWAMPERSAND)
1790 Text(strStr);
1791 else if (CurItem->TrueColors)
1792 HiText(strStr, ComposeColor(HIBYTE(LOWORD(Attr)), &CurItem->TrueColors->Hilighted));
1793 else
1794 HiText(strStr, HIBYTE(LOWORD(Attr)));
1797 break;
1799 /* ***************************************************************** */
1800 case DI_TEXT: {
1801 strStr = CurItem->strData;
1802 LenText = LenStrItem(I, strStr);
1804 if (!(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))
1805 && (CurItem->Flags & DIF_CENTERTEXT) && CX1 != -1)
1806 LenText = LenStrItem(I, CenterStr(strStr, strStr, CX2 - CX1 + 1));
1808 X = (CX1 == -1 || (CurItem->Flags & (DIF_SEPARATOR | DIF_SEPARATOR2)))
1809 ? (X2 - X1 + 1 - LenText) / 2
1810 : CX1;
1811 Y = (CY1 == -1) ? (Y2 - Y1 + 1) / 2 : CY1;
1813 if (X < 0)
1814 X = 0;
1816 if ((CX2 <= 0) || (CX2 < CX1))
1817 CW = LenText;
1819 if (X1 + X + LenText > X2) {
1820 int tmpCW = ObjWidth;
1822 if (CW < ObjWidth)
1823 tmpCW = CW + 1;
1825 strStr.TruncateByCells(tmpCW - 1);
1828 // нужно ЭТО
1829 // SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1830 // вместо этого:
1831 if (CX1 > -1 && CX2 > CX1
1832 && !(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))) { // половинчатое решение
1834 int CntChr = CX2 - CX1 + 1;
1835 SetColorNormal(Attr, CurItem->TrueColors);
1836 GotoXY(X1 + X, Y1 + Y);
1838 if (X1 + X + CntChr - 1 > X2)
1839 CntChr = X2 - (X1 + X) + 1;
1841 FS << fmt::Cells() << fmt::Expand(CntChr) << L"";
1843 if (CntChr < LenText)
1844 strStr.TruncateByCells(CntChr);
1847 if (CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2)) {
1848 SetColorFrame(Attr, CurItem->TrueColors);
1849 GotoXY(X1
1850 + ((CurItem->Flags & DIF_SEPARATORUSER)
1852 : (!DialogMode.Check(DMODE_SMALLDIALOG) ? 3 : 0)),
1853 Y1 + Y); //????
1854 ShowUserSeparator((CurItem->Flags & DIF_SEPARATORUSER)
1855 ? X2 - X1 + 1
1856 : RealWidth - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 6 : 0 /* -1 */),
1857 (CurItem->Flags & DIF_SEPARATORUSER)
1858 ? 12
1859 : (CurItem->Flags & DIF_SEPARATOR2 ? 3 : 1),
1860 CurItem->strMask);
1863 SetColorNormal(Attr, CurItem->TrueColors);
1864 GotoXY(X1 + X, Y1 + Y);
1866 if (CurItem->Flags & DIF_SHOWAMPERSAND) {
1867 // MessageBox(0, strStr, strStr, MB_OK);
1868 Text(strStr);
1869 } else {
1870 // MessageBox(0, strStr, strStr, MB_OK);
1871 HiText(strStr, HIBYTE(LOWORD(Attr)));
1874 break;
1876 /* ***************************************************************** */
1877 case DI_VTEXT: {
1878 strStr = CurItem->strData;
1879 LenText = LenStrItem(I, strStr);
1881 if (!(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))
1882 && (CurItem->Flags & DIF_CENTERTEXT) && CY1 != -1)
1883 LenText = StrLength(CenterStr(strStr, strStr, CY2 - CY1 + 1));
1885 X = (CX1 == -1) ? (X2 - X1 + 1) / 2 : CX1;
1886 Y = (CY1 == -1 || (CurItem->Flags & (DIF_SEPARATOR | DIF_SEPARATOR2)))
1887 ? (Y2 - Y1 + 1 - LenText) / 2
1888 : CY1;
1890 if (Y < 0)
1891 Y = 0;
1893 if ((CY2 <= 0) || (CY2 < CY1))
1894 CH = LenStrItem(I, strStr);
1896 if (Y1 + Y + LenText > Y2) {
1897 int tmpCH = ObjHeight;
1899 if (CH < ObjHeight)
1900 tmpCH = CH + 1;
1902 strStr.TruncateByCells(tmpCH - 1);
1905 // нужно ЭТО
1906 // SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1907 // вместо этого:
1908 if (CY1 > -1 && CY2 > 0 && CY2 > CY1
1909 && !(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))) { // половинчатое решение
1911 int CntChr = CY2 - CY1 + 1;
1912 SetColorNormal(Attr, CurItem->TrueColors);
1913 GotoXY(X1 + X, Y1 + Y);
1915 if (Y1 + Y + CntChr - 1 > Y2)
1916 CntChr = Y2 - (Y1 + Y) + 1;
1918 vmprintf(L"%*ls", CntChr, L"");
1921 #if defined(VTEXT_ADN_SEPARATORS)
1923 if (CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2)) {
1924 SetColorFrame(Attr, CurItem->TrueColors);
1925 GotoXY(X1 + X,
1927 + ((CurItem->Flags & DIF_SEPARATORUSER)
1929 : (!DialogMode.Check(DMODE_SMALLDIALOG) ? 1 : 0))); //????
1930 ShowUserSeparator((CurItem->Flags & DIF_SEPARATORUSER)
1931 ? Y2 - Y1 + 1
1932 : RealHeight - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 2 : 0),
1933 (CurItem->Flags & DIF_SEPARATORUSER)
1934 ? 13
1935 : (CurItem->Flags & DIF_SEPARATOR2 ? 7 : 5),
1936 CurItem->strMask);
1939 #endif
1940 SetColorNormal(Attr, CurItem->TrueColors);
1941 GotoXY(X1 + X, Y1 + Y);
1943 if (CurItem->Flags & DIF_SHOWAMPERSAND)
1944 VText(strStr);
1945 else
1946 HiText(strStr, HIBYTE(LOWORD(Attr)), TRUE);
1948 break;
1950 /* ***************************************************************** */
1951 case DI_CHECKBOX:
1952 case DI_RADIOBUTTON: {
1953 SetColorNormal(Attr, CurItem->TrueColors);
1954 GotoXY(X1 + CX1, Y1 + CY1);
1956 if (CurItem->Type == DI_CHECKBOX) {
1957 const wchar_t Check[] = {L'[',
1958 (CurItem->Selected ? (((CurItem->Flags & DIF_3STATE) && CurItem->Selected == 2)
1959 ? *Msg::CheckBox2State
1960 : L'x')
1961 : L' '),
1962 L']', L'\0'};
1963 strStr = Check;
1965 if (CurItem->strData.GetLength())
1966 strStr+= L" ";
1967 } else {
1968 wchar_t Dot[] = {L' ', CurItem->Selected ? L'\x2022' : L' ', L' ', L'\0'};
1970 if (CurItem->Flags & DIF_MOVESELECT) {
1971 strStr = Dot;
1972 } else {
1973 Dot[0] = L'(';
1974 Dot[2] = L')';
1975 strStr = Dot;
1977 if (CurItem->strData.GetLength())
1978 strStr+= L" ";
1982 strStr+= CurItem->strData;
1983 LenText = LenStrItem(I, strStr);
1985 if (X1 + CX1 + LenText > X2)
1986 strStr.TruncateByCells(ObjWidth - 1);
1988 if (CurItem->Flags & DIF_SHOWAMPERSAND)
1989 Text(strStr);
1990 else
1991 HiText(strStr, HIBYTE(LOWORD(Attr)));
1993 if (CurItem->Focus) {
1994 // Отключение мигающего курсора при перемещении диалога
1995 if (!DialogMode.Check(DMODE_DRAGGED))
1996 SetCursorType(1, -1);
1998 MoveCursor(X1 + CX1 + 1, Y1 + CY1);
2001 break;
2003 /* ***************************************************************** */
2004 case DI_BUTTON: {
2005 strStr = CurItem->strData;
2006 SetColorNormal(Attr, CurItem->TrueColors);
2007 GotoXY(X1 + CX1, Y1 + CY1);
2009 if (CurItem->Flags & DIF_SHOWAMPERSAND)
2010 Text(strStr);
2011 else
2012 HiText(strStr, HIBYTE(LOWORD(Attr)));
2014 if (CurItem->Flags & DIF_SETSHIELD) {
2015 int startx = X1 + CX1 + (CurItem->Flags & DIF_NOBRACKETS ? 0 : 2);
2016 ScrBuf.ApplyColor(startx, Y1 + CY1, startx + 1, Y1 + CY1, 0xE9);
2018 break;
2020 /* ***************************************************************** */
2021 case DI_EDIT:
2022 case DI_FIXEDIT:
2023 case DI_PSWEDIT:
2024 case DI_COMBOBOX:
2025 case DI_MEMOEDIT: {
2026 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
2028 if (!EditPtr)
2029 break;
2031 EditPtr->SetObjectColor(Attr & 0xFF, HIBYTE(LOWORD(Attr)), LOBYTE(HIWORD(Attr)));
2033 if (CurItem->Focus) {
2034 // Отключение мигающего курсора при перемещении диалога
2035 if (!DialogMode.Check(DMODE_DRAGGED))
2036 SetCursorType(1, -1);
2038 EditPtr->Show();
2039 } else {
2040 EditPtr->FastShow();
2041 EditPtr->SetLeftPos(0);
2044 // Отключение мигающего курсора при перемещении диалога
2045 if (DialogMode.Check(DMODE_DRAGGED))
2046 SetCursorType(0, 0);
2048 if (ItemHasDropDownArrow(CurItem)) {
2049 int EditX1, EditY1, EditX2, EditY2;
2050 EditPtr->GetPosition(EditX1, EditY1, EditX2, EditY2);
2051 // Text((CurItem->Type == DI_COMBOBOX?"\x1F":"\x19"));
2052 Text(EditX2 + 1, EditY1, HIBYTE(HIWORD(Attr)), L"\x2193");
2055 if (CurItem->Type == DI_COMBOBOX && GetDropDownOpened() && CurItem->ListPtr->IsVisible()) // need redraw VMenu?
2057 CurItem->ListPtr->Hide();
2058 CurItem->ListPtr->Show();
2061 break;
2063 /* ***************************************************************** */
2064 case DI_LISTBOX: {
2065 if (CurItem->ListPtr) {
2066 // Перед отрисовкой спросим об изменении цветовых атрибутов
2067 BYTE RealColors[VMENU_COLOR_COUNT];
2068 FarListColors ListColors = {0};
2069 ListColors.ColorCount = VMENU_COLOR_COUNT;
2070 ListColors.Colors = RealColors;
2071 CurItem->ListPtr->GetColors(&ListColors);
2073 if (DlgProc((HANDLE)this, DN_CTLCOLORDLGLIST, I, (LONG_PTR)&ListColors))
2074 CurItem->ListPtr->SetColors(&ListColors);
2076 // Курсор запоминаем...
2077 bool CursorVisible = false;
2078 DWORD CursorSize = 0;
2079 GetCursorType(CursorVisible, CursorSize);
2080 CurItem->ListPtr->Show();
2082 // .. а теперь восстановим!
2083 if (FocusPos != I)
2084 SetCursorType(CursorVisible, CursorSize);
2087 break;
2089 /* 01.08.2000 SVS $ */
2090 /* ***************************************************************** */
2091 case DI_USERCONTROL:
2093 if (CurItem->VBuf) {
2094 PutText(X1 + CX1, Y1 + CY1, X1 + CX2, Y1 + CY2, CurItem->VBuf);
2096 // не забудем переместить курсор, если он позиционирован.
2097 if (FocusPos == I) {
2098 if (CurItem->UCData->CursorPos.X != -1 && CurItem->UCData->CursorPos.Y != -1) {
2099 MoveCursor(CurItem->UCData->CursorPos.X + CX1 + X1,
2100 CurItem->UCData->CursorPos.Y + CY1 + Y1);
2101 SetCursorType(CurItem->UCData->CursorVisible, CurItem->UCData->CursorSize);
2102 } else
2103 SetCursorType(0, -1);
2107 break; // уже наприсовали :-)))
2108 /* ***************************************************************** */
2109 //.........
2110 } // end switch(...
2111 } // end for (I=...
2113 // КОСТЫЛЬ!
2114 // но работает ;-)
2115 for (I = 0; I < ItemCount; I++) {
2116 CurItem = Item[I];
2118 if (CurItem->ListPtr && GetDropDownOpened() && CurItem->ListPtr->IsVisible()) {
2119 if ((CurItem->Type == DI_COMBOBOX)
2120 || ((CurItem->Type == DI_EDIT || CurItem->Type == DI_FIXEDIT)
2121 && !(CurItem->Flags & DIF_HIDDEN) && (CurItem->Flags & DIF_HISTORY))) {
2122 CurItem->ListPtr->Show();
2127 // Включим индикатор перемещения...
2128 if (!DialogMode.Check(DMODE_DRAGGED)) // если диалог таскается
2131 $ 03.06.2001 KM
2132 + При каждой перерисовке диалога, кроме режима перемещения, устанавливаем
2133 заголовок консоли, в противном случае он не всегда восстанавливался.
2135 if (!DialogMode.Check(DMODE_KEEPCONSOLETITLE))
2136 ConsoleTitle::SetFarTitle(GetDialogTitle());
2139 DialogMode.Clear(DMODE_DRAWING); // конец отрисовки диалога!!!
2140 DialogMode.Set(DMODE_SHOW); // диалог на экране!
2142 if (DialogMode.Check(DMODE_DRAGGED)) {
2144 - BugZ#813 - DM_RESIZEDIALOG в DN_DRAWDIALOG -> проблема: Ctrl-F5 - отрисовка только полозьев.
2145 Убираем вызов плагиновго обработчика.
2147 // DlgProc((HANDLE)this,DN_DRAWDIALOGDONE,1,0);
2148 DefDlgProc((HANDLE)this, DN_DRAWDIALOGDONE, 1, 0);
2149 } else
2150 DlgProc((HANDLE)this, DN_DRAWDIALOGDONE, 0, 0);
2153 int Dialog::LenStrItem(int ID, const wchar_t *lpwszStr)
2155 CriticalSectionLock Lock(CS);
2157 if (!lpwszStr)
2158 lpwszStr = Item[ID]->strData;
2160 return (Item[ID]->Flags & DIF_SHOWAMPERSAND) ? StrZCellsCount(lpwszStr) : HiStrCellsCount(lpwszStr);
2163 int Dialog::ProcessMoveDialog(DWORD Key)
2165 CriticalSectionLock Lock(CS);
2167 if (DialogMode.Check(DMODE_DRAGGED)) // если диалог таскается
2170 TODO: Здесь проверить "уже здесь" и не делать лишних движений
2171 Т.е., если нажали End, то при следующем End ненужно ничего делать! - сравнить координаты !!!
2173 int rr = 1;
2175 // При перемещении диалога повторяем поведение "бормандовых" сред.
2176 switch (Key) {
2177 case KEY_CTRLLEFT:
2178 case KEY_CTRLNUMPAD4:
2179 case KEY_CTRLHOME:
2180 case KEY_CTRLNUMPAD7:
2181 case KEY_HOME:
2182 case KEY_NUMPAD7:
2183 rr = Key == KEY_CTRLLEFT || Key == KEY_CTRLNUMPAD4 ? 10 : X1;
2184 case KEY_LEFT:
2185 case KEY_NUMPAD4:
2186 Hide();
2188 for (int i = 0; i < rr; i++)
2189 if (X2 > 0) {
2190 X1--;
2191 X2--;
2192 AdjustEditPos(-1, 0);
2195 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2196 Show();
2198 break;
2199 case KEY_CTRLRIGHT:
2200 case KEY_CTRLNUMPAD6:
2201 case KEY_CTRLEND:
2202 case KEY_CTRLNUMPAD1:
2203 case KEY_END:
2204 case KEY_NUMPAD1:
2205 rr = Key == KEY_CTRLRIGHT || Key == KEY_CTRLNUMPAD6 ? 10 : Max(0, ScrX - X2);
2206 case KEY_RIGHT:
2207 case KEY_NUMPAD6:
2208 Hide();
2210 for (int i = 0; i < rr; i++)
2211 if (X1 < ScrX) {
2212 X1++;
2213 X2++;
2214 AdjustEditPos(1, 0);
2217 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2218 Show();
2220 break;
2221 case KEY_PGUP:
2222 case KEY_NUMPAD9:
2223 case KEY_CTRLPGUP:
2224 case KEY_CTRLNUMPAD9:
2225 case KEY_CTRLUP:
2226 case KEY_CTRLNUMPAD8:
2227 rr = Key == KEY_CTRLUP || Key == KEY_CTRLNUMPAD8 ? 5 : Y1;
2228 case KEY_UP:
2229 case KEY_NUMPAD8:
2230 Hide();
2232 for (int i = 0; i < rr; i++)
2233 if (Y2 > 0) {
2234 Y1--;
2235 Y2--;
2236 AdjustEditPos(0, -1);
2239 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2240 Show();
2242 break;
2243 case KEY_CTRLDOWN:
2244 case KEY_CTRLNUMPAD2:
2245 case KEY_CTRLPGDN:
2246 case KEY_CTRLNUMPAD3:
2247 case KEY_PGDN:
2248 case KEY_NUMPAD3:
2249 rr = Key == KEY_CTRLDOWN || Key == KEY_CTRLNUMPAD2 ? 5 : Max(0, ScrY - Y2);
2250 case KEY_DOWN:
2251 case KEY_NUMPAD2:
2252 Hide();
2254 for (int i = 0; i < rr; i++)
2255 if (Y1 < ScrY) {
2256 Y1++;
2257 Y2++;
2258 AdjustEditPos(0, 1);
2261 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2262 Show();
2264 break;
2265 case KEY_NUMENTER:
2266 case KEY_ENTER:
2267 case KEY_CTRLF5:
2268 DialogMode.Clear(DMODE_DRAGGED); // закончим движение!
2270 if (!DialogMode.Check(DMODE_ALTDRAGGED)) {
2271 DlgProc((HANDLE)this, DN_DRAGGED, 1, 0);
2272 Show();
2275 break;
2276 case KEY_ESC:
2277 Hide();
2278 AdjustEditPos(OldX1 - X1, OldY1 - Y1);
2279 X1 = OldX1;
2280 X2 = OldX2;
2281 Y1 = OldY1;
2282 Y2 = OldY2;
2283 DialogMode.Clear(DMODE_DRAGGED);
2285 if (!DialogMode.Check(DMODE_ALTDRAGGED)) {
2286 DlgProc((HANDLE)this, DN_DRAGGED, 1, TRUE);
2287 Show();
2290 break;
2293 if (DialogMode.Check(DMODE_ALTDRAGGED)) {
2294 DialogMode.Clear(DMODE_DRAGGED | DMODE_ALTDRAGGED);
2295 DlgProc((HANDLE)this, DN_DRAGGED, 1, 0);
2296 Show();
2299 return (TRUE);
2302 if (Key == KEY_CTRLF5 && DialogMode.Check(DMODE_ISCANMOVE)) {
2303 if (DlgProc((HANDLE)this, DN_DRAGGED, 0, 0)) // если разрешили перемещать!
2305 // включаем флаг и запоминаем координаты
2306 DialogMode.Set(DMODE_DRAGGED);
2307 OldX1 = X1;
2308 OldX2 = X2;
2309 OldY1 = Y1;
2310 OldY2 = Y2;
2311 // # GetText(0,0,3,0,LV);
2312 Show();
2315 return (TRUE);
2318 return (FALSE);
2321 int64_t Dialog::VMProcess(MacroOpcode OpCode, void *vParam, int64_t iParam)
2323 switch (OpCode) {
2324 case MCODE_F_MENU_CHECKHOTKEY:
2325 case MCODE_F_MENU_GETHOTKEY:
2326 case MCODE_F_MENU_SELECT:
2327 case MCODE_F_MENU_GETVALUE:
2328 case MCODE_F_MENU_ITEMSTATUS:
2329 case MCODE_V_MENU_VALUE: {
2330 const wchar_t *str = (const wchar_t *)vParam;
2332 if (GetDropDownOpened() || Item[FocusPos]->Type == DI_LISTBOX) {
2333 if (Item[FocusPos]->ListPtr)
2334 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2335 } else if (OpCode == MCODE_F_MENU_CHECKHOTKEY)
2336 return (int64_t)(CheckHighlights(*str, (int)iParam) + 1);
2338 return 0;
2342 switch (OpCode) {
2343 case MCODE_C_EOF:
2344 case MCODE_C_BOF:
2345 case MCODE_C_SELECTED:
2346 case MCODE_C_EMPTY: {
2347 if (FarIsEdit(Item[FocusPos]->Type)) {
2348 if (Item[FocusPos]->Type == DI_COMBOBOX && GetDropDownOpened())
2349 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2350 else
2351 return ((DlgEdit *)(Item[FocusPos]->ObjPtr))->VMProcess(OpCode, vParam, iParam);
2352 } else if (Item[FocusPos]->Type == DI_LISTBOX && OpCode != MCODE_C_SELECTED)
2353 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2355 return 0;
2357 case MCODE_V_DLGITEMTYPE: {
2358 switch (Item[FocusPos]->Type) {
2359 case DI_BUTTON:
2360 return 7; // Кнопка (Push Button).
2361 case DI_CHECKBOX:
2362 return 8; // Контрольный переключатель (Check Box).
2363 case DI_COMBOBOX:
2364 return (DropDownOpened ? 0x800A : 10); // Комбинированный список.
2365 case DI_DOUBLEBOX:
2366 return 3; // Двойная рамка.
2367 case DI_EDIT:
2368 return DropDownOpened ? 0x8004 : 4; // Поле ввода.
2369 case DI_FIXEDIT:
2370 return 6; // Поле ввода фиксированного размера.
2371 case DI_LISTBOX:
2372 return 11; // Окно списка.
2373 case DI_PSWEDIT:
2374 return 5; // Поле ввода пароля.
2375 case DI_RADIOBUTTON:
2376 return 9; // Селекторная кнопка (Radio Button).
2377 case DI_SINGLEBOX:
2378 return 2; // Одиночная рамка.
2379 case DI_TEXT:
2380 return 0; // Текстовая строка.
2381 case DI_USERCONTROL:
2382 return 255; // Элемент управления, определяемый программистом.
2383 case DI_VTEXT:
2384 return 1; // Вертикальная текстовая строка.
2387 return -1;
2389 case MCODE_V_DLGITEMCOUNT: // Dlg.ItemCount
2391 return ItemCount;
2393 case MCODE_V_DLGCURPOS: // Dlg.CurPos
2395 return FocusPos + 1;
2397 case MCODE_V_DLGINFOID: // Dlg.Info.Id
2399 static FARString strId;
2400 strId.Format(L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", Id.Data1, Id.Data2, Id.Data3,
2401 Id.Data4[0], Id.Data4[1], Id.Data4[2], Id.Data4[3], Id.Data4[4], Id.Data4[5], Id.Data4[6],
2402 Id.Data4[7]);
2403 return reinterpret_cast<INT64>(strId.CPtr());
2405 case MCODE_V_ITEMCOUNT:
2406 case MCODE_V_CURPOS: {
2407 switch (Item[FocusPos]->Type) {
2408 case DI_COMBOBOX:
2410 if (DropDownOpened || (Item[FocusPos]->Flags & DIF_DROPDOWNLIST))
2411 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2413 case DI_EDIT:
2414 case DI_PSWEDIT:
2415 case DI_FIXEDIT:
2416 return ((DlgEdit *)(Item[FocusPos]->ObjPtr))->VMProcess(OpCode, vParam, iParam);
2417 case DI_LISTBOX:
2418 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2419 case DI_USERCONTROL:
2421 if (OpCode == MCODE_V_CURPOS)
2422 return Item[FocusPos]->UCData->CursorPos.X;
2424 case DI_BUTTON:
2425 case DI_CHECKBOX:
2426 case DI_RADIOBUTTON:
2427 return 0;
2430 return 0;
2432 case MCODE_F_EDITOR_SEL: {
2433 if (FarIsEdit(Item[FocusPos]->Type)
2434 || (Item[FocusPos]->Type == DI_COMBOBOX
2435 && !(DropDownOpened || (Item[FocusPos]->Flags & DIF_DROPDOWNLIST)))) {
2436 return ((DlgEdit *)(Item[FocusPos]->ObjPtr))->VMProcess(OpCode, vParam, iParam);
2439 return 0;
2443 return 0;
2446 //////////////////////////////////////////////////////////////////////////
2448 Public, Virtual:
2449 Обработка данных от клавиатуры.
2450 Перекрывает BaseInput::ProcessKey.
2452 int Dialog::ProcessKey(FarKey Key)
2454 CriticalSectionLock Lock(CS);
2455 _DIALOG(CleverSysLog CL(L"Dialog::ProcessKey"));
2456 _DIALOG(SysLog(L"Param: Key=%ls", _FARKEY_ToName(Key)));
2457 unsigned I;
2458 FARString strStr;
2460 if (Key == KEY_NONE || Key == KEY_IDLE) {
2461 DlgProc((HANDLE)this, DN_ENTERIDLE, 0, 0); // $ 28.07.2000 SVS Передадим этот факт в обработчик :-)
2462 return FALSE;
2465 if (Key == KEY_KILLFOCUS || Key == KEY_GOTFOCUS) {
2466 DlgProc((HANDLE)this, DN_ACTIVATEAPP, Key == KEY_KILLFOCUS ? FALSE : TRUE, 0);
2467 return FALSE;
2470 if (ProcessMoveDialog(Key))
2471 return TRUE;
2473 // BugZ#488 - Shift=enter
2474 if (ShiftPressed && (Key == KEY_ENTER || Key == KEY_NUMENTER) && !CtrlObject->Macro.IsExecuting()
2475 && Item[FocusPos]->Type != DI_BUTTON) {
2476 Key = Key == KEY_ENTER ? KEY_SHIFTENTER : KEY_SHIFTNUMENTER;
2479 if (!(
2480 /*(Key>=KEY_MACRO_BASE && Key <=KEY_MACRO_ENDBASE) ||*/
2481 ((unsigned int)Key >= KEY_OP_BASE && (unsigned int)Key <= KEY_OP_ENDBASE))
2482 && !DialogMode.Check(DMODE_KEY))
2483 if (DlgProc((HANDLE)this, DN_KEY, FocusPos, Key))
2484 return TRUE;
2486 if (!DialogMode.Check(DMODE_SHOW))
2487 return TRUE;
2489 // А ХЗ, может в этот момент изменилось состояние элемента!
2490 if (Item[FocusPos]->Flags & DIF_HIDDEN)
2491 return TRUE;
2493 // небольшая оптимизация
2494 if (Item[FocusPos]->Type == DI_CHECKBOX) {
2495 if (!(Item[FocusPos]->Flags & DIF_3STATE)) {
2496 if (Key == KEY_MULTIPLY) // в CheckBox 2-state Gray* не работает!
2497 Key = KEY_NONE;
2499 if ((Key == KEY_ADD && !Item[FocusPos]->Selected)
2500 || (Key == KEY_SUBTRACT && Item[FocusPos]->Selected))
2501 Key = KEY_SPACE;
2504 // блок else не нужен, т.к. ниже клавиши будут обработаны...
2505 } else if (Key == KEY_ADD)
2506 Key = '+';
2507 else if (Key == KEY_SUBTRACT)
2508 Key = '-';
2509 else if (Key == KEY_MULTIPLY)
2510 Key = '*';
2512 if (Item[FocusPos]->Type == DI_BUTTON && Key == KEY_SPACE)
2513 Key = KEY_ENTER;
2515 if (Item[FocusPos]->Type == DI_LISTBOX) {
2516 switch (Key) {
2517 case KEY_HOME:
2518 case KEY_NUMPAD7:
2519 case KEY_LEFT:
2520 case KEY_NUMPAD4:
2521 case KEY_END:
2522 case KEY_NUMPAD1:
2523 case KEY_RIGHT:
2524 case KEY_NUMPAD6:
2525 case KEY_UP:
2526 case KEY_NUMPAD8:
2527 case KEY_DOWN:
2528 case KEY_NUMPAD2:
2529 case KEY_PGUP:
2530 case KEY_NUMPAD9:
2531 case KEY_PGDN:
2532 case KEY_NUMPAD3:
2533 case KEY_MSWHEEL_UP:
2534 case KEY_MSWHEEL_DOWN:
2535 case KEY_MSWHEEL_LEFT:
2536 case KEY_MSWHEEL_RIGHT:
2537 case KEY_NUMENTER:
2538 case KEY_ENTER:
2539 VMenu *List = Item[FocusPos]->ListPtr;
2540 int CurListPos = List->GetSelectPos();
2541 auto CheckedListItem = List->GetCheck(-1);
2542 List->ProcessKey(Key);
2543 int NewListPos = List->GetSelectPos();
2545 if (NewListPos != CurListPos && !DlgProc((HANDLE)this, DN_LISTCHANGE, FocusPos, NewListPos)) {
2546 if (!DialogMode.Check(DMODE_SHOW))
2547 return TRUE;
2549 List->SetCheck(CheckedListItem, CurListPos);
2551 if (DialogMode.Check(DMODE_SHOW) && !(Item[FocusPos]->Flags & DIF_HIDDEN))
2552 ShowDialog(FocusPos); // FocusPos
2555 if (!(Key == KEY_ENTER || Key == KEY_NUMENTER) || (Item[FocusPos]->Flags & DIF_LISTNOCLOSE))
2556 return TRUE;
2560 switch (Key) {
2561 case KEY_F1:
2564 Перед выводом диалога посылаем сообщение в обработчик
2565 и если вернули что надо, то выводим подсказку
2567 if (!Help::MkTopic(PluginNumber,
2568 (const wchar_t *)DlgProc((HANDLE)this, DN_HELP, FocusPos,
2569 (HelpTopic ? (LONG_PTR)HelpTopic : 0)),
2570 strStr)
2571 .IsEmpty()) {
2572 Help::Present(strStr);
2575 return TRUE;
2576 case KEY_ESC:
2577 case KEY_BREAK:
2578 case KEY_F10:
2579 ExitCode = (Key == KEY_BREAK) ? -2 : -1;
2580 CloseDialog();
2581 return TRUE;
2582 case KEY_HOME:
2583 case KEY_NUMPAD7:
2585 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2586 return TRUE;
2588 return Do_ProcessFirstCtrl();
2589 case KEY_TAB:
2590 case KEY_SHIFTTAB:
2591 return Do_ProcessTab(Key == KEY_TAB);
2592 case KEY_SPACE:
2593 return Do_ProcessSpace();
2594 case KEY_CTRLNUMENTER:
2595 case KEY_CTRLENTER: {
2596 for (I = 0; I < ItemCount; I++)
2597 if (Item[I]->DefaultButton) {
2598 if (Item[I]->Flags & DIF_DISABLE) {
2599 // ProcessKey(KEY_DOWN); // на твой вкус :-)
2600 return TRUE;
2603 if (!FarIsEdit(Item[I]->Type))
2604 Item[I]->Selected = 1;
2606 ExitCode = I;
2607 /* $ 18.05.2001 DJ */
2608 CloseDialog();
2609 /* DJ $ */
2610 return TRUE;
2613 if (!DialogMode.Check(DMODE_OLDSTYLE)) {
2614 DialogMode.Clear(DMODE_ENDLOOP); // только если есть
2615 return TRUE; // делать больше не чего
2618 case KEY_NUMENTER:
2619 case KEY_ENTER: {
2620 if (Item[FocusPos]->Type != DI_COMBOBOX && FarIsEdit(Item[FocusPos]->Type)
2621 && (Item[FocusPos]->Flags & DIF_EDITOR) && !(Item[FocusPos]->Flags & DIF_READONLY)) {
2622 unsigned EditorLastPos;
2624 for (EditorLastPos = I = FocusPos; I < ItemCount; I++)
2625 if (FarIsEdit(Item[I]->Type) && (Item[I]->Flags & DIF_EDITOR))
2626 EditorLastPos = I;
2627 else
2628 break;
2630 if (((DlgEdit *)(Item[EditorLastPos]->ObjPtr))->GetLength())
2631 return TRUE;
2633 for (I = EditorLastPos; I > FocusPos; I--) {
2634 int CurPos;
2636 if (I == FocusPos + 1)
2637 CurPos = ((DlgEdit *)(Item[I - 1]->ObjPtr))->GetCurPos();
2638 else
2639 CurPos = 0;
2641 ((DlgEdit *)(Item[I - 1]->ObjPtr))->GetString(strStr);
2642 int Length = (int)strStr.GetLength();
2643 ((DlgEdit *)(Item[I]->ObjPtr))
2644 ->SetString(CurPos >= Length ? L"" : strStr.CPtr() + CurPos);
2646 if (CurPos < Length)
2647 strStr.Truncate(CurPos);
2649 ((DlgEdit *)(Item[I]->ObjPtr))->SetCurPos(0);
2650 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(strStr);
2653 if (EditorLastPos > FocusPos) {
2654 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->SetCurPos(0);
2655 Do_ProcessNextCtrl(FALSE, FALSE);
2658 ShowDialog();
2659 return TRUE;
2660 } else if (Item[FocusPos]->Type == DI_BUTTON) {
2661 Item[FocusPos]->Selected = 1;
2663 // сообщение - "Кнокна кликнута"
2664 if (SendDlgMessage((HANDLE)this, DN_BTNCLICK, FocusPos, 0))
2665 return TRUE;
2667 if (Item[FocusPos]->Flags & DIF_BTNNOCLOSE)
2668 return TRUE;
2670 ExitCode = FocusPos;
2671 CloseDialog();
2672 return TRUE;
2673 } else {
2674 ExitCode = -1;
2676 for (I = 0; I < ItemCount; I++) {
2677 if (Item[I]->DefaultButton && !(Item[I]->Flags & DIF_BTNNOCLOSE)) {
2678 if (Item[I]->Flags & DIF_DISABLE) {
2679 // ProcessKey(KEY_DOWN); // на твой вкус :-)
2680 return TRUE;
2683 // if (!(FarIsEdit(Item[I].Type) || Item[I].Type == DI_CHECKBOX || Item[I].Type == DI_RADIOBUTTON))
2684 // Item[I].Selected=1;
2685 ExitCode = I;
2686 break;
2691 if (ExitCode == -1)
2692 ExitCode = FocusPos;
2694 CloseDialog();
2695 return TRUE;
2698 3-х уровневое состояние
2699 Для чекбокса сюда попадем только в случае, если контрол
2700 имеет флаг DIF_3STATE
2702 case KEY_ADD:
2703 case KEY_SUBTRACT:
2704 case KEY_MULTIPLY:
2706 if (Item[FocusPos]->Type == DI_CHECKBOX) {
2707 unsigned int CHKState = (Key == KEY_ADD
2709 : (Key == KEY_SUBTRACT
2711 : ((Key == KEY_MULTIPLY) ? 2 : Item[FocusPos]->Selected)));
2713 if (Item[FocusPos]->Selected != (int)CHKState)
2714 if (SendDlgMessage((HANDLE)this, DN_BTNCLICK, FocusPos, CHKState)) {
2715 Item[FocusPos]->Selected = CHKState;
2716 ShowDialog();
2720 return TRUE;
2721 case KEY_LEFT:
2722 case KEY_NUMPAD4:
2723 case KEY_SHIFTNUMPAD4:
2724 case KEY_MSWHEEL_LEFT:
2725 case KEY_RIGHT:
2726 case KEY_NUMPAD6:
2727 case KEY_SHIFTNUMPAD6:
2728 case KEY_MSWHEEL_RIGHT: {
2729 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2730 return TRUE;
2732 if (FarIsEdit(Item[FocusPos]->Type)) {
2733 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(Key);
2734 return TRUE;
2735 } else {
2736 int MinDist = 1000, MinPos = 0;
2738 for (I = 0; I < ItemCount; I++) {
2739 if (I != FocusPos && (!(Item[I]->Flags & (DIF_NOFOCUS | DIF_DISABLE | DIF_HIDDEN)))
2740 && (FarIsEdit(Item[I]->Type) || Item[I]->Type == DI_CHECKBOX
2741 || Item[I]->Type == DI_RADIOBUTTON)
2742 && Item[I]->Y1 == Item[FocusPos]->Y1) {
2743 int Dist = Item[I]->X1 - Item[FocusPos]->X1;
2745 if (((Key == KEY_LEFT || Key == KEY_SHIFTNUMPAD4) && Dist < 0)
2746 || ((Key == KEY_RIGHT || Key == KEY_SHIFTNUMPAD6) && Dist > 0))
2747 if (abs(Dist) < MinDist) {
2748 MinDist = abs(Dist);
2749 MinPos = I;
2754 if (MinDist < 1000) {
2755 ChangeFocus2(MinPos);
2757 if (Item[MinPos]->Flags & DIF_MOVESELECT) {
2758 Do_ProcessSpace();
2759 } else {
2760 ShowDialog();
2763 return TRUE;
2767 case KEY_UP:
2768 case KEY_NUMPAD8:
2769 case KEY_DOWN:
2770 case KEY_NUMPAD2:
2772 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2773 return TRUE;
2775 return Do_ProcessNextCtrl(
2776 Key == KEY_LEFT || Key == KEY_UP || Key == KEY_NUMPAD4 || Key == KEY_NUMPAD8);
2777 // $ 27.04.2001 VVM - Обработка колеса мышки
2778 case KEY_MSWHEEL_UP:
2779 case KEY_MSWHEEL_DOWN:
2780 case KEY_CTRLUP:
2781 case KEY_CTRLNUMPAD8:
2782 case KEY_CTRLDOWN:
2783 case KEY_CTRLNUMPAD2:
2784 return ProcessOpenComboBox(Item[FocusPos]->Type, Item[FocusPos], FocusPos);
2785 // ЭТО перед default предпоследний!!!
2786 case KEY_END:
2787 case KEY_NUMPAD1:
2789 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2790 return TRUE;
2792 if (FarIsEdit(Item[FocusPos]->Type)) {
2793 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(Key);
2794 return TRUE;
2797 // ???
2798 // ЭТО перед default последний!!!
2799 case KEY_PGDN:
2800 case KEY_NUMPAD3:
2802 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2803 return TRUE;
2805 if (!(Item[FocusPos]->Flags & DIF_EDITOR)) {
2806 for (I = 0; I < ItemCount; I++)
2807 if (Item[I]->DefaultButton) {
2808 ChangeFocus2(I);
2809 ShowDialog();
2810 return TRUE;
2813 return TRUE;
2815 break;
2817 case KEY_F11: {
2818 if (!CheckDialogMode(DMODE_NOPLUGINS)) {
2819 return FrameManager->ProcessKey(Key);
2821 } break;
2823 // для DIF_EDITOR будет обработано ниже
2824 default: {
2825 // if(Item[FocusPos].Type == DI_USERCONTROL) // для user-типа вываливаем
2826 // return TRUE;
2827 if (Item[FocusPos]->Type == DI_LISTBOX) {
2828 VMenu *List = Item[FocusPos]->ListPtr;
2829 int CurListPos = List->GetSelectPos();
2830 auto CheckedListItem = List->GetCheck(-1);
2831 List->ProcessKey(Key);
2832 int NewListPos = List->GetSelectPos();
2834 if (NewListPos != CurListPos && !DlgProc((HANDLE)this, DN_LISTCHANGE, FocusPos, NewListPos)) {
2835 if (!DialogMode.Check(DMODE_SHOW))
2836 return TRUE;
2838 List->SetCheck(CheckedListItem, CurListPos);
2840 if (DialogMode.Check(DMODE_SHOW) && !(Item[FocusPos]->Flags & DIF_HIDDEN))
2841 ShowDialog(FocusPos); // FocusPos
2844 return TRUE;
2847 if (FarIsEdit(Item[FocusPos]->Type)) {
2848 DlgEdit *edt = (DlgEdit *)Item[FocusPos]->ObjPtr;
2850 if (Key == KEY_CTRLL) // исключим смену режима RO для поля ввода с клавиатуры
2852 return TRUE;
2853 } else if (Key == KEY_CTRLU) {
2854 edt->SetClearFlag(0);
2855 edt->Select(-1, 0);
2856 edt->Show();
2857 return TRUE;
2858 } else if ((Item[FocusPos]->Flags & DIF_EDITOR) && !(Item[FocusPos]->Flags & DIF_READONLY)) {
2859 switch (Key) {
2860 case KEY_BS: {
2861 int CurPos = edt->GetCurPos();
2863 // В начале строки????
2864 if (!edt->GetCurPos()) {
2865 // а "выше" тоже DIF_EDITOR?
2866 if (FocusPos > 0 && (Item[FocusPos - 1]->Flags & DIF_EDITOR)) {
2867 // добавляем к предыдущему и...
2868 DlgEdit *edt_1 = (DlgEdit *)Item[FocusPos - 1]->ObjPtr;
2869 edt_1->GetString(strStr);
2870 CurPos = static_cast<int>(strStr.GetLength());
2871 FARString strAdd;
2872 edt->GetString(strAdd);
2873 strStr+= strAdd;
2874 edt_1->SetString(strStr);
2876 for (I = FocusPos + 1; I < ItemCount; I++) {
2877 if (Item[I]->Flags & DIF_EDITOR) {
2878 if (I > FocusPos) {
2879 ((DlgEdit *)(Item[I]->ObjPtr))->GetString(strStr);
2880 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(strStr);
2883 ((DlgEdit *)(Item[I]->ObjPtr))->SetString(L"");
2884 } else // ага, значит FocusPos это есть последний из DIF_EDITOR
2886 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(L"");
2887 break;
2891 Do_ProcessNextCtrl(TRUE);
2892 edt_1->SetCurPos(CurPos);
2894 } else {
2895 edt->ProcessKey(Key);
2898 ShowDialog();
2899 return TRUE;
2901 case KEY_CTRLY: {
2902 for (I = FocusPos; I < ItemCount; I++)
2903 if (Item[I]->Flags & DIF_EDITOR) {
2904 if (I > FocusPos) {
2905 ((DlgEdit *)(Item[I]->ObjPtr))->GetString(strStr);
2906 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(strStr);
2909 ((DlgEdit *)(Item[I]->ObjPtr))->SetString(L"");
2910 } else
2911 break;
2913 ShowDialog();
2914 return TRUE;
2916 case KEY_NUMDEL:
2917 case KEY_DEL: {
2919 $ 19.07.2000 SVS
2920 ! "...В редакторе команд меню нажмите home shift+end del
2921 блок не удаляется..."
2922 DEL у итемов, имеющих DIF_EDITOR, работал без учета
2923 выделения...
2925 if (FocusPos < ItemCount + 1 && (Item[FocusPos + 1]->Flags & DIF_EDITOR)) {
2926 int CurPos = edt->GetCurPos();
2927 int Length = edt->GetLength();
2928 int SelStart, SelEnd;
2929 edt->GetSelection(SelStart, SelEnd);
2930 edt->GetString(strStr);
2932 if (SelStart > -1) {
2933 FARString strEnd = strStr.CPtr() + SelEnd;
2934 strStr.Truncate(SelStart);
2935 strStr+= strEnd;
2936 edt->SetString(strStr);
2937 edt->SetCurPos(SelStart);
2938 ShowDialog();
2939 return TRUE;
2940 } else if (CurPos >= Length) {
2941 DlgEdit *edt_1 = (DlgEdit *)Item[FocusPos + 1]->ObjPtr;
2944 $ 12.09.2000 SVS
2945 Решаем проблему, если Del нажали в позиции
2946 большей, чем длина строки
2948 if (CurPos > Length) {
2949 strStr.Append(L' ', CurPos - Length);
2952 FARString strAdd;
2953 edt_1->GetString(strAdd);
2954 edt_1->SetString(strStr + strAdd);
2955 ProcessKey(KEY_CTRLY);
2956 edt->SetCurPos(CurPos);
2957 ShowDialog();
2958 return TRUE;
2962 break;
2964 case KEY_PGDN:
2965 case KEY_NUMPAD3:
2966 case KEY_PGUP:
2967 case KEY_NUMPAD9: {
2968 I = FocusPos;
2970 while (Item[I]->Flags & DIF_EDITOR)
2971 I = ChangeFocus(I, (Key == KEY_PGUP || Key == KEY_NUMPAD9) ? -1 : 1, FALSE);
2973 if (!(Item[I]->Flags & DIF_EDITOR))
2974 I = ChangeFocus(I, (Key == KEY_PGUP || Key == KEY_NUMPAD9) ? 1 : -1, FALSE);
2976 ChangeFocus2(I);
2977 ShowDialog();
2979 return TRUE;
2984 if (Key == KEY_OP_XLAT && !(Item[FocusPos]->Flags & DIF_READONLY)) {
2985 edt->SetClearFlag(0);
2986 edt->Xlat();
2988 // иначе неправильно работает ctrl-end
2989 edt->strLastStr = edt->GetStringAddr();
2990 edt->LastPartLength = static_cast<int>(edt->strLastStr.GetLength());
2992 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
2993 return TRUE;
2996 if (!(Item[FocusPos]->Flags & DIF_READONLY) || IsNavKey(Key)) {
2997 // "только что ломанулись и начинать выделение с нуля"?
2998 if ((Opt.Dialogs.EditLine & DLGEDITLINE_NEWSELONGOTFOCUS) && Item[FocusPos]->SelStart != -1
2999 && PrevFocusPos != FocusPos) { // && Item[FocusPos].SelEnd)
3001 edt->Flags().Clear(FEDITLINE_MARKINGBLOCK);
3002 PrevFocusPos = FocusPos;
3005 if (edt->ProcessKey(Key)) {
3006 if (Item[FocusPos]->Flags & DIF_READONLY)
3007 return TRUE;
3009 if ((Key == KEY_CTRLEND || Key == KEY_CTRLNUMPAD1)
3010 && edt->GetCurPos() == edt->GetLength()) {
3011 if (edt->LastPartLength == -1)
3012 edt->strLastStr = edt->GetStringAddr();
3014 strStr = edt->strLastStr;
3015 int CurCmdPartLength = static_cast<int>(strStr.GetLength());
3016 edt->HistoryGetSimilar(strStr, edt->LastPartLength);
3018 if (edt->LastPartLength == -1) {
3019 edt->strLastStr = edt->GetStringAddr();
3020 edt->LastPartLength = CurCmdPartLength;
3022 edt->DisableAC();
3023 edt->SetString(strStr);
3024 edt->Select(edt->LastPartLength, static_cast<int>(strStr.GetLength()));
3025 edt->RevertAC();
3026 Show();
3027 return TRUE;
3030 edt->LastPartLength = -1;
3032 if (Key == KEY_CTRLSHIFTEND || Key == KEY_CTRLSHIFTNUMPAD1) {
3033 edt->EnableAC();
3034 edt->AutoComplete(true, false);
3035 edt->RevertAC();
3038 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3039 return TRUE;
3041 } else if (!(Key & (KEY_ALT | KEY_RALT)))
3042 return TRUE;
3045 if (ProcessHighlighting(Key, FocusPos, FALSE))
3046 return TRUE;
3048 return (Opt.XLat.EnableForDialogs && ProcessHighlighting(Key, FocusPos, TRUE));
3051 return FALSE;
3054 void Dialog::ProcessKey(FarKey Key, unsigned ItemPos)
3056 unsigned SavedFocusPos = FocusPos;
3057 FocusPos = ItemPos;
3058 ProcessKey(Key);
3059 if (FocusPos == ItemPos)
3060 FocusPos = SavedFocusPos;
3063 //////////////////////////////////////////////////////////////////////////
3065 Public, Virtual:
3066 Обработка данных от "мыши".
3067 Перекрывает BaseInput::ProcessMouse.
3070 $ 18.08.2000 SVS
3071 + DN_MOUSECLICK
3073 int Dialog::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
3075 CriticalSectionLock Lock(CS);
3076 unsigned I;
3077 int MsX, MsY;
3078 int Type;
3079 SMALL_RECT Rect;
3081 if (!DialogMode.Check(DMODE_SHOW))
3082 return FALSE;
3084 if (DialogMode.Check(DMODE_MOUSEEVENT)) {
3085 if (!DlgProc((HANDLE)this, DN_MOUSEEVENT, 0, (LONG_PTR)MouseEvent))
3086 return TRUE;
3089 if (!DialogMode.Check(DMODE_SHOW))
3090 return FALSE;
3092 MsX = MouseEvent->dwMousePosition.X;
3093 MsY = MouseEvent->dwMousePosition.Y;
3095 // for (I=0;I<ItemCount;I++)
3096 for (I = ItemCount - 1; I != (unsigned)-1; I--) {
3097 if (Item[I]->Flags & (DIF_DISABLE | DIF_HIDDEN))
3098 continue;
3100 Type = Item[I]->Type;
3102 if (Type == DI_LISTBOX && MsY >= Y1 + Item[I]->Y1 && MsY <= Y1 + Item[I]->Y2
3103 && MsX >= X1 + Item[I]->X1 && MsX <= X1 + Item[I]->X2) {
3104 VMenu *List = Item[I]->ListPtr;
3105 int Pos = List->GetSelectPos();
3106 auto CheckedListItem = List->GetCheck(-1);
3108 if ((MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) {
3109 if (FocusPos != I) {
3110 ChangeFocus2(I);
3111 ShowDialog();
3114 if (MouseEvent->dwEventFlags != DOUBLE_CLICK
3115 && !(Item[I]->IFlags.Flags
3116 & (DLGIIF_LISTREACTIONFOCUS | DLGIIF_LISTREACTIONNOFOCUS))) {
3118 List->ProcessMouse(MouseEvent);
3119 int NewListPos = List->GetSelectPos();
3121 if (NewListPos != Pos
3122 && !SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)NewListPos)) {
3123 List->SetCheck(CheckedListItem, Pos);
3125 if (DialogMode.Check(DMODE_SHOW) && !(Item[I]->Flags & DIF_HIDDEN))
3126 ShowDialog(I); // FocusPos
3127 } else {
3128 Pos = NewListPos;
3130 } else if (!SendDlgMessage((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent)) {
3131 #if 1
3132 List->ProcessMouse(MouseEvent);
3133 int NewListPos = List->GetSelectPos();
3134 int InScroolBar =
3135 (MsX == X1 + Item[I]->X2 && MsY >= Y1 + Item[I]->Y1 && MsY <= Y1 + Item[I]->Y2)
3136 && (List->CheckFlags(VMENU_LISTBOX | VMENU_ALWAYSSCROLLBAR)
3137 || Opt.ShowMenuScrollbar);
3139 if (!InScroolBar && // вне скроллбара и
3140 NewListPos != Pos && // позиция изменилась и
3141 !SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)NewListPos)) // и плагин сказал в морг
3143 List->SetCheck(CheckedListItem, Pos);
3145 if (DialogMode.Check(DMODE_SHOW) && !(Item[I]->Flags & DIF_HIDDEN))
3146 ShowDialog(I); // FocusPos
3147 } else {
3148 Pos = NewListPos;
3150 if (!InScroolBar && !(Item[I]->Flags & DIF_LISTNOCLOSE)) {
3151 ExitCode = I;
3152 CloseDialog();
3153 return TRUE;
3157 #else
3159 if (SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)Pos)) {
3160 if (MsX == X1 + Item[I]->X2 && MsY >= Y1 + Item[I]->Y1 && MsY <= Y1 + Item[I]->Y2)
3161 List->ProcessMouse(MouseEvent); // забыл проверить на клик на скролбар (KM)
3162 else
3163 ProcessKey(KEY_ENTER, I);
3166 #endif
3169 return TRUE;
3170 } else {
3171 if (!MouseEvent->dwButtonState
3172 || SendDlgMessage((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent)) {
3173 if ((I == FocusPos && (Item[I]->IFlags.Flags & DLGIIF_LISTREACTIONFOCUS))
3174 || (I != FocusPos && (Item[I]->IFlags.Flags & DLGIIF_LISTREACTIONNOFOCUS))) {
3175 List->ProcessMouse(MouseEvent);
3176 int NewListPos = List->GetSelectPos();
3178 if (NewListPos != Pos
3179 && !SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)NewListPos)) {
3180 List->SetCheck(CheckedListItem, Pos);
3182 if (DialogMode.Check(DMODE_SHOW) && !(Item[I]->Flags & DIF_HIDDEN))
3183 ShowDialog(I); // FocusPos
3184 } else
3185 Pos = NewListPos;
3190 return TRUE;
3194 if (MsX < X1 || MsY < Y1 || MsX > X2 || MsY > Y2) {
3195 if (DialogMode.Check(DMODE_CLICKOUTSIDE)
3196 && !DlgProc((HANDLE)this, DN_MOUSECLICK, -1, (LONG_PTR)MouseEvent)) {
3197 if (!DialogMode.Check(DMODE_SHOW))
3198 return FALSE;
3200 // if (!(MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) && PrevLButtonPressed && ScreenObject::CaptureMouseObject)
3201 if (!(MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
3202 && (PrevMouseButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
3203 && (Opt.Dialogs.MouseButton & DMOUSEBUTTON_LEFT))
3204 ProcessKey(KEY_ESC);
3205 // else if (!(MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) && PrevRButtonPressed && ScreenObject::CaptureMouseObject)
3206 else if (!(MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED)
3207 && (PrevMouseButtonState & RIGHTMOST_BUTTON_PRESSED)
3208 && (Opt.Dialogs.MouseButton & DMOUSEBUTTON_RIGHT))
3209 ProcessKey(KEY_ENTER);
3212 if (MouseEvent->dwButtonState)
3213 DialogMode.Set(DMODE_CLICKOUTSIDE);
3215 // ScreenObject::SetCapture(this);
3216 return TRUE;
3219 if (!MouseEvent->dwButtonState) {
3220 DialogMode.Clear(DMODE_CLICKOUTSIDE);
3221 // ScreenObject::SetCapture(nullptr);
3222 return FALSE;
3225 if (!MouseEvent->dwEventFlags || MouseEvent->dwEventFlags == DOUBLE_CLICK) {
3226 // первый цикл - все за исключением рамок.
3227 // for (I=0; I < ItemCount;I++)
3228 for (I = ItemCount - 1; I != (unsigned)-1; I--) {
3229 if (Item[I]->Flags & (DIF_DISABLE | DIF_HIDDEN))
3230 continue;
3232 GetItemRect(I, Rect);
3233 Rect.Left+= X1;
3234 Rect.Top+= Y1;
3235 Rect.Right+= X1;
3236 Rect.Bottom+= Y1;
3237 //_D(SysLog(L"? %2d) Rect (%2d,%2d) (%2d,%2d) '%ls'",I,Rect.left,Rect.top,Rect.right,Rect.bottom,Item[I].Data));
3239 if (MsX >= Rect.Left && MsY >= Rect.Top && MsX <= Rect.Right && MsY <= Rect.Bottom) {
3240 // для прозрачных :-)
3241 if (Item[I]->Type == DI_SINGLEBOX || Item[I]->Type == DI_DOUBLEBOX) {
3242 // если на рамке, то...
3243 if (((MsX == Rect.Left || MsX == Rect.Right) && MsY >= Rect.Top && MsY <= Rect.Bottom)
3244 || // vert
3245 ((MsY == Rect.Top || MsY == Rect.Bottom) && MsX >= Rect.Left
3246 && MsX <= Rect.Right)) // hor
3248 if (DlgProc((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent))
3249 return TRUE;
3251 if (!DialogMode.Check(DMODE_SHOW))
3252 return FALSE;
3253 } else
3254 continue;
3257 if (Item[I]->Type == DI_USERCONTROL) {
3258 // для user-типа подготовим координаты мыши
3259 MouseEvent->dwMousePosition.X-= Rect.Left;
3260 MouseEvent->dwMousePosition.Y-= Rect.Top;
3263 //_SVS(SysLog(L"+ %2d) Rect (%2d,%2d) (%2d,%2d) '%ls' Dbl=%d",I,Rect.left,Rect.top,Rect.right,Rect.bottom,Item[I].Data,MouseEvent->dwEventFlags==DOUBLE_CLICK));
3264 if (DlgProc((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent))
3265 return TRUE;
3267 if (!DialogMode.Check(DMODE_SHOW))
3268 return TRUE;
3270 if (Item[I]->Type == DI_USERCONTROL) {
3271 ChangeFocus2(I);
3272 ShowDialog();
3273 return TRUE;
3276 break;
3280 if ((MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) {
3281 // for (I=0;I<ItemCount;I++)
3283 for (I = ItemCount - 1; I != (unsigned)-1; I--) {
3284 // Исключаем из списка оповещаемых о мыши недоступные элементы
3285 if (Item[I]->Flags & (DIF_DISABLE | DIF_HIDDEN))
3286 continue;
3288 Type = Item[I]->Type;
3290 GetItemRect(I, Rect);
3291 Rect.Left+= X1;
3292 Rect.Top+= Y1;
3293 Rect.Right+= X1;
3294 Rect.Bottom+= Y1;
3295 if (ItemHasDropDownArrow(Item[I]))
3296 Rect.Right++;
3298 if (MsX >= Rect.Left && MsY >= Rect.Top && MsX <= Rect.Right && MsY <= Rect.Bottom) {
3299 /* ********************************************************** */
3300 if (FarIsEdit(Type)) {
3302 $ 15.08.2000 SVS
3303 + Сделаем так, чтобы ткнув мышкой в DropDownList
3304 список раскрывался сам.
3305 Есть некоторая глюкавость - когда список раскрыт и мы
3306 мышой переваливаем на другой элемент, то список закрывается
3307 но перехода реального на указанный элемент диалога не происходит
3309 int EditX1, EditY1, EditX2, EditY2;
3310 DlgEdit *EditLine = (DlgEdit *)(Item[I]->ObjPtr);
3311 EditLine->GetPosition(EditX1, EditY1, EditX2, EditY2);
3313 if (MsY == EditY1 && Type == DI_COMBOBOX && (Item[I]->Flags & DIF_DROPDOWNLIST)
3314 && MsX >= EditX1 && MsX <= EditX2 + 1) {
3315 EditLine->SetClearFlag(0);
3317 ChangeFocus2(I);
3318 ShowDialog();
3320 ProcessOpenComboBox(Item[I]->Type, Item[I], I);
3322 return TRUE;
3325 ChangeFocus2(I);
3327 if (EditLine->ProcessMouse(MouseEvent)) {
3328 EditLine->SetClearFlag(0); // а может это делать в самом edit?
3331 $ 23.06.2001 KM
3332 ! Оказалось нужно перерисовывать весь диалог иначе
3333 не снимался признак активности с комбобокса с которго уходим.
3335 ShowDialog(); // нужен ли только один контрол или весь диалог?
3336 return TRUE;
3337 } else {
3338 // Проверка на DI_COMBOBOX здесь лишняя. Убрана (KM).
3339 if (MsX == EditX2 + 1 && MsY == EditY1 && ItemHasDropDownArrow(Item[I])) {
3340 EditLine->SetClearFlag(0); // раз уж покусились на, то и...
3342 ChangeFocus2(I);
3344 if (!(Item[I]->Flags & DIF_HIDDEN))
3345 ShowDialog(I);
3347 ProcessOpenComboBox(Item[I]->Type, Item[I], I);
3349 return TRUE;
3354 /* ********************************************************** */
3355 if (Type == DI_BUTTON && MsY == Y1 + Item[I]->Y1
3356 && MsX < X1 + Item[I]->X1 + HiStrCellsCount(Item[I]->strData)) {
3357 ChangeFocus2(I);
3358 ShowDialog();
3360 while (IsMouseButtonPressed())
3363 if (MouseX < X1 || MouseX > X1 + Item[I]->X1 + HiStrCellsCount(Item[I]->strData) + 4
3364 || MouseY != Y1 + Item[I]->Y1) {
3365 ChangeFocus2(I);
3366 ShowDialog();
3368 return TRUE;
3371 ProcessKey(KEY_ENTER, I);
3372 return TRUE;
3375 /* ********************************************************** */
3376 if ((Type == DI_CHECKBOX || Type == DI_RADIOBUTTON) && MsY == Y1 + Item[I]->Y1
3377 && MsX < (X1 + Item[I]->X1 + HiStrCellsCount(Item[I]->strData) + 4
3378 - ((Item[I]->Flags & DIF_MOVESELECT) != 0))) {
3379 ChangeFocus2(I);
3380 ProcessKey(KEY_SPACE, I);
3381 return TRUE;
3384 } // for (I=0;I<ItemCount;I++)
3386 // ДЛЯ MOUSE-Перемещалки:
3387 // Сюда попадаем в том случае, если мышь не попала на активные элементы
3390 if (DialogMode.Check(DMODE_ISCANMOVE)) {
3391 // DialogMode.Set(DMODE_DRAGGED);
3392 OldX1 = X1;
3393 OldX2 = X2;
3394 OldY1 = Y1;
3395 OldY2 = Y2;
3396 // запомним delta места хватания и Left-Top диалогового окна
3397 MsX = abs(X1 - MouseX);
3398 MsY = abs(Y1 - MouseY);
3399 int NeedSendMsg = 0;
3401 for (;;) {
3402 DWORD Mb = IsMouseButtonPressed();
3403 int mx, my, X0, Y0;
3405 if (Mb == FROM_LEFT_1ST_BUTTON_PRESSED) // still dragging
3407 int AdjX = 0, AdjY = 0;
3408 int OX1 = X1;
3409 int OY1 = Y1;
3410 int NX1 = X0 = X1;
3411 int NX2 = X2;
3412 int NY1 = Y0 = Y1;
3413 int NY2 = Y2;
3415 if (MouseX == PrevMouseX)
3416 mx = X1;
3417 else
3418 mx = MouseX - MsX;
3420 if (MouseY == PrevMouseY)
3421 my = Y1;
3422 else
3423 my = MouseY - MsY;
3425 NX2 = mx + (X2 - X1);
3426 NX1 = mx;
3427 AdjX = NX1 - X0;
3428 NY2 = my + (Y2 - Y1);
3429 NY1 = my;
3430 AdjY = NY1 - Y0;
3432 // "А был ли мальчик?" (про холостой ход)
3433 if (OX1 != NX1 || OY1 != NY1) {
3434 if (!NeedSendMsg) // тыкс, а уже посылку делали в диалоговую процедуру?
3436 NeedSendMsg++;
3438 if (!DlgProc((HANDLE)this, DN_DRAGGED, 0, 0)) // а может нас обломали?
3439 break; // валим отсель...плагин сказал - в морг перемещения
3441 if (!DialogMode.Check(DMODE_SHOW))
3442 break;
3445 // Да, мальчик был. Зачнем...
3447 LockScreen LckScr;
3448 Hide();
3449 X1 = NX1;
3450 X2 = NX2;
3451 Y1 = NY1;
3452 Y2 = NY2;
3454 if (AdjX || AdjY)
3455 AdjustEditPos(AdjX, AdjY); //?
3457 Show();
3460 } else if (Mb == RIGHTMOST_BUTTON_PRESSED) // abort
3462 LockScreen LckScr;
3463 Hide();
3464 AdjustEditPos(OldX1 - X1, OldY1 - Y1);
3465 X1 = OldX1;
3466 X2 = OldX2;
3467 Y1 = OldY1;
3468 Y2 = OldY2;
3469 DialogMode.Clear(DMODE_DRAGGED);
3470 DlgProc((HANDLE)this, DN_DRAGGED, 1, TRUE);
3472 if (DialogMode.Check(DMODE_SHOW))
3473 Show();
3475 break;
3476 } else // release key, drop dialog
3478 if (OldX1 != X1 || OldX2 != X2 || OldY1 != Y1 || OldY2 != Y2) {
3479 LockScreen LckScr;
3480 DialogMode.Clear(DMODE_DRAGGED);
3481 DlgProc((HANDLE)this, DN_DRAGGED, 1, 0);
3483 if (DialogMode.Check(DMODE_SHOW))
3484 Show();
3487 break;
3489 } // while (1)
3494 return FALSE;
3497 int Dialog::ProcessOpenComboBox(int Type, DialogItemEx *CurItem, unsigned CurFocusPos)
3499 CriticalSectionLock Lock(CS);
3500 FARString strStr;
3501 DlgEdit *CurEditLine;
3503 // для user-типа вываливаем
3504 if (Type == DI_USERCONTROL)
3505 return TRUE;
3507 CurEditLine = ((DlgEdit *)(CurItem->ObjPtr));
3509 if (FarIsEdit(Type) && (CurItem->Flags & DIF_HISTORY) && Opt.Dialogs.EditHistory
3510 && !CurItem->strHistory.IsEmpty() && !(CurItem->Flags & DIF_READONLY)) {
3511 // Передаем то, что в строке ввода в функцию выбора из истории для выделения нужного пункта в истории.
3512 CurEditLine->GetString(strStr);
3513 SelectFromEditHistory(CurItem, CurEditLine, CurItem->strHistory, strStr);
3515 // $ 18.07.2000 SVS: +обработка DI_COMBOBOX - выбор из списка!
3516 else if (Type == DI_COMBOBOX && CurItem->ListPtr && !(CurItem->Flags & DIF_READONLY)
3517 && CurItem->ListPtr->GetItemCount() > 0) //??
3519 SelectFromComboBox(CurItem, CurEditLine, CurItem->ListPtr);
3522 return TRUE;
3525 unsigned Dialog::ProcessRadioButton(unsigned CurRB)
3527 CriticalSectionLock Lock(CS);
3528 unsigned PrevRB = CurRB, J;
3529 unsigned I;
3531 for (I = CurRB;; I--) {
3532 if (!I)
3533 break;
3535 if (Item[I]->Type == DI_RADIOBUTTON && (Item[I]->Flags & DIF_GROUP))
3536 break;
3538 if (Item[I - 1]->Type != DI_RADIOBUTTON)
3539 break;
3542 do {
3544 $ 28.07.2000 SVS
3545 При изменении состояния каждого элемента посылаем сообщение
3546 посредством функции SendDlgMessage - в ней делается все!
3548 J = Item[I]->Selected;
3549 Item[I]->Selected = 0;
3551 if (J) {
3552 PrevRB = I;
3555 ++I;
3556 } while (I < ItemCount && Item[I]->Type == DI_RADIOBUTTON && !(Item[I]->Flags & DIF_GROUP));
3558 Item[CurRB]->Selected = 1;
3561 $ 28.07.2000 SVS
3562 При изменении состояния каждого элемента посылаем сообщение
3563 посредством функции SendDlgMessage - в ней делается все!
3565 if (!SendDlgMessage((HANDLE)this, DN_BTNCLICK, PrevRB, 0)
3566 || !SendDlgMessage((HANDLE)this, DN_BTNCLICK, CurRB, 1)) {
3567 // вернем назад, если пользователь не захотел...
3568 Item[CurRB]->Selected = 0;
3569 Item[PrevRB]->Selected = 1;
3570 return PrevRB;
3573 return CurRB;
3576 int Dialog::Do_ProcessFirstCtrl()
3578 CriticalSectionLock Lock(CS);
3580 if (FarIsEdit(Item[FocusPos]->Type)) {
3581 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(KEY_HOME);
3582 return TRUE;
3583 } else {
3584 for (unsigned I = 0; I < ItemCount; I++)
3585 if (CanGetFocus(Item[I]->Type)) {
3586 ChangeFocus2(I);
3587 ShowDialog();
3588 break;
3592 return TRUE;
3595 int Dialog::Do_ProcessNextCtrl(int Up, BOOL IsRedraw)
3597 CriticalSectionLock Lock(CS);
3598 unsigned OldPos = FocusPos;
3599 unsigned PrevPos = 0;
3601 if (FarIsEdit(Item[FocusPos]->Type) && (Item[FocusPos]->Flags & DIF_EDITOR))
3602 PrevPos = ((DlgEdit *)(Item[FocusPos]->ObjPtr))->GetCurPos();
3604 unsigned I = ChangeFocus(FocusPos, Up ? -1 : 1, FALSE);
3605 Item[FocusPos]->Focus = 0;
3606 Item[I]->Focus = 1;
3607 ChangeFocus2(I);
3609 if (FarIsEdit(Item[I]->Type) && (Item[I]->Flags & DIF_EDITOR))
3610 ((DlgEdit *)(Item[I]->ObjPtr))->SetCurPos(PrevPos);
3612 if (Item[FocusPos]->Type == DI_RADIOBUTTON && (Item[I]->Flags & DIF_MOVESELECT))
3613 ProcessKey(KEY_SPACE);
3614 else if (IsRedraw) {
3615 ShowDialog(OldPos);
3616 ShowDialog(FocusPos);
3619 return TRUE;
3622 int Dialog::Do_ProcessTab(int Next)
3624 CriticalSectionLock Lock(CS);
3625 unsigned I;
3627 if (ItemCount > 1) {
3628 // Must check for DI_EDIT since DIF_EDITOR and DIF_LISTNOAMPERSAND are equal
3629 if (Item[FocusPos]->Type==DI_EDIT && (Item[FocusPos]->Flags & DIF_EDITOR)) {
3630 I = FocusPos;
3632 while (Item[I]->Type==DI_EDIT && (Item[I]->Flags & DIF_EDITOR))
3633 I = ChangeFocus(I, Next ? 1 : -1, TRUE);
3634 } else {
3635 I = ChangeFocus(FocusPos, Next ? 1 : -1, TRUE);
3637 if (!Next)
3638 while (I > 0
3639 && Item[I]->Type == DI_EDIT && Item[I - 1]->Type == DI_EDIT
3640 && (Item[I]->Flags & DIF_EDITOR) && (Item[I - 1]->Flags & DIF_EDITOR)
3641 && !((DlgEdit *)Item[I]->ObjPtr)->GetLength())
3642 I--;
3644 } else
3645 I = FocusPos;
3647 ChangeFocus2(I);
3648 ShowDialog();
3650 return TRUE;
3653 int Dialog::Do_ProcessSpace()
3655 CriticalSectionLock Lock(CS);
3656 int OldFocusPos;
3658 if (Item[FocusPos]->Type == DI_CHECKBOX) {
3659 int OldSelected = Item[FocusPos]->Selected;
3661 if (Item[FocusPos]->Flags & DIF_3STATE) {
3662 Item[FocusPos]->Selected = (Item[FocusPos]->Selected + 1) % 3;
3663 } else
3664 Item[FocusPos]->Selected = !Item[FocusPos]->Selected;
3666 OldFocusPos = FocusPos;
3668 if (!SendDlgMessage((HANDLE)this, DN_BTNCLICK, FocusPos, Item[FocusPos]->Selected))
3669 Item[OldFocusPos]->Selected = OldSelected;
3671 ShowDialog();
3672 return TRUE;
3673 } else if (Item[FocusPos]->Type == DI_RADIOBUTTON) {
3674 FocusPos = ProcessRadioButton(FocusPos);
3675 ShowDialog();
3676 return TRUE;
3677 } else if (FarIsEdit(Item[FocusPos]->Type) && !(Item[FocusPos]->Flags & DIF_READONLY)) {
3678 if (((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(KEY_SPACE)) {
3679 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3682 return TRUE;
3685 return TRUE;
3688 //////////////////////////////////////////////////////////////////////////
3690 Private:
3691 Изменяет фокус ввода (воздействие клавишами
3692 KEY_TAB, KEY_SHIFTTAB, KEY_UP, KEY_DOWN,
3693 а так же Alt-HotKey)
3696 $ 28.07.2000 SVS
3697 Довесок для сообщений DN_KILLFOCUS & DN_SETFOCUS
3700 $ 24.08.2000 SVS
3701 Добавка для DI_USERCONTROL
3703 unsigned Dialog::ChangeFocus(unsigned CurFocusPos, int Step, int SkipGroup)
3705 CriticalSectionLock Lock(CS);
3706 int Type;
3707 unsigned OrigFocusPos = CurFocusPos;
3708 // int FucusPosNeed=-1;
3709 // В функцию обработки диалога здесь передаем сообщение,
3710 // что элемент - LostFocus() - теряет фокус ввода.
3711 // if(DialogMode.Check(DMODE_INITOBJECTS))
3712 // FucusPosNeed=DlgProc((HANDLE)this,DN_KILLFOCUS,FocusPos,0);
3713 // if(FucusPosNeed != -1 && CanGetFocus(Item[FucusPosNeed].Type))
3714 // FocusPos=FucusPosNeed;
3715 // else
3717 for (;;) {
3718 CurFocusPos+= Step;
3720 if ((int)CurFocusPos < 0)
3721 CurFocusPos = ItemCount - 1;
3723 if (CurFocusPos >= ItemCount)
3724 CurFocusPos = 0;
3726 Type = Item[CurFocusPos]->Type;
3728 if (!(Item[CurFocusPos]->Flags & (DIF_NOFOCUS | DIF_DISABLE | DIF_HIDDEN))) {
3729 if (Type == DI_LISTBOX || Type == DI_BUTTON || Type == DI_CHECKBOX || FarIsEdit(Type)
3730 || Type == DI_USERCONTROL)
3731 break;
3733 if (Type == DI_RADIOBUTTON && (!SkipGroup || Item[CurFocusPos]->Selected))
3734 break;
3737 // убираем зацикливание с последующим подвисанием :-)
3738 if (OrigFocusPos == CurFocusPos)
3739 break;
3742 // Dialog::FocusPos=FocusPos;
3743 // В функцию обработки диалога здесь передаем сообщение,
3744 // что элемент GotFocus() - получил фокус ввода.
3745 // Игнорируем возвращаемое функцией диалога значение
3746 // if(DialogMode.Check(DMODE_INITOBJECTS))
3747 // DlgProc((HANDLE)this,DN_GOTFOCUS,FocusPos,0);
3748 return (CurFocusPos);
3751 //////////////////////////////////////////////////////////////////////////
3753 Private:
3754 Изменяет фокус ввода между двумя элементами.
3755 Вынесен отдельно с тем, чтобы обработать DN_KILLFOCUS & DM_SETFOCUS
3757 void Dialog::ChangeFocus2(unsigned SetFocusPos)
3759 CriticalSectionLock Lock(CS);
3760 int FocusPosNeed = -1;
3762 if (!(Item[SetFocusPos]->Flags & (DIF_NOFOCUS | DIF_DISABLE | DIF_HIDDEN))) {
3763 if (DialogMode.Check(DMODE_INITOBJECTS)) {
3764 FocusPosNeed = (int)DlgProc((HANDLE)this, DN_KILLFOCUS, FocusPos, 0);
3766 if (!DialogMode.Check(DMODE_SHOW))
3767 return;
3770 if (FocusPosNeed != -1 && CanGetFocus(Item[FocusPosNeed]->Type))
3771 SetFocusPos = FocusPosNeed;
3773 Item[FocusPos]->Focus = 0;
3775 // "снимать выделение при потере фокуса?"
3776 if (FarIsEdit(Item[FocusPos]->Type)
3777 && !(Item[FocusPos]->Type == DI_COMBOBOX && (Item[FocusPos]->Flags & DIF_DROPDOWNLIST))) {
3778 DlgEdit *EditPtr = (DlgEdit *)Item[FocusPos]->ObjPtr;
3779 EditPtr->GetSelection(Item[FocusPos]->SelStart, Item[FocusPos]->SelEnd);
3781 if ((Opt.Dialogs.EditLine & DLGEDITLINE_CLEARSELONKILLFOCUS)) {
3782 EditPtr->Select(-1, 0);
3786 Item[SetFocusPos]->Focus = 1;
3788 // "не восстанавливать выделение при получении фокуса?"
3789 if (FarIsEdit(Item[SetFocusPos]->Type)
3790 && !(Item[SetFocusPos]->Type == DI_COMBOBOX
3791 && (Item[SetFocusPos]->Flags & DIF_DROPDOWNLIST))) {
3792 DlgEdit *EditPtr = (DlgEdit *)Item[SetFocusPos]->ObjPtr;
3794 if (!(Opt.Dialogs.EditLine & DLGEDITLINE_NOTSELONGOTFOCUS)) {
3795 if (Opt.Dialogs.EditLine & DLGEDITLINE_SELALLGOTFOCUS)
3796 EditPtr->Select(0, EditPtr->GetStrSize());
3797 else
3798 EditPtr->Select(Item[SetFocusPos]->SelStart, Item[SetFocusPos]->SelEnd);
3799 } else {
3800 EditPtr->Select(-1, 0);
3803 // при получении фокуса ввода переместить курсор в конец строки?
3804 if (Opt.Dialogs.EditLine & DLGEDITLINE_GOTOEOLGOTFOCUS) {
3805 EditPtr->SetCurPos(EditPtr->GetStrSize());
3809 // проинформируем листбокс, есть ли у него фокус
3810 if (Item[FocusPos]->Type == DI_LISTBOX)
3811 Item[FocusPos]->ListPtr->ClearFlags(VMENU_LISTHASFOCUS);
3813 if (Item[SetFocusPos]->Type == DI_LISTBOX)
3814 Item[SetFocusPos]->ListPtr->SetFlags(VMENU_LISTHASFOCUS);
3816 SelectOnEntry(FocusPos, FALSE);
3817 SelectOnEntry(SetFocusPos, TRUE);
3819 PrevFocusPos = FocusPos;
3820 FocusPos = SetFocusPos;
3822 if (DialogMode.Check(DMODE_INITOBJECTS))
3823 DlgProc((HANDLE)this, DN_GOTFOCUS, FocusPos, 0);
3828 Функция SelectOnEntry - выделение строки редактирования
3829 Обработка флага DIF_SELECTONENTRY
3831 void Dialog::SelectOnEntry(unsigned Pos, BOOL Selected)
3833 // if(!DialogMode.Check(DMODE_SHOW))
3834 // return;
3835 if (FarIsEdit(Item[Pos]->Type) && (Item[Pos]->Flags & DIF_SELECTONENTRY)
3836 // && PrevFocusPos != -1 && PrevFocusPos != Pos
3838 DlgEdit *edt = (DlgEdit *)Item[Pos]->ObjPtr;
3840 if (edt) {
3841 if (Selected)
3842 edt->Select(0, edt->GetLength());
3843 else
3844 edt->Select(-1, 0);
3846 //_SVS(SysLog(L"Selected=%d edt->GetLength()=%d",Selected,edt->GetLength()));
3851 int Dialog::SetAutomation(WORD IDParent, WORD id, FarDialogItemFlags UncheckedSet,
3852 FarDialogItemFlags UncheckedSkip, FarDialogItemFlags CheckedSet, FarDialogItemFlags CheckedSkip,
3853 FarDialogItemFlags Checked3Set, FarDialogItemFlags Checked3Skip)
3855 CriticalSectionLock Lock(CS);
3856 int Ret = FALSE;
3858 if (IDParent < ItemCount && (Item[IDParent]->Flags & DIF_AUTOMATION) && id < ItemCount
3859 && IDParent != id) // Сами себя не юзаем!
3861 Ret = Item[IDParent]->AddAutomation(id, UncheckedSet, UncheckedSkip, CheckedSet, CheckedSkip,
3862 Checked3Set, Checked3Skip);
3865 return Ret;
3868 //////////////////////////////////////////////////////////////////////////
3870 Private:
3871 Заполняем выпадающий список для ComboBox
3873 int Dialog::SelectFromComboBox(DialogItemEx *CurItem,
3874 DlgEdit *EditLine, // строка редактирования
3875 VMenu *ComboBox) // список строк
3877 CriticalSectionLock Lock(CS);
3878 // char *Str;
3879 FARString strStr;
3880 int EditX1, EditY1, EditX2, EditY2;
3881 int I, Dest, OriginalPos;
3882 unsigned CurFocusPos = FocusPos;
3883 // if((Str=(char*)malloc(MaxLen)) )
3885 EditLine->GetPosition(EditX1, EditY1, EditX2, EditY2);
3887 if (EditX2 - EditX1 < 20)
3888 EditX2 = EditX1 + 20;
3890 SetDropDownOpened(TRUE); // Установим флаг "открытия" комбобокса.
3891 SetComboBoxPos(CurItem);
3892 // Перед отрисовкой спросим об изменении цветовых атрибутов
3893 BYTE RealColors[VMENU_COLOR_COUNT];
3894 FarListColors ListColors = {0};
3895 ListColors.ColorCount = VMENU_COLOR_COUNT;
3896 ListColors.Colors = RealColors;
3897 ComboBox->SetColors(nullptr);
3898 ComboBox->GetColors(&ListColors);
3900 if (DlgProc((HANDLE)this, DN_CTLCOLORDLGLIST, CurItem->ID, (LONG_PTR)&ListColors))
3901 ComboBox->SetColors(&ListColors);
3903 // Выставим то, что есть в строке ввода!
3904 // if(EditLine->GetDropDownBox()) //???
3905 EditLine->GetString(strStr);
3907 if (CurItem->Flags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND))
3908 HiText2Str(strStr, strStr);
3910 ComboBox->SetSelectPos(ComboBox->FindItem(0, strStr, LIFIND_EXACTMATCH), 1);
3911 ComboBox->Show();
3912 OriginalPos = Dest = ComboBox->GetSelectPos();
3913 CurItem->IFlags.Set(DLGIIF_COMBOBOXNOREDRAWEDIT);
3915 while (!ComboBox->Done()) {
3916 if (!GetDropDownOpened()) {
3917 ComboBox->ProcessKey(KEY_ESC);
3918 continue;
3921 INPUT_RECORD ReadRec;
3922 FarKey Key = ComboBox->ReadInput(&ReadRec);
3924 if (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTKEY) && ReadRec.EventType == KEY_EVENT) {
3925 if (DlgProc((HANDLE)this, DN_KEY, FocusPos, Key))
3926 continue;
3927 } else if (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTMOUSE) && ReadRec.EventType == MOUSE_EVENT)
3928 if (!DlgProc((HANDLE)this, DN_MOUSEEVENT, 0, (LONG_PTR)&ReadRec.Event.MouseEvent))
3929 continue;
3931 // здесь можно добавить что-то свое, например,
3932 I = ComboBox->GetSelectPos();
3934 if (Key == KEY_TAB) // Tab в списке - аналог Enter
3936 ComboBox->ProcessKey(KEY_ENTER);
3937 continue; //??
3940 if (I != Dest) {
3941 if (!DlgProc((HANDLE)this, DN_LISTCHANGE, CurFocusPos, I))
3942 ComboBox->SetSelectPos(Dest, Dest < I ? -1 : 1); //????
3943 else
3944 Dest = I;
3946 #if 0
3948 // во время навигации по DropDown листу - отобразим ЭТО дело в
3949 // связанной строке
3950 // ВНИМАНИЕ!!!
3951 // Очень медленная реакция!
3952 if (EditLine->GetDropDownBox())
3954 MenuItem *CurCBItem=ComboBox->GetItemPtr();
3955 EditLine->SetString(CurCBItem->Name);
3956 EditLine->Show();
3957 //EditLine->FastShow();
3960 #endif
3963 // обработку multiselect ComboBox
3964 // ...
3965 ComboBox->ProcessInput();
3968 CurItem->IFlags.Clear(DLGIIF_COMBOBOXNOREDRAWEDIT);
3969 ComboBox->ClearDone();
3970 ComboBox->Hide();
3972 if (GetDropDownOpened()) // Закрылся не программным путём?
3973 Dest = ComboBox->Modal::GetExitCode();
3974 else
3975 Dest = -1;
3977 if (Dest == -1)
3978 ComboBox->SetSelectPos(OriginalPos, 0); //????
3980 SetDropDownOpened(FALSE); // Установим флаг "закрытия" комбобокса.
3982 if (Dest < 0) {
3983 Redraw();
3984 // free(Str);
3985 return KEY_ESC;
3988 // ComboBox->GetUserData(Str,MaxLen,Dest);
3989 MenuItemEx *ItemPtr = ComboBox->GetItemPtr(Dest);
3991 if (CurItem->Flags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND)) {
3992 HiText2Str(strStr, ItemPtr->strName);
3993 EditLine->SetString(strStr);
3994 } else
3995 EditLine->SetString(ItemPtr->strName);
3997 EditLine->SetLeftPos(0);
3998 Redraw();
3999 // free(Str);
4000 return KEY_ENTER;
4002 // return KEY_ESC;
4005 //////////////////////////////////////////////////////////////////////////
4007 Private:
4008 Заполняем выпадающий список из истории
4010 BOOL Dialog::SelectFromEditHistory(DialogItemEx *CurItem, DlgEdit *EditLine, const wchar_t *HistoryName,
4011 FARString &strIStr)
4013 CriticalSectionLock Lock(CS);
4015 if (!EditLine)
4016 return FALSE;
4018 FARString strStr;
4019 int ret = 0;
4020 FARString strRegKey = fmtSavedDialogHistory;
4021 strRegKey+= HistoryName;
4022 History DlgHist(HISTORYTYPE_DIALOG, Opt.DialogsHistoryCount, strRegKey.GetMB(), &Opt.Dialogs.EditHistory,
4023 false);
4024 DlgHist.ResetPosition();
4026 // создание пустого вертикального меню
4027 VMenu HistoryMenu(L"", nullptr, 0, Opt.Dialogs.CBoxMaxHeight,
4028 VMENU_ALWAYSSCROLLBAR | VMENU_COMBOBOX | VMENU_NOTCHANGE);
4029 HistoryMenu.SetFlags(VMENU_SHOWAMPERSAND);
4030 HistoryMenu.SetBoxType(SHORT_SINGLE_BOX);
4031 SetDropDownOpened(TRUE); // Установим флаг "открытия" комбобокса.
4032 // запомним (для прорисовки)
4033 CurItem->ListPtr = &HistoryMenu;
4034 ret = DlgHist.Select(HistoryMenu, Opt.Dialogs.CBoxMaxHeight, this, strStr);
4035 // забудим (не нужен)
4036 CurItem->ListPtr = nullptr;
4037 SetDropDownOpened(FALSE); // Установим флаг "закрытия" комбобокса.
4040 if (ret > 0) {
4041 EditLine->SetString(strStr);
4042 EditLine->SetLeftPos(0);
4043 EditLine->SetClearFlag(0);
4044 Redraw();
4045 return TRUE;
4048 return FALSE;
4051 //////////////////////////////////////////////////////////////////////////
4053 Private:
4054 Работа с историей - добавление и reorder списка
4056 int Dialog::AddToEditHistory(const wchar_t *AddStr, const wchar_t *HistoryName)
4058 CriticalSectionLock Lock(CS);
4060 if (!*AddStr) {
4061 return FALSE;
4064 FARString strRegKey = fmtSavedDialogHistory;
4065 strRegKey+= HistoryName;
4066 History DlgHist(HISTORYTYPE_DIALOG, Opt.DialogsHistoryCount, strRegKey.GetMB(), &Opt.Dialogs.EditHistory,
4067 false);
4068 DlgHist.AddToHistory(AddStr);
4069 return TRUE;
4072 int Dialog::CheckHighlights(WORD CheckSymbol, int StartPos)
4074 CriticalSectionLock Lock(CS);
4075 int Type, I;
4076 DWORD Flags;
4078 if (StartPos < 0)
4079 StartPos = 0;
4081 for (I = StartPos; I < (int)ItemCount; I++) {
4082 Type = Item[I]->Type;
4083 Flags = Item[I]->Flags;
4085 if ((!FarIsEdit(Type) || (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST)))
4086 && !(Flags & (DIF_SHOWAMPERSAND | DIF_DISABLE | DIF_HIDDEN))) {
4087 const wchar_t *ChPtr = wcschr(Item[I]->strData, L'&');
4089 if (ChPtr) {
4090 WORD Ch = ChPtr[1];
4092 if (Ch && Upper(CheckSymbol) == Upper(Ch))
4093 return I;
4094 } else if (!CheckSymbol)
4095 return I;
4099 return -1;
4102 //////////////////////////////////////////////////////////////////////////
4104 Private:
4105 Если жмакнули Alt-???
4107 int Dialog::ProcessHighlighting(FarKey Key, unsigned FocusPos, int Translate)
4109 CriticalSectionLock Lock(CS);
4110 int Type;
4111 DWORD Flags;
4113 for (unsigned I = 0; I < ItemCount; I++) {
4114 Type = Item[I]->Type;
4115 Flags = Item[I]->Flags;
4117 if ((!FarIsEdit(Type) || (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST)))
4118 && !(Flags & (DIF_SHOWAMPERSAND | DIF_DISABLE | DIF_HIDDEN)))
4119 if (IsKeyHighlighted(Item[I]->strData, Key, Translate)) {
4120 int DisableSelect = FALSE;
4122 // Если ЭТО: DlgEdit(пред контрол) и DI_TEXT в одну строку, то...
4123 if (I > 0 && Type == DI_TEXT && // DI_TEXT
4124 FarIsEdit(Item[I - 1]->Type) && // и редактор
4125 Item[I]->Y1 == Item[I - 1]->Y1 && // и оба в одну строку
4126 (I + 1 < ItemCount && Item[I]->Y1 != Item[I + 1]->Y1)) // ...и следующий контрол в другой строке
4128 // Сначала сообщим о случившемся факте процедуре обработки диалога, а потом...
4129 if (!DlgProc((HANDLE)this, DN_HOTKEY, I, Key))
4130 break; // сказали не продолжать обработку...
4132 // ... если предыдущий контрол задизаблен или невидим, тогда выходим.
4133 if ((Item[I - 1]->Flags & (DIF_DISABLE | DIF_HIDDEN))) // и не задисаблен
4134 break;
4136 I = ChangeFocus(I, -1, FALSE);
4137 DisableSelect = TRUE;
4138 } else if (Item[I]->Type == DI_TEXT || Item[I]->Type == DI_VTEXT
4139 || Item[I]->Type == DI_SINGLEBOX || Item[I]->Type == DI_DOUBLEBOX) {
4140 if (I + 1 < ItemCount) // ...и следующий контрол
4142 // Сначала сообщим о случившемся факте процедуре обработки диалога, а потом...
4143 if (!DlgProc((HANDLE)this, DN_HOTKEY, I, Key))
4144 break; // сказали не продолжать обработку...
4146 // ... если следующий контрол задизаблен или невидим, тогда выходим.
4147 if ((Item[I + 1]->Flags & (DIF_DISABLE | DIF_HIDDEN))) // и не задисаблен
4148 break;
4150 I = ChangeFocus(I, 1, FALSE);
4151 DisableSelect = TRUE;
4155 // Сообщим о случивщемся факте процедуре обработки диалога
4156 if (!DlgProc((HANDLE)this, DN_HOTKEY, I, Key))
4157 break; // сказали не продолжать обработку...
4159 ChangeFocus2(I);
4160 ShowDialog();
4162 if ((Item[I]->Type == DI_CHECKBOX || Item[I]->Type == DI_RADIOBUTTON)
4163 && (!DisableSelect || (Item[I]->Flags & DIF_MOVESELECT))) {
4164 Do_ProcessSpace();
4165 return TRUE;
4166 } else if (Item[I]->Type == DI_BUTTON) {
4167 ProcessKey(KEY_ENTER, I);
4168 return TRUE;
4170 // при ComboBox`е - "вываливаем" последний //????
4171 else if (Item[I]->Type == DI_COMBOBOX) {
4172 ProcessOpenComboBox(Item[I]->Type, Item[I], I);
4173 // ProcessKey(KEY_CTRLDOWN);
4174 return TRUE;
4177 return TRUE;
4181 return FALSE;
4184 //////////////////////////////////////////////////////////////////////////
4186 функция подравнивания координат edit классов
4188 void Dialog::AdjustEditPos(int dx, int dy)
4190 CriticalSectionLock Lock(CS);
4191 DialogItemEx *CurItem;
4192 int x1, x2, y1, y2;
4194 if (!DialogMode.Check(DMODE_CREATEOBJECTS))
4195 return;
4197 ScreenObject *DialogScrObject;
4199 for (unsigned I = 0; I < ItemCount; I++) {
4200 CurItem = Item[I];
4201 int Type = CurItem->Type;
4203 if ((CurItem->ObjPtr && FarIsEdit(Type)) || (CurItem->ListPtr && Type == DI_LISTBOX)) {
4204 if (Type == DI_LISTBOX)
4205 DialogScrObject = (ScreenObject *)CurItem->ListPtr;
4206 else
4207 DialogScrObject = (ScreenObject *)CurItem->ObjPtr;
4209 DialogScrObject->GetPosition(x1, y1, x2, y2);
4210 x1+= dx;
4211 x2+= dx;
4212 y1+= dy;
4213 y2+= dy;
4214 DialogScrObject->SetPosition(x1, y1, x2, y2);
4218 ProcessCenterGroup();
4221 //////////////////////////////////////////////////////////////////////////
4223 Работа с доп. данными экземпляра диалога
4224 Пока простое копирование (присвоение)
4226 void Dialog::SetDialogData(LONG_PTR NewDataDialog)
4228 DataDialog = NewDataDialog;
4231 //////////////////////////////////////////////////////////////////////////
4233 $ 29.06.2007 yjh\
4234 При расчётах времён копирования проще/надёжнее учитывать время ожидания
4235 пользовательских ответов в одном месте (здесь).
4236 Сброс этой переменной должен осуществляться перед общим началом операции
4238 long WaitUserTime;
4241 $ 11.08.2000 SVS
4242 + Для того, чтобы послать DM_CLOSE нужно переопределить Process
4244 static std::atomic<int> s_in_dialog{0};
4246 void Dialog::Process()
4248 // if(DialogMode.Check(DMODE_SMALLDIALOG))
4249 SetRestoreScreenMode(TRUE);
4250 ClearDone();
4251 InitDialog();
4253 if (ExitCode == -1) {
4254 clock_t btm = 0;
4255 long save = 0;
4256 DialogMode.Set(DMODE_BEGINLOOP);
4258 if (1 == ++s_in_dialog) {
4259 btm = GetProcessUptimeMSec();
4260 save = WaitUserTime;
4261 WaitUserTime = -1;
4264 FrameManager->ExecuteModal(this);
4265 save+= (GetProcessUptimeMSec() - btm);
4267 if (0 == --s_in_dialog)
4268 WaitUserTime = save;
4271 if (pSaveItemEx)
4272 for (unsigned i = 0; i < ItemCount; i++)
4273 DialogItemExToDialogItemEx(Item[i], &pSaveItemEx[i]);
4276 void Dialog::CloseDialog()
4278 CriticalSectionLock Lock(CS);
4279 GetDialogObjectsData();
4281 if (DlgProc((HANDLE)this, DN_CLOSE, ExitCode, 0)) {
4282 DialogMode.Set(DMODE_ENDLOOP);
4283 Hide();
4285 if (DialogMode.Check(DMODE_BEGINLOOP)
4286 && (DialogMode.Check(DMODE_MSGINTERNAL) || FrameManager->ManagerStarted())) {
4287 DialogMode.Clear(DMODE_BEGINLOOP);
4288 FrameManager->DeleteFrame(this);
4291 _DIALOG(CleverSysLog CL(L"Close Dialog"));
4296 $ 17.05.2001 DJ
4297 установка help topic'а и прочие радости, временно перетащенные сюда
4298 из Modal
4300 void Dialog::SetHelp(const wchar_t *Topic)
4302 CriticalSectionLock Lock(CS);
4304 if (HelpTopic)
4305 delete[] HelpTopic;
4307 HelpTopic = nullptr;
4309 if (Topic && *Topic) {
4310 HelpTopic = new (std::nothrow) wchar_t[wcslen(Topic) + 1];
4312 if (HelpTopic)
4313 wcscpy(HelpTopic, Topic);
4317 void Dialog::ShowHelp()
4319 CriticalSectionLock Lock(CS);
4321 if (HelpTopic && *HelpTopic) {
4322 Help::Present(HelpTopic);
4326 void Dialog::ClearDone()
4328 CriticalSectionLock Lock(CS);
4329 ExitCode = -1;
4330 DialogMode.Clear(DMODE_ENDLOOP);
4333 void Dialog::SetExitCode(int Code)
4335 CriticalSectionLock Lock(CS);
4336 ExitCode = Code;
4337 DialogMode.Set(DMODE_ENDLOOP);
4338 // CloseDialog();
4342 $ 19.05.2001 DJ
4343 возвращаем наше название для меню по F12
4345 int Dialog::GetTypeAndName(FARString &strType, FARString &strName)
4347 CriticalSectionLock Lock(CS);
4348 strType = Msg::DialogType;
4349 strName.Clear();
4350 const wchar_t *lpwszTitle = GetDialogTitle();
4352 if (lpwszTitle)
4353 strName = lpwszTitle;
4355 return MODALTYPE_DIALOG;
4358 int Dialog::GetMacroMode()
4360 return MACRO_DIALOG;
4363 int Dialog::FastHide()
4365 return Opt.AllCtrlAltShiftRule & CASR_DIALOG;
4368 void Dialog::ResizeConsole()
4370 CriticalSectionLock Lock(CS);
4372 DialogMode.Set(DMODE_RESIZED);
4374 if (IsVisible()) {
4375 Hide();
4378 COORD c = {(SHORT)(ScrX + 1), (SHORT)(ScrY + 1)};
4379 SendDlgMessage(reinterpret_cast<HANDLE>(this), DN_RESIZECONSOLE, 0, reinterpret_cast<LONG_PTR>(&c));
4381 int x1, y1, x2, y2;
4382 GetPosition(x1, y1, x2, y2);
4383 c.X = Min(x1, ScrX - 1);
4384 c.Y = Min(y1, ScrY - 1);
4385 if (c.X != x1 || c.Y != y1) {
4386 c.X = x1;
4387 c.Y = y1;
4388 SendDlgMessage(reinterpret_cast<HANDLE>(this), DM_MOVEDIALOG, TRUE, reinterpret_cast<LONG_PTR>(&c));
4389 Dialog::SetComboBoxPos();
4393 // void Dialog::OnDestroy()
4395 // /*
4396 // $ 21.04.2002 KM
4397 // Эта функция потеряла своё значение при текущем менеджере
4398 // и системе создания и уничтожения фреймов.
4399 // */
4400 // if(DialogMode.Check(DMODE_RESIZED))
4401 // {
4402 // Frame *BFrame=FrameManager->GetBottomFrame();
4403 // if(BFrame)
4404 // BFrame->UnlockRefresh();
4405 // /*
4406 // $ 21.04.2002 KM
4407 // А вот этот DM_KILLSAVESCREEN здесь только вредит. Удаление
4408 // диалога происходит без восстановления ShadowSaveScr и вот
4409 // они: "артефакты" непрорисовки.
4410 // */
4411 // SendDlgMessage((HANDLE)this,DM_KILLSAVESCREEN,0,0);
4412 // }
4413 // };
4415 LONG_PTR WINAPI Dialog::DlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
4417 if (DialogMode.Check(DMODE_ENDLOOP))
4418 return 0;
4420 LONG_PTR Result;
4421 FarDialogEvent de = {hDlg, Msg, Param1, Param2, 0};
4423 if (!reinterpret_cast<Dialog *>(hDlg)->CheckDialogMode(DMODE_NOPLUGINS)) {
4424 if (CtrlObject->Plugins.ProcessDialogEvent(DE_DLGPROCINIT, &de))
4425 return de.Result;
4427 Result = RealDlgProc(hDlg, Msg, Param1, Param2);
4428 if (!reinterpret_cast<Dialog *>(hDlg)->CheckDialogMode(DMODE_NOPLUGINS)) {
4429 de.Result = Result;
4430 if (CtrlObject->Plugins.ProcessDialogEvent(DE_DLGPROCEND, &de))
4431 return de.Result;
4433 return Result;
4436 //////////////////////////////////////////////////////////////////////////
4438 $ 28.07.2000 SVS
4439 функция обработки диалога (по умолчанию)
4440 Вот именно эта функция и является последним рубежом обработки диалога.
4441 Т.е. здесь должна быть ВСЯ обработка ВСЕХ сообщений!!!
4443 LONG_PTR WINAPI DefDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
4445 _DIALOG(CleverSysLog CL(L"Dialog.DefDlgProc()"));
4446 _DIALOG(SysLog(L"hDlg=%p, Msg=%ls, Param1=%d (0x%08X), Param2=%d (0x%08X)", hDlg, _DLGMSG_ToName(Msg),
4447 Param1, Param1, Param2, Param2));
4449 if (!hDlg || hDlg == INVALID_HANDLE_VALUE)
4450 return 0;
4452 FarDialogEvent de = {hDlg, Msg, Param1, Param2, 0};
4454 if (!reinterpret_cast<Dialog *>(hDlg)->CheckDialogMode(DMODE_NOPLUGINS)) {
4455 if (CtrlObject->Plugins.ProcessDialogEvent(DE_DEFDLGPROCINIT, &de)) {
4456 return de.Result;
4459 Dialog *Dlg = (Dialog *)hDlg;
4460 CriticalSectionLock Lock(Dlg->CS);
4461 DialogItemEx *CurItem = nullptr;
4462 int Type = 0;
4464 switch (Msg) {
4465 case DN_INITDIALOG:
4466 return FALSE; // изменений не было!
4467 case DM_CLOSE:
4468 return TRUE; // согласен с закрытием
4469 case DN_KILLFOCUS:
4470 return -1; // "Согласен с потерей фокуса"
4471 case DN_GOTFOCUS:
4472 return 0; // always 0
4473 case DN_HELP:
4474 return Param2; // что передали, то и...
4475 case DN_DRAGGED:
4476 return TRUE; // согласен с перемещалкой.
4477 case DN_DRAWDIALOGDONE: {
4478 if (Param1 == 1) // Нужно отрисовать "салазки"?
4481 $ 03.08.2000 tran
4482 вывод текста в углу может приводить к ошибкам изображения
4483 1) когда диалог перемещается в угол
4484 2) когда диалог перемещается из угла
4485 сделал вывод красных палочек по углам
4487 Text(Dlg->X1, Dlg->Y1, 0xCE, L"\\");
4488 Text(Dlg->X1, Dlg->Y2, 0xCE, L"/");
4489 Text(Dlg->X2, Dlg->Y1, 0xCE, L"/");
4490 Text(Dlg->X2, Dlg->Y2, 0xCE, L"\\");
4493 return TRUE;
4495 case DN_DRAWDIALOG: {
4496 return TRUE;
4498 case DN_CTLCOLORDIALOG:
4499 return Param2;
4500 case DN_CTLCOLORDLGITEM:
4501 return Param2;
4502 case DN_CTLCOLORDLGLIST:
4503 return FALSE;
4504 case DN_ENTERIDLE:
4505 return 0; // always 0
4506 case DM_GETDIALOGINFO: {
4507 bool Result = false;
4509 if (Param2) {
4510 if (Dlg->IdExist) {
4511 DialogInfo *di = reinterpret_cast<DialogInfo *>(Param2);
4513 if (static_cast<size_t>(di->StructSize) >= offsetof(DialogInfo, Id) + sizeof(di->Id)) {
4514 di->Id = Dlg->Id;
4515 Result = true;
4520 return Result;
4524 // предварительно проверим...
4525 if (Param1 < 0 || (unsigned)Param1 >= Dlg->ItemCount || !Dlg->Item)
4526 return 0;
4528 CurItem = Dlg->Item[Param1];
4529 Type = CurItem->Type;
4531 switch (Msg) {
4532 case DN_MOUSECLICK:
4533 return FALSE;
4534 case DN_DRAWDLGITEM:
4535 return TRUE;
4536 case DN_HOTKEY:
4537 return TRUE;
4538 case DN_EDITCHANGE:
4539 return TRUE;
4540 case DN_BTNCLICK:
4541 return ((Type == DI_BUTTON && !(CurItem->Flags & DIF_BTNNOCLOSE)) ? FALSE : TRUE);
4542 case DN_LISTCHANGE:
4543 return TRUE;
4544 case DN_KEY:
4545 return FALSE;
4546 case DN_MOUSEEVENT:
4547 return TRUE;
4548 case DM_GETSELECTION: // Msg=DM_GETSELECTION, Param1=ID, Param2=*EditorSelect
4549 return FALSE;
4550 case DM_SETSELECTION:
4551 return FALSE;
4554 return 0;
4557 LONG_PTR Dialog::CallDlgProc(int nMsg, int nParam1, LONG_PTR nParam2)
4559 CriticalSectionLock Lock(CS);
4560 return Dialog::DlgProc((HANDLE)this, nMsg, nParam1, nParam2);
4563 //////////////////////////////////////////////////////////////////////////
4564 LONG_PTR SendDlgMessageSynched(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
4566 Dialog *Dlg = (Dialog *)hDlg;
4567 CriticalSectionLock Lock(Dlg->CS);
4568 _DIALOG(CleverSysLog CL(L"Dialog.SendDlgMessage()"));
4569 _DIALOG(SysLog(L"hDlg=%p, Msg=%ls, Param1=%d (0x%08X), Param2=%d (0x%08X)", hDlg, _DLGMSG_ToName(Msg),
4570 Param1, Param1, Param2, Param2));
4572 // Сообщения, касаемые только диалога и не затрагивающие элементы
4573 switch (Msg) {
4574 /*****************************************************************/
4575 case DM_RESIZEDIALOG:
4576 // изменим вызов RESIZE.
4577 Param1 = -1;
4578 /*****************************************************************/
4579 case DM_MOVEDIALOG: {
4580 int W1, H1;
4581 W1 = Dlg->X2 - Dlg->X1 + 1;
4582 H1 = Dlg->Y2 - Dlg->Y1 + 1;
4583 Dlg->OldX1 = Dlg->X1;
4584 Dlg->OldY1 = Dlg->Y1;
4585 Dlg->OldX2 = Dlg->X2;
4586 Dlg->OldY2 = Dlg->Y2;
4588 // переместили
4589 if (Param1 > 0) // абсолютно?
4591 Dlg->X1 = ((COORD *)Param2)->X;
4592 Dlg->Y1 = ((COORD *)Param2)->Y;
4593 Dlg->X2 = W1;
4594 Dlg->Y2 = H1;
4595 Dlg->CheckDialogCoord();
4596 } else if (!Param1) // значит относительно
4598 Dlg->X1+= ((COORD *)Param2)->X;
4599 Dlg->Y1+= ((COORD *)Param2)->Y;
4600 } else // Resize, Param2=width/height
4602 int OldW1, OldH1;
4603 OldW1 = W1;
4604 OldH1 = H1;
4605 W1 = ((COORD *)Param2)->X;
4606 H1 = ((COORD *)Param2)->Y;
4607 Dlg->RealWidth = W1;
4608 Dlg->RealHeight = H1;
4610 if (W1 < OldW1 || H1 < OldH1) {
4611 Dlg->DialogMode.Set(DMODE_DRAWING);
4612 DialogItemEx *Item;
4613 SMALL_RECT Rect;
4615 for (unsigned int I = 0; I < Dlg->ItemCount; I++) {
4616 Item = Dlg->Item[I];
4618 if (Item->Flags & DIF_HIDDEN)
4619 continue;
4621 Rect.Left = Item->X1;
4622 Rect.Top = Item->Y1;
4624 if (Item->X2 >= W1) {
4625 Rect.Right = Item->X2 - (OldW1 - W1);
4626 Rect.Bottom = Item->Y2;
4627 Dlg->SetItemRect(I, &Rect);
4630 if (Item->Y2 >= H1) {
4631 Rect.Right = Item->X2;
4632 Rect.Bottom = Item->Y2 - (OldH1 - H1);
4633 Dlg->SetItemRect(I, &Rect);
4637 Dlg->DialogMode.Clear(DMODE_DRAWING);
4641 // проверили и скорректировали
4642 if (Dlg->X1 + W1 < 0)
4643 Dlg->X1 = -W1 + 1;
4645 if (Dlg->Y1 + H1 < 0)
4646 Dlg->Y1 = -H1 + 1;
4648 if (Dlg->X1 > ScrX)
4649 Dlg->X1 = ScrX;
4651 if (Dlg->Y1 > ScrY)
4652 Dlg->Y1 = ScrY;
4654 Dlg->X2 = Dlg->X1 + W1 - 1;
4655 Dlg->Y2 = Dlg->Y1 + H1 - 1;
4657 if (Param1 > 0) // абсолютно?
4659 Dlg->CheckDialogCoord();
4662 if (Param1 < 0) // размер?
4664 ((COORD *)Param2)->X = Dlg->X2 - Dlg->X1 + 1;
4665 ((COORD *)Param2)->Y = Dlg->Y2 - Dlg->Y1 + 1;
4666 } else {
4667 ((COORD *)Param2)->X = Dlg->X1;
4668 ((COORD *)Param2)->Y = Dlg->Y1;
4671 int I = Dlg->IsVisible(); // && Dlg->DialogMode.Check(DMODE_INITOBJECTS);
4673 if (I)
4674 Dlg->Hide();
4676 // приняли.
4677 Dlg->AdjustEditPos(Dlg->X1 - Dlg->OldX1, Dlg->Y1 - Dlg->OldY1);
4679 if (I)
4680 Dlg->Show(); // только если диалог был виден
4682 return Param2;
4684 /*****************************************************************/
4685 case DM_REDRAW: {
4686 if (Dlg->DialogMode.Check(DMODE_INITOBJECTS))
4687 Dlg->Show();
4689 return 0;
4691 /*****************************************************************/
4692 case DM_ENABLEREDRAW: {
4693 int Prev = Dlg->IsEnableRedraw;
4695 if (Param1 == TRUE)
4696 Dlg->IsEnableRedraw++;
4697 else if (Param1 == FALSE)
4698 Dlg->IsEnableRedraw--;
4700 // Edit::DisableEditOut(!Dlg->IsEnableRedraw?FALSE:TRUE);
4702 if (!Dlg->IsEnableRedraw && Prev != Dlg->IsEnableRedraw)
4703 if (Dlg->DialogMode.Check(DMODE_INITOBJECTS)) {
4704 Dlg->ShowDialog();
4705 // Dlg->Show();
4706 ScrBuf.Flush();
4709 return Prev;
4712 case DM_ENABLEREDRAW:
4714 if(Param1)
4715 Dlg->IsEnableRedraw++;
4716 else
4717 Dlg->IsEnableRedraw--;
4719 if(!Dlg->IsEnableRedraw)
4720 if(Dlg->DialogMode.Check(DMODE_INITOBJECTS))
4722 Dlg->ShowDialog();
4723 ScrBuf.Flush();
4724 // Dlg->Show();
4726 return 0;
4729 /*****************************************************************/
4730 case DM_SHOWDIALOG: {
4731 // if(!Dlg->IsEnableRedraw)
4733 if (Param1) {
4735 $ 20.04.2002 KM
4736 Залочим прорисовку при прятании диалога, в противном
4737 случае ОТКУДА менеджер узнает, что отрисовывать
4738 объект нельзя!
4740 if (!Dlg->IsVisible()) {
4741 Dlg->Unlock();
4742 Dlg->Show();
4744 } else {
4745 if (Dlg->IsVisible()) {
4746 Dlg->Hide();
4747 Dlg->Lock();
4751 return 0;
4753 /*****************************************************************/
4754 case DM_SETDLGDATA: {
4755 LONG_PTR PrewDataDialog = Dlg->DataDialog;
4756 Dlg->DataDialog = Param2;
4757 return PrewDataDialog;
4759 /*****************************************************************/
4760 case DM_GETDLGDATA: {
4761 return Dlg->DataDialog;
4763 /*****************************************************************/
4764 case DM_KEY: {
4765 int *KeyArray = (int *)Param2;
4766 Dlg->DialogMode.Set(DMODE_KEY);
4768 for (unsigned int I = 0; I < (unsigned)Param1; ++I)
4769 Dlg->ProcessKey(KeyArray[I]);
4771 Dlg->DialogMode.Clear(DMODE_KEY);
4772 return 0;
4774 /*****************************************************************/
4775 case DM_CLOSE: {
4776 if (Param1 == -1)
4777 Dlg->ExitCode = Dlg->FocusPos;
4778 else
4779 Dlg->ExitCode = Param1;
4781 Dlg->CloseDialog();
4782 return TRUE; // согласен с закрытием
4784 /*****************************************************************/
4785 case DM_GETDLGRECT: {
4786 if (Param2) {
4787 int x1, y1, x2, y2;
4788 Dlg->GetPosition(x1, y1, x2, y2);
4789 ((SMALL_RECT *)Param2)->Left = x1;
4790 ((SMALL_RECT *)Param2)->Top = y1;
4791 ((SMALL_RECT *)Param2)->Right = x2;
4792 ((SMALL_RECT *)Param2)->Bottom = y2;
4793 return TRUE;
4796 return FALSE;
4798 /*****************************************************************/
4799 case DM_GETDROPDOWNOPENED: // Param1=0; Param2=0
4801 return Dlg->GetDropDownOpened();
4803 /*****************************************************************/
4804 case DM_KILLSAVESCREEN: {
4805 if (Dlg->SaveScr)
4806 Dlg->SaveScr->Discard();
4808 if (Dlg->ShadowSaveScr)
4809 Dlg->ShadowSaveScr->Discard();
4811 return TRUE;
4813 /*****************************************************************/
4815 Msg=DM_ALLKEYMODE
4816 Param1
4817 =-1 - получить состояние
4818 = 0 - выключить
4819 = 1 - включить
4820 Ret = состояние
4822 case DM_ALLKEYMODE: {
4823 if (Param1 == -1)
4824 return IsProcessAssignMacroKey;
4826 BOOL OldIsProcessAssignMacroKey = IsProcessAssignMacroKey;
4827 IsProcessAssignMacroKey = Param1;
4828 return OldIsProcessAssignMacroKey;
4830 /*****************************************************************/
4831 case DM_SETMOUSEEVENTNOTIFY: // Param1 = 1 on, 0 off, -1 - get
4833 int State = Dlg->DialogMode.Check(DMODE_MOUSEEVENT) ? TRUE : FALSE;
4835 if (Param1 != -1) {
4836 if (!Param1)
4837 Dlg->DialogMode.Clear(DMODE_MOUSEEVENT);
4838 else
4839 Dlg->DialogMode.Set(DMODE_MOUSEEVENT);
4842 return State;
4844 /*****************************************************************/
4845 case DN_RESIZECONSOLE: {
4846 return Dlg->CallDlgProc(Msg, Param1, Param2);
4848 case DM_GETDIALOGINFO: {
4849 return DefDlgProc(hDlg, DM_GETDIALOGINFO, Param1, Param2);
4853 /*****************************************************************/
4854 if (Msg >= DM_USER) {
4855 return Dlg->CallDlgProc(Msg, Param1, Param2);
4858 /*****************************************************************/
4859 DialogItemEx *CurItem = nullptr;
4860 int Type = 0;
4861 size_t Len = 0;
4864 предварительно проверим...
4865 $ 09.12.2001 DJ
4866 для DM_USER проверять _не_надо_!
4868 if ((unsigned)Param1 >= Dlg->ItemCount || !Dlg->Item)
4869 return 0;
4871 // CurItem=&Dlg->Item[Param1];
4872 CurItem = Dlg->Item[Param1];
4873 Type = CurItem->Type;
4874 const wchar_t *Ptr = CurItem->strData;
4876 if (FarIsEdit(Type) && CurItem->ObjPtr)
4877 Ptr = const_cast<const wchar_t *>(((DlgEdit *)(CurItem->ObjPtr))->GetStringAddr());
4879 switch (Msg) {
4880 /*****************************************************************/
4881 case DM_LISTSORT: // Param1=ID Param=Direct {0|1}
4882 case DM_LISTADD: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
4883 case DM_LISTADDSTR: // Param1=ID Param2=String
4884 case DM_LISTDELETE: // Param1=ID Param2=FarListDelete: StartIndex=BeginIndex, Count=количество (<=0 - все!)
4885 case DM_LISTGETITEM: // Param1=ID Param2=FarListGetItem: ItemsNumber=Index, Items=Dest
4886 case DM_LISTSET: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
4887 case DM_LISTGETCURPOS: // Param1=ID Param2=FarListPos
4888 case DM_LISTSETCURPOS: // Param1=ID Param2=FarListPos Ret: RealPos
4889 case DM_LISTUPDATE: // Param1=ID Param2=FarList: ItemsNumber=Index, Items=Src
4890 case DM_LISTINFO: // Param1=ID Param2=FarListInfo
4891 case DM_LISTFINDSTRING: // Param1=ID Param2=FarListFind
4892 case DM_LISTINSERT: // Param1=ID Param2=FarListInsert
4893 case DM_LISTGETDATA: // Param1=ID Param2=Index
4894 case DM_LISTSETDATA: // Param1=ID Param2=FarListItemData
4895 case DM_LISTSETTITLES: // Param1=ID Param2=FarListTitles: TitleLen=strlen(Title), BottomLen=strlen(Bottom)
4896 case DM_LISTGETTITLES: // Param1=ID Param2=FarListTitles: TitleLen=strlen(Title), BottomLen=strlen(Bottom)
4897 case DM_LISTGETDATASIZE: // Param1=ID Param2=Index
4898 case DM_LISTSETMOUSEREACTION: // Param1=ID Param2=FARLISTMOUSEREACTIONTYPE Ret=OldSets
4899 case DM_SETCOMBOBOXEVENT: // Param1=ID Param2=FARCOMBOBOXEVENTTYPE Ret=OldSets
4900 case DM_GETCOMBOBOXEVENT: // Param1=ID Param2=0 Ret=Sets
4902 if (Type == DI_LISTBOX || Type == DI_COMBOBOX) {
4903 VMenu *ListBox = CurItem->ListPtr;
4905 if (ListBox) {
4906 int Ret = TRUE;
4908 switch (Msg) {
4909 case DM_LISTINFO: // Param1=ID Param2=FarListInfo
4911 return ListBox->GetVMenuInfo((FarListInfo *)Param2);
4913 case DM_LISTSORT: // Param1=ID Param=Direct {0|1}
4915 ListBox->SortItems((int)Param2);
4916 break;
4918 case DM_LISTFINDSTRING: // Param1=ID Param2=FarListFind
4920 FarListFind *lf = reinterpret_cast<FarListFind *>(Param2);
4921 return ListBox->FindItem(lf->StartIndex, lf->Pattern, lf->Flags);
4923 case DM_LISTADDSTR: // Param1=ID Param2=String
4925 Ret = ListBox->AddItem((wchar_t *)Param2);
4926 break;
4928 case DM_LISTADD: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
4930 FarList *ListItems = (FarList *)Param2;
4932 if (!ListItems)
4933 return FALSE;
4935 Ret = ListBox->AddItem(ListItems);
4936 break;
4938 case DM_LISTDELETE: // Param1=ID Param2=FarListDelete: StartIndex=BeginIndex, Count=количество (<=0 - все!)
4940 int Count;
4941 FarListDelete *ListItems = (FarListDelete *)Param2;
4943 if (!ListItems || (Count = ListItems->Count) <= 0)
4944 ListBox->DeleteItems();
4945 else
4946 ListBox->DeleteItem(ListItems->StartIndex, Count);
4948 break;
4950 case DM_LISTINSERT: // Param1=ID Param2=FarListInsert
4952 if ((Ret = ListBox->InsertItem((FarListInsert *)Param2)) == -1)
4953 return -1;
4955 break;
4957 case DM_LISTUPDATE: // Param1=ID Param2=FarListUpdate: Index=Index, Items=Src
4959 if (Param2 && ListBox->UpdateItem((FarListUpdate *)Param2))
4960 break;
4962 return FALSE;
4964 case DM_LISTGETITEM: // Param1=ID Param2=FarListGetItem: ItemsNumber=Index, Items=Dest
4966 FarListGetItem *ListItems = (FarListGetItem *)Param2;
4968 if (!ListItems)
4969 return FALSE;
4971 MenuItemEx *ListMenuItem;
4973 if ((ListMenuItem = ListBox->GetItemPtr(ListItems->ItemIndex))) {
4974 // ListItems->ItemIndex=1;
4975 FarListItem *Item = &ListItems->Item;
4976 memset(Item, 0, sizeof(FarListItem));
4977 Item->Flags = ListMenuItem->Flags;
4978 Item->Text = ListMenuItem->strName;
4980 if(ListMenuItem->UserDataSize <= sizeof(DWORD)) //???
4981 Item->UserData=ListMenuItem->UserData;
4983 return TRUE;
4986 return FALSE;
4988 case DM_LISTGETDATA: // Param1=ID Param2=Index
4990 if (Param2 < ListBox->GetItemCount())
4991 return (LONG_PTR)ListBox->GetUserData(nullptr, 0, (int)Param2);
4993 return 0;
4995 case DM_LISTGETDATASIZE: // Param1=ID Param2=Index
4997 if (Param2 < ListBox->GetItemCount())
4998 return ListBox->GetUserDataSize((int)Param2);
5000 return 0;
5002 case DM_LISTSETDATA: // Param1=ID Param2=FarListItemData
5004 FarListItemData *ListItems = (FarListItemData *)Param2;
5006 if (ListItems && ListItems->Index < ListBox->GetItemCount()) {
5007 Ret = ListBox->SetUserData(ListItems->Data, ListItems->DataSize,
5008 ListItems->Index);
5010 if (!Ret && ListBox->GetUserData(nullptr, 0, ListItems->Index))
5011 Ret = sizeof(DWORD);
5013 return Ret;
5016 return 0;
5019 $ 02.12.2001 KM
5020 + Сообщение для добавления в список строк, с удалением
5021 уже существующих, т.с. "чистая" установка
5023 case DM_LISTSET: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
5025 FarList *ListItems = (FarList *)Param2;
5027 if (!ListItems)
5028 return FALSE;
5030 ListBox->DeleteItems();
5031 Ret = ListBox->AddItem(ListItems);
5032 break;
5034 // case DM_LISTINS: // Param1=ID Param2=FarList: ItemsNumber=Index, Items=Dest
5035 case DM_LISTSETTITLES: // Param1=ID Param2=FarListTitles
5037 FarListTitles *ListTitle = (FarListTitles *)Param2;
5038 ListBox->SetTitle(ListTitle->Title);
5039 ListBox->SetBottomTitle(ListTitle->Bottom);
5040 break; // return TRUE;
5042 case DM_LISTGETTITLES: // Param1=ID Param2=FarListTitles
5044 if (Param2) {
5045 FarListTitles *ListTitle = (FarListTitles *)Param2;
5046 FARString strTitle, strBottomTitle;
5047 ListBox->GetTitle(strTitle);
5048 ListBox->GetBottomTitle(strBottomTitle);
5050 if (!strTitle.IsEmpty() || !strBottomTitle.IsEmpty()) {
5051 if (ListTitle->Title && ListTitle->TitleLen)
5052 far_wcsncpy((wchar_t *)ListTitle->Title, strTitle,
5053 ListTitle->TitleLen);
5054 else
5055 ListTitle->TitleLen = (int)strTitle.GetLength() + 1;
5057 if (ListTitle->Bottom && ListTitle->BottomLen)
5058 far_wcsncpy((wchar_t *)ListTitle->Bottom, strBottomTitle,
5059 ListTitle->BottomLen);
5060 else
5061 ListTitle->BottomLen = (int)strBottomTitle.GetLength() + 1;
5063 return TRUE;
5067 return FALSE;
5069 case DM_LISTGETCURPOS: // Param1=ID Param2=FarListPos
5071 return Param2 ? ListBox->GetSelectPos((FarListPos *)Param2)
5072 : ListBox->GetSelectPos();
5074 case DM_LISTSETCURPOS: // Param1=ID Param2=FarListPos Ret: RealPos
5076 /* 26.06.2001 KM Подадим перед изменением позиции об этом сообщение */
5077 int CurListPos = ListBox->GetSelectPos();
5078 Ret = ListBox->SetSelectPos((FarListPos *)Param2);
5080 if (Ret != CurListPos)
5081 if (!Dlg->CallDlgProc(DN_LISTCHANGE, Param1, Ret))
5082 Ret = ListBox->SetSelectPos(CurListPos, 1);
5084 break; // т.к. нужно перерисовать!
5086 case DM_LISTSETMOUSEREACTION: // Param1=ID Param2=FARLISTMOUSEREACTIONTYPE Ret=OldSets
5088 int OldSets = CurItem->IFlags.Flags;
5090 if (Param2 == LMRT_ONLYFOCUS) {
5091 CurItem->IFlags.Clear(DLGIIF_LISTREACTIONNOFOCUS);
5092 CurItem->IFlags.Set(DLGIIF_LISTREACTIONFOCUS);
5093 } else if (Param2 == LMRT_NEVER) {
5094 CurItem->IFlags.Clear(DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS);
5095 // ListBox->ClearFlags(VMENU_MOUSEREACTION);
5096 } else {
5097 CurItem->IFlags.Set(DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS);
5098 // ListBox->SetFlags(VMENU_MOUSEREACTION);
5101 if ((OldSets & (DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS))
5102 == (DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS))
5103 OldSets = LMRT_ALWAYS;
5104 else if (!(OldSets & (DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS)))
5105 OldSets = LMRT_NEVER;
5106 else
5107 OldSets = LMRT_ONLYFOCUS;
5109 return OldSets;
5111 case DM_GETCOMBOBOXEVENT: // Param1=ID Param2=0 Ret=Sets
5113 return (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTKEY) ? CBET_KEY : 0)
5114 | (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTMOUSE) ? CBET_MOUSE : 0);
5116 case DM_SETCOMBOBOXEVENT: // Param1=ID Param2=FARCOMBOBOXEVENTTYPE Ret=OldSets
5118 int OldSets = CurItem->IFlags.Flags;
5119 CurItem->IFlags.Clear(DLGIIF_COMBOBOXEVENTKEY | DLGIIF_COMBOBOXEVENTMOUSE);
5121 if (Param2 & CBET_KEY)
5122 CurItem->IFlags.Set(DLGIIF_COMBOBOXEVENTKEY);
5124 if (Param2 & CBET_MOUSE)
5125 CurItem->IFlags.Set(DLGIIF_COMBOBOXEVENTMOUSE);
5127 return OldSets;
5131 // уточнение для DI_COMBOBOX - здесь еще и DlgEdit нужно корректно заполнить
5132 if (!CurItem->IFlags.Check(DLGIIF_COMBOBOXNOREDRAWEDIT) && Type == DI_COMBOBOX
5133 && CurItem->ObjPtr) {
5134 MenuItemEx *ListMenuItem;
5136 if ((ListMenuItem = ListBox->GetItemPtr(ListBox->GetSelectPos()))) {
5137 if (CurItem->Flags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND))
5138 ((DlgEdit *)(CurItem->ObjPtr))->SetHiString(ListMenuItem->strName);
5139 else
5140 ((DlgEdit *)(CurItem->ObjPtr))->SetString(ListMenuItem->strName);
5142 ((DlgEdit *)(CurItem->ObjPtr))->Select(-1, -1); // снимаем выделение
5146 if (Dlg->DialogMode.Check(DMODE_SHOW) && ListBox->UpdateRequired()) {
5147 Dlg->ShowDialog(Param1);
5148 ScrBuf.Flush();
5151 return Ret;
5155 return FALSE;
5157 /*****************************************************************/
5158 case DM_SETHISTORY: // Param1 = ID, Param2 = LPSTR HistoryName
5160 if (Type == DI_EDIT || Type == DI_FIXEDIT) {
5161 if (Param2 && *(const wchar_t *)Param2) {
5162 CurItem->Flags|= DIF_HISTORY;
5163 CurItem->strHistory = (const wchar_t *)Param2;
5165 if (Type == DI_EDIT && (CurItem->Flags & DIF_USELASTHISTORY)) {
5166 Dlg->ProcessLastHistory(CurItem, Param1);
5168 } else {
5169 CurItem->Flags&= ~DIF_HISTORY;
5170 CurItem->strHistory.Clear();
5173 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5174 Dlg->ShowDialog(Param1);
5175 ScrBuf.Flush();
5178 return TRUE;
5181 return FALSE;
5183 /*****************************************************************/
5184 case DM_ADDHISTORY: {
5185 if (Param2 && (Type == DI_EDIT || Type == DI_FIXEDIT) && (CurItem->Flags & DIF_HISTORY)) {
5186 return Dlg->AddToEditHistory((const wchar_t *)Param2, CurItem->strHistory);
5189 return FALSE;
5191 /*****************************************************************/
5192 case DM_GETCURSORPOS: {
5193 if (!Param2)
5194 return FALSE;
5196 if (FarIsEdit(Type) && CurItem->ObjPtr) {
5197 ((COORD *)Param2)->X = ((DlgEdit *)(CurItem->ObjPtr))->GetCurPos();
5198 ((COORD *)Param2)->Y = 0;
5199 return TRUE;
5200 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5201 ((COORD *)Param2)->X = CurItem->UCData->CursorPos.X;
5202 ((COORD *)Param2)->Y = CurItem->UCData->CursorPos.Y;
5203 return TRUE;
5206 return FALSE;
5208 /*****************************************************************/
5209 case DM_SETCURSORPOS: {
5210 if (FarIsEdit(Type) && CurItem->ObjPtr && ((COORD *)Param2)->X >= 0) {
5211 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
5212 EditPtr->SetCurPos(((COORD *)Param2)->X);
5213 // EditPtr->Show();
5214 Dlg->ShowDialog(Param1);
5215 return TRUE;
5216 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5218 учтем, что координаты для этого элемента всегда относительные!
5219 и начинаются с 0,0
5221 COORD Coord = *(COORD *)Param2;
5222 Coord.X+= CurItem->X1;
5224 if (Coord.X > CurItem->X2)
5225 Coord.X = CurItem->X2;
5227 Coord.Y+= CurItem->Y1;
5229 if (Coord.Y > CurItem->Y2)
5230 Coord.Y = CurItem->Y2;
5232 // Запомним
5233 CurItem->UCData->CursorPos.X = Coord.X - CurItem->X1;
5234 CurItem->UCData->CursorPos.Y = Coord.Y - CurItem->Y1;
5236 // переместим если надо
5237 if (Dlg->DialogMode.Check(DMODE_SHOW) && Dlg->FocusPos == (unsigned)Param1) {
5238 // что-то одно надо убрать :-)
5239 MoveCursor(Coord.X + Dlg->X1, Coord.Y + Dlg->Y1); // ???
5240 Dlg->ShowDialog(Param1); // ???
5243 return TRUE;
5246 return FALSE;
5248 /*****************************************************************/
5249 case DM_GETEDITPOSITION: {
5250 if (Param2 && FarIsEdit(Type)) {
5251 if (Type == DI_MEMOEDIT) {
5252 // EditorControl(ECTL_GETINFO,(EditorSetPosition *)Param2);
5253 return TRUE;
5254 } else {
5255 EditorSetPosition *esp = (EditorSetPosition *)Param2;
5256 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
5257 esp->CurLine = 0;
5258 esp->CurPos = EditPtr->GetCurPos();
5259 esp->CurTabPos = EditPtr->GetCellCurPos();
5260 esp->TopScreenLine = 0;
5261 esp->LeftPos = EditPtr->GetLeftPos();
5262 esp->Overtype = EditPtr->GetOvertypeMode();
5263 return TRUE;
5267 return FALSE;
5269 /*****************************************************************/
5270 case DM_SETEDITPOSITION: {
5271 if (Param2 && FarIsEdit(Type)) {
5272 if (Type == DI_MEMOEDIT) {
5273 // EditorControl(ECTL_SETPOSITION,(EditorSetPosition *)Param2);
5274 return TRUE;
5275 } else {
5276 EditorSetPosition *esp = (EditorSetPosition *)Param2;
5277 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
5278 EditPtr->SetCurPos(esp->CurPos);
5279 EditPtr->SetCellCurPos(esp->CurTabPos);
5280 EditPtr->SetLeftPos(esp->LeftPos);
5281 EditPtr->SetOvertypeMode(esp->Overtype);
5282 Dlg->ShowDialog(Param1);
5283 ScrBuf.Flush();
5284 return TRUE;
5288 return FALSE;
5290 /*****************************************************************/
5291 // Param2=0
5292 // Return MAKELONG(Visible,Size)
5293 case DM_GETCURSORSIZE: {
5294 if (FarIsEdit(Type) && CurItem->ObjPtr) {
5295 bool Visible;
5296 DWORD Size;
5297 ((DlgEdit *)(CurItem->ObjPtr))->GetCursorType(Visible, Size);
5298 return MAKELONG(Visible, Size);
5299 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5300 return MAKELONG(CurItem->UCData->CursorVisible, CurItem->UCData->CursorSize);
5303 return FALSE;
5305 /*****************************************************************/
5306 // Param2=MAKELONG(Visible,Size)
5307 // Return MAKELONG(OldVisible,OldSize)
5308 case DM_SETCURSORSIZE: {
5309 bool Visible = false;
5310 DWORD Size = 0;
5312 if (FarIsEdit(Type) && CurItem->ObjPtr) {
5313 ((DlgEdit *)(CurItem->ObjPtr))->GetCursorType(Visible, Size);
5314 ((DlgEdit *)(CurItem->ObjPtr))->SetCursorType(LOWORD(Param2) != 0, HIWORD(Param2));
5315 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5316 Visible = CurItem->UCData->CursorVisible;
5317 Size = CurItem->UCData->CursorSize;
5318 CurItem->UCData->CursorVisible = LOWORD(Param2) != 0;
5319 CurItem->UCData->CursorSize = HIWORD(Param2);
5320 int CCX = CurItem->UCData->CursorPos.X;
5321 int CCY = CurItem->UCData->CursorPos.Y;
5323 if (Dlg->DialogMode.Check(DMODE_SHOW) && Dlg->FocusPos == (unsigned)Param1 && CCX != -1
5324 && CCY != -1)
5325 SetCursorType(CurItem->UCData->CursorVisible, CurItem->UCData->CursorSize);
5328 return MAKELONG(Visible, Size);
5330 /*****************************************************************/
5331 case DN_LISTCHANGE: {
5332 return Dlg->CallDlgProc(Msg, Param1, Param2);
5334 /*****************************************************************/
5335 case DN_EDITCHANGE: {
5336 FarDialogItem Item;
5338 if (!ConvertItemEx(CVTITEM_TOPLUGIN, &Item, CurItem, 1))
5339 return FALSE; // no memory TODO: may be needed diagnostic
5341 INT_PTR I = 0;
5342 if (CurItem->Type == DI_EDIT || CurItem->Type == DI_COMBOBOX || CurItem->Type == DI_FIXEDIT
5343 || CurItem->Type == DI_PSWEDIT) {
5344 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(false);
5345 const wchar_t *original_PtrData = Item.PtrData;
5346 I = Dlg->CallDlgProc(DN_EDITCHANGE, Param1, (LONG_PTR)&Item);
5347 if (I) {
5348 if (Type == DI_COMBOBOX && CurItem->ListPtr)
5349 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
5351 if (original_PtrData)
5352 free((void *)original_PtrData);
5353 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(true);
5356 return I;
5358 /*****************************************************************/
5359 case DN_BTNCLICK: {
5360 LONG_PTR Ret = Dlg->CallDlgProc(Msg, Param1, Param2);
5362 if (Ret && (CurItem->Flags & DIF_AUTOMATION) && CurItem->AutoCount && CurItem->AutoPtr) {
5363 DialogItemAutomation *Auto = CurItem->AutoPtr;
5364 Param2%= 3;
5366 for (UINT I = 0; I < CurItem->AutoCount; ++I, ++Auto) {
5367 DWORD NewFlags = Dlg->Item[Auto->ID]->Flags;
5368 Dlg->Item[Auto->ID]->Flags =
5369 (NewFlags & (~Auto->Flags[Param2][1])) | Auto->Flags[Param2][0];
5370 // здесь намеренно в обработчик не посылаются эвенты об изменении
5371 // состояния...
5375 return Ret;
5377 /*****************************************************************/
5378 case DM_GETCHECK: {
5379 if (Type == DI_CHECKBOX || Type == DI_RADIOBUTTON)
5380 return CurItem->Selected;
5382 return 0;
5384 /*****************************************************************/
5385 case DM_SET3STATE: {
5386 if (Type == DI_CHECKBOX) {
5387 int OldState = CurItem->Flags & DIF_3STATE ? TRUE : FALSE;
5389 if (Param2)
5390 CurItem->Flags|= DIF_3STATE;
5391 else
5392 CurItem->Flags&= ~DIF_3STATE;
5394 return OldState;
5397 return 0;
5399 /*****************************************************************/
5400 case DM_SETCHECK: {
5401 if (Type == DI_CHECKBOX) {
5402 int Selected = CurItem->Selected;
5404 if (Param2 == BSTATE_TOGGLE)
5405 Param2 = ++Selected;
5407 if (CurItem->Flags & DIF_3STATE)
5408 Param2%= 3;
5409 else
5410 Param2&= 1;
5412 CurItem->Selected = (int)Param2;
5414 if (Selected != (int)Param2 && Dlg->DialogMode.Check(DMODE_SHOW)) {
5415 // автоматизация
5416 if ((CurItem->Flags & DIF_AUTOMATION) && CurItem->AutoCount && CurItem->AutoPtr) {
5417 DialogItemAutomation *Auto = CurItem->AutoPtr;
5418 Param2%= 3;
5420 for (UINT I = 0; I < CurItem->AutoCount; ++I, ++Auto) {
5421 DWORD NewFlags = Dlg->Item[Auto->ID]->Flags;
5422 Dlg->Item[Auto->ID]->Flags =
5423 (NewFlags & (~Auto->Flags[Param2][1])) | Auto->Flags[Param2][0];
5424 // здесь намеренно в обработчик не посылаются эвенты об изменении
5425 // состояния...
5428 Param1 = -1;
5431 Dlg->ShowDialog(Param1);
5432 ScrBuf.Flush();
5435 return Selected;
5436 } else if (Type == DI_RADIOBUTTON) {
5437 Param1 = Dlg->ProcessRadioButton(Param1);
5439 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5440 Dlg->ShowDialog();
5441 ScrBuf.Flush();
5444 return Param1;
5447 return 0;
5449 /*****************************************************************/
5450 case DN_DRAWDLGITEM: {
5451 FarDialogItem Item;
5453 if (!ConvertItemEx(CVTITEM_TOPLUGIN, &Item, CurItem, 1))
5454 return FALSE; // no memory TODO: may be needed diagnostic
5456 INT_PTR I = Dlg->CallDlgProc(Msg, Param1, (LONG_PTR)&Item);
5458 if ((Type == DI_LISTBOX || Type == DI_COMBOBOX) && CurItem->ListPtr)
5459 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
5461 if (Item.PtrData)
5462 free((wchar_t *)Item.PtrData);
5464 return I;
5466 /*****************************************************************/
5467 case DM_SETFOCUS: {
5468 if (!CanGetFocus(Type))
5469 return FALSE;
5471 if (Dlg->FocusPos == (unsigned)Param1) // уже и так установлено все!
5472 return TRUE;
5474 Dlg->ChangeFocus2(Param1);
5476 if (Dlg->FocusPos == (unsigned)Param1) {
5477 Dlg->ShowDialog();
5478 return TRUE;
5481 return FALSE;
5483 /*****************************************************************/
5484 case DM_GETFOCUS: // Получить ID фокуса
5486 return Dlg->FocusPos;
5488 /*****************************************************************/
5489 case DM_GETCONSTTEXTPTR: {
5490 return (LONG_PTR)Ptr;
5492 /*****************************************************************/
5493 case DM_GETTEXTPTR:
5495 if (Param2) {
5496 FarDialogItemData IData = {0, (wchar_t *)Param2};
5497 return SendDlgMessage(hDlg, DM_GETTEXT, Param1, (LONG_PTR)&IData);
5500 /*****************************************************************/
5501 case DM_GETTEXT:
5503 if (Param2) // если здесь nullptr, то это еще один способ получить размер
5505 FarDialogItemData *did = (FarDialogItemData *)Param2;
5506 Len = 0;
5508 switch (Type) {
5509 case DI_MEMOEDIT:
5510 break;
5511 case DI_COMBOBOX:
5512 case DI_EDIT:
5513 case DI_PSWEDIT:
5514 case DI_FIXEDIT:
5516 if (!CurItem->ObjPtr)
5517 break;
5519 Ptr = const_cast<const wchar_t *>(((DlgEdit *)(CurItem->ObjPtr))->GetStringAddr());
5520 case DI_TEXT:
5521 case DI_VTEXT:
5522 case DI_SINGLEBOX:
5523 case DI_DOUBLEBOX:
5524 case DI_CHECKBOX:
5525 case DI_RADIOBUTTON:
5526 case DI_BUTTON:
5527 Len = StrLength(Ptr) + 1;
5529 if (Type == DI_BUTTON) {
5530 if (!(CurItem->Flags & DIF_NOBRACKETS)) {
5531 Ptr+= 2;
5532 Len-= 4;
5534 if (CurItem->Flags & DIF_SETSHIELD) {
5535 Ptr+= 2;
5539 if (!did->PtrLength)
5540 did->PtrLength = Len;
5541 else if (Len > did->PtrLength)
5542 Len = did->PtrLength + 1; // Прибавим 1, чтобы учесть нулевой байт.
5544 if (Len > 0 && did->PtrData) {
5545 wmemmove(did->PtrData, Ptr, Len);
5546 did->PtrData[Len - 1] = 0;
5549 break;
5550 case DI_USERCONTROL:
5551 /*did->PtrLength=CurItem->Ptr.PtrLength; BUGBUG
5552 did->PtrData=(char*)CurItem->Ptr.PtrData;*/
5553 break;
5554 case DI_LISTBOX: {
5555 // if(!CurItem->ListPtr)
5556 // break;
5557 // did->PtrLength=CurItem->ListPtr->GetUserData(did->PtrData,did->PtrLength,-1);
5558 break;
5560 default: // подразумеваем, что остались
5561 did->PtrLength = 0;
5562 break;
5565 return Len - (!Len ? 0 : 1);
5568 // здесь умышленно не ставим return, т.к. хотим получить размер
5569 // следовательно сразу должен идти "case DM_GETTEXTLENGTH"!!!
5570 /*****************************************************************/
5571 case DM_GETTEXTLENGTH: {
5572 switch (Type) {
5573 case DI_BUTTON:
5574 Len = StrLength(Ptr) + 1;
5576 if (!(CurItem->Flags & DIF_NOBRACKETS))
5577 Len-= 4;
5579 break;
5580 case DI_USERCONTROL:
5581 // Len=CurItem->Ptr.PtrLength; BUGBUG
5582 break;
5583 case DI_TEXT:
5584 case DI_VTEXT:
5585 case DI_SINGLEBOX:
5586 case DI_DOUBLEBOX:
5587 case DI_CHECKBOX:
5588 case DI_RADIOBUTTON:
5589 Len = StrLength(Ptr) + 1;
5590 break;
5591 case DI_COMBOBOX:
5592 case DI_EDIT:
5593 case DI_PSWEDIT:
5594 case DI_FIXEDIT:
5595 case DI_MEMOEDIT:
5597 if (CurItem->ObjPtr) {
5598 Len = ((DlgEdit *)(CurItem->ObjPtr))->GetLength() + 1;
5599 break;
5602 case DI_LISTBOX: {
5603 Len = 0;
5604 MenuItemEx *ListMenuItem;
5606 if ((ListMenuItem = CurItem->ListPtr->GetItemPtr(-1))) {
5607 Len = (int)ListMenuItem->strName.GetLength() + 1;
5610 break;
5612 default:
5613 Len = 0;
5614 break;
5617 return Len - (!Len ? 0 : 1);
5619 /*****************************************************************/
5620 case DM_SETTEXTPTR: {
5621 if (!Param2)
5622 return 0;
5624 FarDialogItemData IData = {(size_t)StrLength((wchar_t *)Param2), (wchar_t *)Param2};
5625 return SendDlgMessage(hDlg, DM_SETTEXT, Param1, (LONG_PTR)&IData);
5628 case DM_SETTEXTPTRSILENT: {
5629 if (!Param2)
5630 return 0;
5632 if (CurItem->Type != DI_FIXEDIT && CurItem->Type != DI_EDIT)
5633 return 0;
5635 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(false);
5636 FarDialogItemData IData = {(size_t)StrLength((wchar_t *)Param2), (wchar_t *)Param2};
5637 intptr_t rv = SendDlgMessage(hDlg, DM_SETTEXT, Param1, (LONG_PTR)&IData);
5638 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(true);
5640 return rv;
5643 /*****************************************************************/
5644 case DM_SETTEXT: {
5645 if (Param2) {
5646 int NeedInit = TRUE;
5647 FarDialogItemData *did = (FarDialogItemData *)Param2;
5649 switch (Type) {
5650 case DI_MEMOEDIT:
5651 break;
5652 case DI_COMBOBOX:
5653 case DI_EDIT:
5654 case DI_TEXT:
5655 case DI_VTEXT:
5656 case DI_SINGLEBOX:
5657 case DI_DOUBLEBOX:
5658 case DI_BUTTON:
5659 case DI_CHECKBOX:
5660 case DI_RADIOBUTTON:
5661 case DI_PSWEDIT:
5662 case DI_FIXEDIT:
5663 case DI_LISTBOX: // меняет только текущий итем
5664 CurItem->strData = did->PtrData;
5665 Len = (int)CurItem->strData.GetLength();
5666 break;
5667 default:
5668 Len = 0;
5669 break;
5672 switch (Type) {
5673 case DI_USERCONTROL:
5674 /*CurItem->Ptr.PtrLength=did->PtrLength;
5675 CurItem->Ptr.PtrData=did->PtrData;
5676 return CurItem->Ptr.PtrLength;*/
5677 return 0; // BUGBUG
5678 case DI_TEXT:
5679 case DI_VTEXT:
5680 case DI_SINGLEBOX:
5681 case DI_DOUBLEBOX:
5683 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5684 if (!Dlg->DialogMode.Check(DMODE_KEEPCONSOLETITLE))
5685 ConsoleTitle::SetFarTitle(Dlg->GetDialogTitle());
5686 Dlg->ShowDialog(Param1);
5687 ScrBuf.Flush();
5690 return Len - (!Len ? 0 : 1);
5691 case DI_BUTTON:
5692 case DI_CHECKBOX:
5693 case DI_RADIOBUTTON:
5694 break;
5695 case DI_MEMOEDIT:
5696 break;
5697 case DI_COMBOBOX:
5698 case DI_EDIT:
5699 case DI_PSWEDIT:
5700 case DI_FIXEDIT:
5701 NeedInit = FALSE;
5703 if (CurItem->ObjPtr) {
5704 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
5705 int ReadOnly = EditLine->GetReadOnly();
5706 EditLine->SetReadOnly(0);
5707 EditLine->DisableAC();
5708 EditLine->SetString(CurItem->strData);
5709 EditLine->RevertAC();
5710 EditLine->SetReadOnly(ReadOnly);
5712 if (Dlg->DialogMode.Check(DMODE_INITOBJECTS)) // не меняем клеар-флаг, пока не проиницализировались
5713 EditLine->SetClearFlag(0);
5715 EditLine->Select(-1, 0); // снимаем выделение
5716 // ...оно уже снимается в DlgEdit::SetString()
5719 break;
5720 case DI_LISTBOX: // меняет только текущий итем
5722 VMenu *ListBox = CurItem->ListPtr;
5724 if (ListBox) {
5725 FarListUpdate LUpdate;
5726 LUpdate.Index = ListBox->GetSelectPos();
5727 MenuItemEx *ListMenuItem = ListBox->GetItemPtr(LUpdate.Index);
5729 if (ListMenuItem) {
5730 LUpdate.Item.Flags = ListMenuItem->Flags;
5731 LUpdate.Item.Text = Ptr;
5732 SendDlgMessage(hDlg, DM_LISTUPDATE, Param1, (LONG_PTR)&LUpdate);
5735 break;
5736 } else
5737 return 0;
5739 default: // подразумеваем, что остались
5740 return 0;
5743 if (NeedInit)
5744 Dlg->InitDialogObjects(Param1); // переинициализируем элементы диалога
5746 if (Dlg->DialogMode.Check(DMODE_SHOW)) // достаточно ли этого????!!!!
5748 Dlg->ShowDialog(Param1);
5749 ScrBuf.Flush();
5752 // CurItem->strData = did->PtrData;
5753 return CurItem->strData.GetLength(); //???
5756 return 0;
5758 /*****************************************************************/
5759 case DM_SETMAXTEXTLENGTH: {
5760 if ((Type == DI_EDIT || Type == DI_PSWEDIT
5761 || (Type == DI_COMBOBOX && !(CurItem->Flags & DIF_DROPDOWNLIST)))
5762 && CurItem->ObjPtr) {
5763 int MaxLen = ((DlgEdit *)(CurItem->ObjPtr))->GetMaxLength();
5764 // BugZ#628 - Неправильная длина редактируемого текста.
5765 ((DlgEdit *)(CurItem->ObjPtr))->SetMaxLength((int)Param2);
5766 // if (DialogMode.Check(DMODE_INITOBJECTS)) //???
5767 Dlg->InitDialogObjects(Param1); // переинициализируем элементы диалога
5768 if (!Dlg->DialogMode.Check(DMODE_KEEPCONSOLETITLE))
5769 ConsoleTitle::SetFarTitle(Dlg->GetDialogTitle());
5770 return MaxLen;
5773 return 0;
5775 /*****************************************************************/
5776 case DM_GETDLGITEM: {
5777 FarDialogItem *Item = (FarDialogItem *)Param2;
5778 return (LONG_PTR)ConvertItemEx2(Item, CurItem);
5780 /*****************************************************************/
5781 case DM_GETDLGITEMSHORT: {
5782 if (Param2 && ConvertItemEx(CVTITEM_TOPLUGINSHORT, (FarDialogItem *)Param2, CurItem, 1))
5783 return TRUE;
5784 return FALSE;
5786 /*****************************************************************/
5787 case DM_SETDLGITEM:
5788 case DM_SETDLGITEMSHORT: {
5789 if (!Param2)
5790 return FALSE;
5792 if (Type != ((FarDialogItem *)Param2)->Type) // пока нефига менять тип
5793 return FALSE;
5795 // не менять
5796 if (!ConvertItemEx((Msg == DM_SETDLGITEM) ? CVTITEM_FROMPLUGIN : CVTITEM_FROMPLUGINSHORT,
5797 (FarDialogItem *)Param2, CurItem, 1))
5798 return FALSE; // invalid parameters
5800 CurItem->Type = Type;
5802 if ((Type == DI_LISTBOX || Type == DI_COMBOBOX) && CurItem->ListPtr)
5803 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
5805 // еще разок, т.к. данные могли быть изменены
5806 Dlg->InitDialogObjects(Param1);
5807 if (!Dlg->DialogMode.Check(DMODE_KEEPCONSOLETITLE))
5808 ConsoleTitle::SetFarTitle(Dlg->GetDialogTitle());
5810 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5811 Dlg->ShowDialog(Param1);
5812 ScrBuf.Flush();
5815 return TRUE;
5817 /*****************************************************************/
5819 $ 03.01.2001 SVS
5820 + показать/скрыть элемент
5821 Param2:
5822 -1 - получить состояние
5823 0 - погасить
5824 1 - показать
5825 Return: предыдущее состояние
5827 case DM_SHOWITEM: {
5828 DWORD PrevFlags = CurItem->Flags;
5830 if (Param2 != -1) {
5831 if (Param2)
5832 CurItem->Flags&= ~DIF_HIDDEN;
5833 else
5834 CurItem->Flags|= DIF_HIDDEN;
5836 if (Dlg->DialogMode.Check(DMODE_SHOW)) // && (PrevFlags&DIF_HIDDEN) != (CurItem->Flags&DIF_HIDDEN))//!(CurItem->Flags&DIF_HIDDEN))
5838 if ((CurItem->Flags & DIF_HIDDEN) && Dlg->FocusPos == (unsigned)Param1) {
5839 Param2 = Dlg->ChangeFocus(Param1, 1, TRUE);
5840 Dlg->ChangeFocus2((int)Param2);
5843 // Либо все, либо... только 1
5844 Dlg->ShowDialog(Dlg->GetDropDownOpened() || (CurItem->Flags & DIF_HIDDEN) ? -1 : Param1);
5845 ScrBuf.Flush();
5849 return (PrevFlags & DIF_HIDDEN) ? FALSE : TRUE;
5851 /*****************************************************************/
5852 case DM_SETDROPDOWNOPENED: // Param1=ID; Param2={TRUE|FALSE}
5854 if (!Param2) // Закрываем любой открытый комбобокс или историю
5856 if (Dlg->GetDropDownOpened()) {
5857 Dlg->SetDropDownOpened(FALSE);
5858 WINPORT(Sleep)(10);
5861 return TRUE;
5864 $ 09.12.2001 DJ
5865 у DI_PSWEDIT не бывает хистори!
5867 else if (Param2
5868 && (Type == DI_COMBOBOX
5869 || ((Type == DI_EDIT || Type == DI_FIXEDIT) && (CurItem->Flags & DIF_HISTORY)))) /* DJ $ */
5871 // Открываем заданный в Param1 комбобокс или историю
5872 if (Dlg->GetDropDownOpened()) {
5873 Dlg->SetDropDownOpened(FALSE);
5874 WINPORT(Sleep)(10);
5877 if (SendDlgMessage(hDlg, DM_SETFOCUS, Param1, 0)) {
5878 Dlg->ProcessOpenComboBox(Type, CurItem, Param1); //?? Param1 ??
5879 // Dlg->ProcessKey(KEY_CTRLDOWN);
5880 return TRUE;
5881 } else
5882 return FALSE;
5885 return FALSE;
5887 /* KM $ */
5888 /*****************************************************************/
5889 case DM_SETITEMPOSITION: // Param1 = ID; Param2 = SMALL_RECT
5891 return Dlg->SetItemRect((int)Param1, (SMALL_RECT *)Param2);
5893 /*****************************************************************/
5895 $ 31.08.2000 SVS
5896 + переключение/получение состояния Enable/Disable элемента
5898 case DM_ENABLE: {
5899 DWORD PrevFlags = CurItem->Flags;
5901 if (Param2 != -1) {
5902 if (Param2)
5903 CurItem->Flags&= ~DIF_DISABLE;
5904 else
5905 CurItem->Flags|= DIF_DISABLE;
5907 if ((Type == DI_LISTBOX || Type == DI_COMBOBOX) && CurItem->ListPtr)
5908 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
5911 if (Dlg->DialogMode.Check(DMODE_SHOW)) //???
5913 Dlg->ShowDialog(Param1);
5914 ScrBuf.Flush();
5917 return (PrevFlags & DIF_DISABLE) ? FALSE : TRUE;
5920 case DM_GETCOLOR: {
5921 *(DWORD *)Param2 = (DWORD)Dlg->CtlColorDlgItem(Param1, CurItem);
5922 *(DWORD *)Param2|= (CurItem->Flags & DIF_SETCOLOR);
5923 return TRUE;
5926 case DM_SETCOLOR: {
5927 CurItem->Flags&= ~(DIF_SETCOLOR | DIF_COLORMASK);
5928 CurItem->Flags|= Param2 & (DIF_SETCOLOR | DIF_COLORMASK);
5930 if (Dlg->DialogMode.Check(DMODE_SHOW)) { //???
5931 Dlg->ShowDialog(Param1);
5932 ScrBuf.Flush();
5935 return TRUE;
5938 case DM_GETTRUECOLOR: {
5939 if (!CurItem->TrueColors) {
5940 memset((DialogItemTrueColors *)Param2, 0, sizeof(DialogItemTrueColors));
5941 } else {
5942 *(DialogItemTrueColors *)Param2 = *CurItem->TrueColors;
5944 return TRUE;
5947 case DM_SETTRUECOLOR: {
5948 if (!CurItem->TrueColors) {
5949 CurItem->TrueColors.reset(new DialogItemTrueColors);
5951 *CurItem->TrueColors = *(const DialogItemTrueColors *)Param2;
5952 if (Dlg->InCtlColorDlgItem == 0 && Dlg->DialogMode.Check(DMODE_SHOW)) { //???
5953 Dlg->ShowDialog(Param1);
5954 ScrBuf.Flush();
5956 return TRUE;
5959 case DM_SETREADONLY: {
5960 if (Param2) {
5961 CurItem->Flags|= DIF_READONLY;
5962 } else {
5963 CurItem->Flags&= ~DIF_READONLY;
5965 if (FarIsEdit(Type)) {
5966 DlgEdit *CurItemEdit = (DlgEdit *)CurItem->ObjPtr;
5967 if (CurItemEdit) {
5968 CurItemEdit->SetReadOnly(Param2 ? 1 : 0);
5970 } else {
5971 fprintf(stderr,
5972 "%s: DM_SETREADONLY invoked for non-edit item %u\n",
5973 __FUNCTION__, Param1);
5975 if (Dlg->DialogMode.Check(DMODE_SHOW)) { //???
5976 Dlg->ShowDialog(Param1);
5977 ScrBuf.Flush();
5979 return TRUE;
5982 /*****************************************************************/
5983 // получить позицию и размеры контрола
5984 case DM_GETITEMPOSITION: // Param1=ID, Param2=*SMALL_RECT
5986 if (Param2) {
5987 SMALL_RECT Rect;
5988 if (Dlg->GetItemRect(Param1, Rect)) {
5989 *reinterpret_cast<PSMALL_RECT>(Param2) = Rect;
5990 return TRUE;
5994 return FALSE;
5995 /*****************************************************************/
5996 case DM_SETITEMDATA: {
5997 LONG_PTR PrewDataDialog = CurItem->UserData;
5998 CurItem->UserData = Param2;
5999 return PrewDataDialog;
6001 /*****************************************************************/
6002 case DM_GETITEMDATA: {
6003 return CurItem->UserData;
6005 /*****************************************************************/
6006 case DM_EDITUNCHANGEDFLAG: // -1 Get, 0 - Skip, 1 - Set; Выделение блока снимается.
6008 if (FarIsEdit(Type)) {
6009 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
6010 int ClearFlag = EditLine->GetClearFlag();
6012 if (Param2 >= 0) {
6013 EditLine->SetClearFlag((int)Param2);
6014 EditLine->Select(-1, 0); // снимаем выделение
6016 if (Dlg->DialogMode.Check(DMODE_SHOW)) //???
6018 Dlg->ShowDialog(Param1);
6019 ScrBuf.Flush();
6023 return ClearFlag;
6026 break;
6028 /*****************************************************************/
6029 case DM_GETSELECTION: // Msg=DM_GETSELECTION, Param1=ID, Param2=*EditorSelect
6030 case DM_SETSELECTION: // Msg=DM_SETSELECTION, Param1=ID, Param2=*EditorSelect
6032 if (FarIsEdit(Type) && Param2) {
6033 if (Msg == DM_GETSELECTION) {
6034 EditorSelect *EdSel = (EditorSelect *)Param2;
6035 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
6036 EdSel->BlockStartLine = 0;
6037 EdSel->BlockHeight = 1;
6038 EditLine->GetSelection(EdSel->BlockStartPos, EdSel->BlockWidth);
6040 if (EdSel->BlockStartPos == -1 && !EdSel->BlockWidth)
6041 EdSel->BlockType = BTYPE_NONE;
6042 else {
6043 EdSel->BlockType = BTYPE_STREAM;
6044 EdSel->BlockWidth-= EdSel->BlockStartPos;
6047 return TRUE;
6048 } else {
6049 if (Param2) {
6050 EditorSelect *EdSel = (EditorSelect *)Param2;
6051 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
6053 // EdSel->BlockType=BTYPE_STREAM;
6054 // EdSel->BlockStartLine=0;
6055 // EdSel->BlockHeight=1;
6056 if (EdSel->BlockType == BTYPE_NONE)
6057 EditLine->Select(-1, 0);
6058 else
6059 EditLine->Select(EdSel->BlockStartPos, EdSel->BlockStartPos + EdSel->BlockWidth);
6061 if (Dlg->DialogMode.Check(DMODE_SHOW)) //???
6063 Dlg->ShowDialog(Param1);
6064 ScrBuf.Flush();
6067 return TRUE;
6072 break;
6076 // Все, что сами не отрабатываем - посылаем на обработку обработчику.
6077 return Dlg->CallDlgProc(Msg, Param1, Param2);
6081 $ 28.07.2000 SVS
6082 Посылка сообщения диалогу
6083 Некоторые сообщения эта функция обрабатывает сама, не передавая управление
6084 обработчику диалога.
6086 LONG_PTR WINAPI SendDlgMessage(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
6088 if (!hDlg)
6089 return 0;
6091 return InterThreadCall<LONG_PTR, 0>(std::bind(SendDlgMessageSynched, hDlg, Msg, Param1, Param2));
6094 void Dialog::SetPosition(int X1, int Y1, int X2, int Y2)
6096 CriticalSectionLock Lock(CS);
6098 if (X1 >= 0)
6099 RealWidth = X2 - X1 + 1;
6100 else
6101 RealWidth = X2;
6103 if (Y1 >= 0)
6104 RealHeight = Y2 - Y1 + 1;
6105 else
6106 RealHeight = Y2;
6108 ScreenObject::SetPosition(X1, Y1, X2, Y2);
6110 //////////////////////////////////////////////////////////////////////////
6111 BOOL Dialog::IsInited()
6113 CriticalSectionLock Lock(CS);
6114 return DialogMode.Check(DMODE_INITOBJECTS);
6117 void Dialog::SetComboBoxPos(DialogItemEx *CurItem)
6119 if (GetDropDownOpened()) {
6120 if (!CurItem) {
6121 CurItem = Item[FocusPos];
6123 int EditX1, EditY1, EditX2, EditY2;
6124 ((DlgEdit *)CurItem->ObjPtr)->GetPosition(EditX1, EditY1, EditX2, EditY2);
6126 if (EditX2 - EditX1 < 20)
6127 EditX2 = EditX1 + 20;
6129 if (ScrY - EditY1 < Min(Opt.Dialogs.CBoxMaxHeight, CurItem->ListPtr->GetItemCount()) + 2
6130 && EditY1 > ScrY / 2)
6131 CurItem->ListPtr->SetPosition(EditX1,
6132 Max(0, EditY1 - 1 - Min(Opt.Dialogs.CBoxMaxHeight, CurItem->ListPtr->GetItemCount()) - 1),
6133 EditX2, EditY1 - 1);
6134 else
6135 CurItem->ListPtr->SetPosition(EditX1, EditY1 + 1, EditX2, 0);
6139 bool Dialog::ProcessEvents()
6141 return !DialogMode.Check(DMODE_ENDLOOP);
6144 void Dialog::SetId(const GUID &Id)
6146 this->Id = Id;
6147 IdExist = true;