Merge branch 'master' of github.com:elfmz/far2l
[far2l.git] / far2l / src / dialog.cpp
blobe108939d889aa7ebc8748686f0a1c0b6b3a9369e
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 //////////////////////////////////////////////////////////////////////////
96 /**
97 * check if dialog element can be focused
99 static inline bool IsItemFocusable(const struct DialogItemEx* item)
101 switch (item->Type)
103 case DI_EDIT:
104 case DI_FIXEDIT:
105 case DI_PSWEDIT:
106 case DI_COMBOBOX:
107 case DI_MEMOEDIT:
108 case DI_BUTTON:
109 case DI_CHECKBOX:
110 case DI_RADIOBUTTON:
111 case DI_LISTBOX:
112 case DI_USERCONTROL:
113 return !(item->Flags & (DIF_NOFOCUS | DIF_DISABLE | DIF_HIDDEN));
114 default:
115 return false;
120 * check if dialog item is horizontal separator.
122 static inline bool IsItemHorizontalSeparator(const struct DialogItemEx* item)
124 return (item->Type == DI_SINGLEBOX || item->Type == DI_DOUBLEBOX ||
125 (item->Type == DI_TEXT && (item->Flags & (DIF_SEPARATOR | DIF_SEPARATOR2 | DIF_SEPARATORUSER))));
129 * check if dialog item is vertical separator.
131 static inline bool IsItemVerticalSeparator(const struct DialogItemEx* item)
133 return (item->Type == DI_SINGLEBOX || item->Type == DI_DOUBLEBOX ||
134 (item->Type == DI_VTEXT && (item->Flags & (DIF_SEPARATOR | DIF_SEPARATOR2 | DIF_SEPARATORUSER))));
137 bool IsKeyHighlighted(const wchar_t *Str, FarKey Key, int Translate, int AmpPos)
139 if (AmpPos == -1) {
140 if (!(Str = wcschr(Str, L'&')))
141 return false;
143 AmpPos = 1;
144 } else {
145 if (AmpPos >= StrLength(Str))
146 return false;
148 Str+= AmpPos;
149 AmpPos = 0;
151 if (Str[AmpPos] == L'&')
152 AmpPos++;
155 wchar_t UpperStrKey = Upper(Str[AmpPos]);
157 if (WCHAR_IS_VALID(Key)) {
158 return UpperStrKey == Upper(Key) || (Translate && KeyToKeyLayoutCompare(Upper(Key), UpperStrKey));
161 if (Key & KEY_ALT) {
162 uint32_t AltKey = Key & (~KEY_ALT);
164 if (WCHAR_IS_VALID(AltKey)) {
165 if (iswdigit(AltKey) != 0)
166 return (AltKey == (uint32_t)UpperStrKey);
168 if (AltKey > L' ')
169 // (AltKey=='-' || AltKey=='/' || AltKey==',' || AltKey=='.' ||
170 // AltKey=='\\' || AltKey=='=' || AltKey=='[' || AltKey==']' ||
171 // AltKey==':' || AltKey=='"' || AltKey=='~'))
173 return (UpperStrKey == Upper(AltKey)
174 || (Translate && KeyToKeyLayoutCompare(AltKey, UpperStrKey)));
179 return false;
182 void DialogItemExToDialogItemEx(DialogItemEx *pSrc, DialogItemEx *pDest)
184 pDest->Type = pSrc->Type;
185 pDest->X1 = pSrc->X1;
186 pDest->Y1 = pSrc->Y1;
187 pDest->X2 = pSrc->X2;
188 pDest->Y2 = pSrc->Y2;
189 pDest->Focus = pSrc->Focus;
190 pDest->Reserved = pSrc->Reserved;
191 pDest->strHistory = pSrc->strHistory;
192 pDest->strMask = pSrc->strMask;
193 pDest->Flags = pSrc->Flags;
194 pDest->DefaultButton = pSrc->DefaultButton;
195 pDest->nMaxLength = 0;
196 pDest->strData = pSrc->strData;
197 pDest->ID = pSrc->ID;
198 pDest->IFlags = pSrc->IFlags;
199 pDest->AutoCount = pSrc->AutoCount;
200 pDest->AutoPtr = pSrc->AutoPtr;
201 pDest->UserData = pSrc->UserData;
202 pDest->ObjPtr = pSrc->ObjPtr;
203 pDest->ListPtr = pSrc->ListPtr;
204 pDest->UCData = pSrc->UCData;
205 pDest->SelStart = pSrc->SelStart;
206 pDest->SelEnd = pSrc->SelEnd;
208 pDest->customItemColor[0] = pSrc->customItemColor[0];
209 pDest->customItemColor[1] = pSrc->customItemColor[1];
210 pDest->customItemColor[2] = pSrc->customItemColor[2];
211 pDest->customItemColor[3] = pSrc->customItemColor[3];
214 void ConvertItemSmall(FarDialogItem *Item, DialogItemEx *Data)
216 Item->Type = Data->Type;
217 Item->X1 = Data->X1;
218 Item->Y1 = Data->Y1;
219 Item->X2 = Data->X2;
220 Item->Y2 = Data->Y2;
221 Item->Focus = Data->Focus;
222 Item->Flags = Data->Flags;
223 Item->DefaultButton = Data->DefaultButton;
224 Item->MaxLen = Data->nMaxLength;
225 Item->PtrData = nullptr;
227 Item->Param.History = nullptr;
228 if (Data->Type == DI_LISTBOX || Data->Type == DI_COMBOBOX) {
229 Item->Param.ListPos = Data->ListPtr ? Data->ListPtr->GetSelectPos() : 0;
231 if ((Data->Type == DI_EDIT || Data->Type == DI_FIXEDIT) && Data->Flags & DIF_HISTORY) {
232 Item->Param.History = Data->strHistory;
233 } else if (Data->Type == DI_FIXEDIT && Data->Flags & DIF_MASKEDIT) {
234 Item->Param.Mask = Data->strMask;
235 } else {
236 Item->Param.Reserved = Data->Reserved;
240 size_t ItemStringAndSize(DialogItemEx *Data, FARString &ItemString)
242 DlgEdit *EditPtr;
243 if (FarIsEdit(Data->Type) && (EditPtr = (DlgEdit *)(Data->ObjPtr)) != nullptr)
244 EditPtr->GetString(ItemString);
245 else
246 ItemString = Data->strData;
248 size_t sz = ItemString.GetLength();
250 if (sz > Data->nMaxLength && Data->nMaxLength > 0)
251 sz = Data->nMaxLength;
253 return sz;
256 bool ConvertItemEx(CVTITEMFLAGS FromPlugin, FarDialogItem *Item, DialogItemEx *Data, unsigned Count)
258 unsigned I;
260 if (!Item || !Data)
261 return false;
263 switch (FromPlugin) {
264 case CVTITEM_TOPLUGIN:
265 case CVTITEM_TOPLUGINSHORT:
267 for (I = 0; I < Count; I++, ++Item, ++Data) {
268 ConvertItemSmall(Item, Data);
270 if (FromPlugin == CVTITEM_TOPLUGIN) {
271 FARString str;
272 size_t sz = ItemStringAndSize(Data, str);
274 wchar_t *p = (wchar_t *)malloc((sz + 1) * sizeof(wchar_t));
275 Item->PtrData = p;
277 if (!p) // TODO: may be needed message?
278 return false;
280 wmemcpy(p, str.CPtr(), sz);
281 p[sz] = L'\0';
286 break;
287 case CVTITEM_FROMPLUGIN:
288 case CVTITEM_FROMPLUGINSHORT:
290 for (I = 0; I < Count; I++, ++Item, ++Data) {
291 Data->X1 = Item->X1;
292 Data->Y1 = Item->Y1;
293 Data->X2 = Item->X2;
294 Data->Y2 = Item->Y2;
295 Data->Focus = Item->Focus;
296 Data->Reserved = 0;
297 if ((Item->Type == DI_EDIT || Item->Type == DI_FIXEDIT) && Item->Flags & DIF_HISTORY) {
298 Data->strHistory = Item->Param.History;
299 } else if (Item->Type == DI_FIXEDIT && Item->Flags & DIF_MASKEDIT) {
300 Data->strMask = Item->Param.Mask;
301 } else {
302 Data->Reserved = Item->Param.Reserved;
304 Data->Flags = Item->Flags;
305 Data->DefaultButton = Item->DefaultButton;
306 Data->Type = Item->Type;
308 if (FromPlugin == CVTITEM_FROMPLUGIN) {
309 Data->strData = Item->PtrData;
310 Data->nMaxLength = Item->MaxLen;
312 if (Data->nMaxLength > 0)
313 Data->strData.Truncate(Data->nMaxLength);
316 Data->ListItems = Item->Param.ListItems;
318 if (Data->X2 < Data->X1)
319 Data->X2 = Data->X1;
321 if (Data->Y2 < Data->Y1)
322 Data->Y2 = Data->Y1;
324 if ((Data->Type == DI_COMBOBOX || Data->Type == DI_LISTBOX) && !IsPtr(Item->Param.ListItems))
325 Data->ListItems = nullptr;
328 break;
331 return true;
334 size_t ConvertItemEx2(FarDialogItem *Item, DialogItemEx *Data)
336 size_t size = sizeof(*Item);
337 FARString str;
338 size_t sz = ItemStringAndSize(Data, str);
339 size+= (sz + 1) * sizeof(wchar_t);
341 if (Item) {
342 ConvertItemSmall(Item, Data);
344 wchar_t *p = (wchar_t *)(Item + 1);
345 Item->PtrData = p;
346 wmemcpy(p, str.CPtr(), sz);
347 p[sz] = L'\0';
350 return size;
353 void DataToItemEx(const DialogDataEx *Data, DialogItemEx *Item, int Count)
355 if (!Item || !Data)
356 return;
358 for (int i = 0; i < Count; i++) {
359 Item[i].Clear();
360 Item[i].ID = static_cast<WORD>(i);
361 Item[i].Type = Data[i].Type;
362 Item[i].X1 = Data[i].X1;
363 Item[i].Y1 = Data[i].Y1;
364 Item[i].X2 = Data[i].X2;
365 Item[i].Y2 = Data[i].Y2;
367 Item[i].customItemColor[0] = 0;
368 Item[i].customItemColor[1] = 0;
369 Item[i].customItemColor[2] = 0;
370 Item[i].customItemColor[3] = 0;
372 if (Item[i].X2 < Item[i].X1)
373 Item[i].X2 = Item[i].X1;
375 if (Item[i].Y2 < Item[i].Y1)
376 Item[i].Y2 = Item[i].Y1;
378 Item[i].Focus =
379 Item[i].Type != DI_SINGLEBOX && Item[i].Type != DI_DOUBLEBOX && (Data[i].Flags & DIF_FOCUS);
380 if ((Data[i].Type == DI_EDIT || Data[i].Type == DI_FIXEDIT) && Data[i].Flags & DIF_HISTORY) {
381 Item[i].strHistory = Data[i].History;
382 } else if (Data[i].Type == DI_FIXEDIT && Data[i].Flags & DIF_MASKEDIT) {
383 Item[i].strMask = Data[i].Mask;
384 } else {
385 Item[i].Reserved = Data[i].Reserved;
387 Item[i].Flags = Data[i].Flags;
388 Item[i].DefaultButton =
389 Item[i].Type != DI_TEXT && Item[i].Type != DI_VTEXT && (Data[i].Flags & DIF_DEFAULT);
390 Item[i].SelStart = -1;
392 if (!IsPtr(Data[i].Data)) // awful
393 Item[i].strData = FarLangMsg{(int)(DWORD_PTR)Data[i].Data};
394 else
395 Item[i].strData = Data[i].Data;
399 Dialog::Dialog(DialogItemEx *SrcItem, // Набор элементов диалога
400 unsigned SrcItemCount, // Количество элементов
401 FARWINDOWPROC DlgProc, // Диалоговая процедура
402 LONG_PTR InitParam) // Ассоцированные с диалогом данные
404 CMM(MACRO_DIALOG)
406 Dialog::Item = (DialogItemEx **)malloc(sizeof(DialogItemEx *) * SrcItemCount);
408 for (unsigned i = 0; i < SrcItemCount; i++) {
409 Dialog::Item[i] = new DialogItemEx;
410 Dialog::Item[i]->Clear();
411 DialogItemExToDialogItemEx(&SrcItem[i], Dialog::Item[i]);
414 Dialog::ItemCount = SrcItemCount;
415 Dialog::pSaveItemEx = SrcItem;
416 Init(DlgProc, InitParam);
419 Dialog::Dialog(FarDialogItem *SrcItem, // Набор элементов диалога
420 unsigned SrcItemCount, // Количество элементов
421 FARWINDOWPROC DlgProc, // Диалоговая процедура
422 LONG_PTR InitParam) // Ассоцированные с диалогом данные
424 CMM(MACRO_DIALOG)
426 Dialog::Item = (DialogItemEx **)malloc(sizeof(DialogItemEx *) * SrcItemCount);
428 for (unsigned i = 0; i < SrcItemCount; i++) {
429 Dialog::Item[i] = new DialogItemEx;
430 Dialog::Item[i]->Clear();
431 // BUGBUG add error check
432 ConvertItemEx(CVTITEM_FROMPLUGIN, &SrcItem[i], Dialog::Item[i], 1);
435 Dialog::ItemCount = SrcItemCount;
436 Dialog::pSaveItemEx = nullptr;
437 Init(DlgProc, InitParam);
440 void Dialog::Init(FARWINDOWPROC DlgProc, // Диалоговая процедура
441 LONG_PTR InitParam) // Ассоцированные с диалогом данные
443 SetDynamicallyBorn(FALSE); // $OT: По умолчанию все диалоги создаются статически
444 CanLoseFocus = FALSE;
445 HelpTopic = nullptr;
446 // Номер плагина, вызвавшего диалог (-1 = Main)
447 PluginNumber = -1;
448 Dialog::DataDialog = InitParam;
449 DialogMode.Set(DMODE_ISCANMOVE);
450 SetDropDownOpened(FALSE);
451 IsEnableRedraw = 0;
452 InCtlColorDlgItem = 0;
453 FocusPos = (unsigned)-1;
454 PrevFocusPos = (unsigned)-1;
456 if (!DlgProc) // функция должна быть всегда!!!
458 DlgProc = DefDlgProc;
459 // знать диалог в старом стиле - учтем этот факт!
460 DialogMode.Set(DMODE_OLDSTYLE);
463 Dialog::RealDlgProc = DlgProc;
465 //_SVS(SysLog(L"Dialog =%d",CtrlObject->Macro.GetMode()));
466 // запоминаем предыдущий заголовок консоли
467 OldTitle = new ConsoleTitle;
468 IdExist = false;
469 memset(&Id, 0, sizeof(Id));
472 //////////////////////////////////////////////////////////////////////////
474 Public, Virtual:
475 Деструктор класса Dialog
477 Dialog::~Dialog()
479 _tran(SysLog(L"[%p] Dialog::~Dialog()", this));
481 DeleteDialogObjects();
483 Hide();
484 ScrBuf.Flush();
486 if (HelpTopic)
487 delete[] HelpTopic;
489 for (unsigned i = 0; i < ItemCount; i++)
490 delete Item[i];
492 free(Item);
493 delete OldTitle;
495 if (!WinPortTesting()) {
496 INPUT_RECORD rec;
497 PeekInputRecord(&rec);
500 _DIALOG(CleverSysLog CL(L"Destroy Dialog"));
503 void Dialog::CheckDialogCoord()
505 CriticalSectionLock Lock(CS);
507 if (X1 == -1) // задано центрирование диалога по горизонтали?
508 { // X2 при этом = ширине диалога.
509 X1 = (ScrX - X2 + 1) / 2;
511 if (X1 < 0) // ширина диалога больше ширины экрана?
513 X1 = 0;
514 } else {
515 X2+= X1 - 1;
519 if (Y1 == -1) // задано центрирование диалога по вертикали?
520 { // Y2 при этом = высоте диалога.
521 Y1 = (ScrY - Y2 + 1) / 2;
523 if (!DialogMode.Check(DMODE_SMALLDIALOG)) //????
524 if (Y1 > 5)
525 Y1--;
527 if (Y1 < 0) {
528 Y1 = 0;
529 } else {
530 Y2+= Y1 - 1;
535 void Dialog::InitDialog()
537 CriticalSectionLock Lock(CS);
539 if (!DialogMode.Check(DMODE_INITOBJECTS)) // самодостаточный вариант, когда
540 { // элементы инициализируются при первом вызове.
541 CheckDialogCoord();
542 unsigned InitFocus = InitDialogObjects();
543 int Result = (int)DlgProc((HANDLE)this, DN_INITDIALOG, InitFocus, DataDialog);
545 if (ExitCode == -1) {
546 if (Result) {
547 // еще разок, т.к. данные могли быть изменены
548 InitFocus = InitDialogObjects(); // InitFocus=????
551 if (!DialogMode.Check(DMODE_KEEPCONSOLETITLE))
552 ConsoleTitle::SetFarTitle(GetDialogTitle());
555 // все объекты проинициализированы!
556 DialogMode.Set(DMODE_INITOBJECTS);
557 DialogInfo di = {sizeof(di)};
559 if (DlgProc(reinterpret_cast<HANDLE>(this), DN_GETDIALOGINFO, 0, reinterpret_cast<LONG_PTR>(&di))) {
560 Id = di.Id;
561 IdExist = true;
564 DlgProc((HANDLE)this, DN_GOTFOCUS, InitFocus, 0);
568 //////////////////////////////////////////////////////////////////////////
570 Public, Virtual:
571 Расчет значений координат окна диалога и вызов функции
572 ScreenObject::Show() для вывода диалога на экран.
574 void Dialog::Show()
576 CriticalSectionLock Lock(CS);
577 _tran(SysLog(L"[%p] Dialog::Show()", this));
579 if (!DialogMode.Check(DMODE_INITOBJECTS))
580 return;
582 if (!Locked() && DialogMode.Check(DMODE_RESIZED)) {
583 PreRedrawItem preRedrawItem = PreRedraw.Peek();
585 if (preRedrawItem.PreRedrawFunc)
586 preRedrawItem.PreRedrawFunc();
589 DialogMode.Clear(DMODE_RESIZED);
591 if (Locked())
592 return;
594 DialogMode.Set(DMODE_SHOW);
595 ScreenObject::Show();
598 // Цель перехвата данной функции - управление видимостью...
599 void Dialog::Hide()
601 CriticalSectionLock Lock(CS);
602 _tran(SysLog(L"[%p] Dialog::Hide()", this));
604 if (!DialogMode.Check(DMODE_INITOBJECTS))
605 return;
607 DialogMode.Clear(DMODE_SHOW);
608 ScreenObject::Hide();
611 //////////////////////////////////////////////////////////////////////////
613 Private, Virtual:
614 Инициализация объектов и вывод диалога на экран.
616 void Dialog::DisplayObject()
618 CriticalSectionLock Lock(CS);
620 if (DialogMode.Check(DMODE_SHOW)) {
621 ChangePriority ChPriority(ChangePriority::NORMAL);
622 ShowDialog(); // "нарисуем" диалог
626 // пересчитать координаты для элементов с DIF_CENTERGROUP
627 void Dialog::ProcessCenterGroup()
629 CriticalSectionLock Lock(CS);
631 for (unsigned I = 0; I < ItemCount; I++) {
633 Последовательно объявленные элементы с флагом DIF_CENTERGROUP
634 и одинаковой вертикальной позицией будут отцентрированы в диалоге.
635 Их координаты X не важны. Удобно использовать для центрирования
636 групп кнопок.
638 if ((Item[I]->Flags & DIF_CENTERGROUP)
639 && (I == 0 || (Item[I - 1]->Flags & DIF_CENTERGROUP) == 0
640 || Item[I - 1]->Y1 != Item[I]->Y1)) {
641 int Length = 0;
643 for (UINT J = I;
644 J < ItemCount && (Item[J]->Flags & DIF_CENTERGROUP) && Item[J]->Y1 == Item[I]->Y1; J++) {
645 Length+= LenStrItem(J);
647 if (!Item[J]->strData.IsEmpty())
648 switch (Item[J]->Type) {
649 case DI_BUTTON:
650 Length++;
651 break;
652 case DI_CHECKBOX:
653 case DI_RADIOBUTTON:
654 Length+= 5;
655 break;
659 if (!Item[I]->strData.IsEmpty())
660 switch (Item[I]->Type) {
661 case DI_BUTTON:
662 Length--;
663 break;
664 case DI_CHECKBOX:
665 case DI_RADIOBUTTON:
666 // Length-=5;
667 break;
668 } // Бля, це ж ботва какая-то
670 int StartX = Max(0, (X2 - X1 + 1 - Length) / 2);
672 for (UINT J = I;
673 J < ItemCount && (Item[J]->Flags & DIF_CENTERGROUP) && Item[J]->Y1 == Item[I]->Y1; J++) {
674 Item[J]->X1 = StartX;
675 StartX+= LenStrItem(J);
677 if (!Item[J]->strData.IsEmpty())
678 switch (Item[J]->Type) {
679 case DI_BUTTON:
680 StartX++;
681 break;
682 case DI_CHECKBOX:
683 case DI_RADIOBUTTON:
684 StartX+= 5;
685 break;
688 if (StartX == Item[J]->X1)
689 Item[J]->X2 = StartX;
690 else
691 Item[J]->X2 = StartX - 1;
697 //////////////////////////////////////////////////////////////////////////
699 Public:
700 Инициализация элементов диалога.
702 InitDialogObjects возвращает ID элемента с фокусом ввода
703 Параметр - для выборочной реинициализации элементов. ID = -1 - касаемо всех объектов
706 TODO: Необходимо применить ProcessRadioButton для исправления
707 кривых рук некоторых плагинописателей (а надо?)
709 unsigned Dialog::InitDialogObjects(unsigned ID)
711 CriticalSectionLock Lock(CS);
712 unsigned I, J;
713 int Type;
714 DialogItemEx *CurItem;
715 unsigned InitItemCount;
716 DWORD ItemFlags;
717 _DIALOG(CleverSysLog CL(L"Init Dialog"));
719 if (ID == (unsigned)-1) // инициализируем все?
721 ID = 0;
722 InitItemCount = ItemCount;
723 } else if (ID + 1 > ItemCount) {
724 return (unsigned)-1;
725 } else {
726 InitItemCount = ID + 1;
729 // если FocusPos в пределах и элемент задисаблен, то ищем сначала
730 if (FocusPos != (unsigned)-1 && FocusPos < ItemCount && !IsItemFocusable(Item[FocusPos]))
731 FocusPos = (unsigned)-1; // будем искать сначала!
733 // предварительный цикл по поводу кнопок
734 for (I = ID; I < InitItemCount; I++) {
735 CurItem = Item[I];
736 ItemFlags = CurItem->Flags;
737 Type = CurItem->Type;
739 if (Type == DI_BUTTON && ItemFlags & DIF_SETSHIELD) {
740 CurItem->strData = FARString(L"\x2580\x2584 ") + CurItem->strData;
744 для кнопок не имеющи стиля "Показывает заголовок кнопки без скобок"
745 добавим энти самые скобки
747 if (Type == DI_BUTTON && !(ItemFlags & DIF_NOBRACKETS)) {
748 LPCWSTR Brackets[] = {L"[ ", L" ]", L"{ ", L" }"};
749 int Start = (CurItem->DefaultButton ? 2 : 0);
750 if (CurItem->strData.At(0) != *Brackets[Start]) {
751 CurItem->strData = Brackets[Start] + CurItem->strData + Brackets[Start + 1];
754 // предварительный поик фокуса
755 if (FocusPos == (unsigned)-1 && IsItemFocusable(CurItem) && CurItem->Focus)
756 FocusPos = I; // запомним первый фокусный элемент
758 CurItem->Focus = 0; // сбросим для всех, чтобы не оказалось,
759 // что фокусов - как у дурочка фантиков
761 // сбросим флаг DIF_CENTERGROUP для редакторов
762 switch (Type) {
763 case DI_BUTTON:
764 case DI_CHECKBOX:
765 case DI_RADIOBUTTON:
766 case DI_TEXT:
767 case DI_VTEXT: // ????
768 break;
769 default:
771 if (ItemFlags & DIF_CENTERGROUP)
772 CurItem->Flags&= ~DIF_CENTERGROUP;
777 Опять про фокус ввода - теперь, если "чудо" забыло выставить
778 хотя бы один, то ставим на первый подходящий
780 if (FocusPos == (unsigned)-1) {
781 for (I = 0; I < ItemCount; I++) // по всем!!!!
783 CurItem = Item[I];
785 if (IsItemFocusable(CurItem)) {
786 FocusPos = I;
787 break;
792 if (FocusPos == (unsigned)-1) // ну ни хрена себе - нет ни одного
793 { // элемента с возможностью фокуса
794 FocusPos = 0; // убится, блин
797 // ну вот и добрались до!
798 Item[FocusPos]->Focus = 1;
799 // а теперь все сначала и по полной программе...
800 ProcessCenterGroup(); // сначала отцентрируем
802 for (I = ID; I < InitItemCount; I++) {
803 CurItem = Item[I];
804 Type = CurItem->Type;
805 ItemFlags = CurItem->Flags;
807 if (Type == DI_LISTBOX) {
808 if (!DialogMode.Check(DMODE_CREATEOBJECTS)) {
809 CurItem->ListPtr = new VMenu(nullptr, nullptr, 0, CurItem->Y2 - CurItem->Y1 + 1,
810 VMENU_ALWAYSSCROLLBAR | VMENU_LISTBOX, nullptr, this);
813 if (CurItem->ListPtr) {
814 VMenu *ListPtr = CurItem->ListPtr;
815 ListPtr->SetVDialogItemID(I);
817 $ 13.09.2000 SVS
818 + Флаг DIF_LISTNOAMPERSAND. По умолчанию для DI_LISTBOX &
819 DI_COMBOBOX выставляется флаг MENU_SHOWAMPERSAND. Этот флаг
820 подавляет такое поведение
822 CurItem->IFlags.Set(DLGIIF_LISTREACTIONFOCUS | DLGIIF_LISTREACTIONNOFOCUS); // всегда!
823 ListPtr->ChangeFlags(VMENU_DISABLED, ItemFlags & DIF_DISABLE);
824 ListPtr->ChangeFlags(VMENU_SHOWAMPERSAND, !(ItemFlags & DIF_LISTNOAMPERSAND));
825 ListPtr->ChangeFlags(VMENU_SHOWNOBOX, ItemFlags & DIF_LISTNOBOX);
826 ListPtr->ChangeFlags(VMENU_WRAPMODE, ItemFlags & DIF_LISTWRAPMODE);
827 ListPtr->ChangeFlags(VMENU_AUTOHIGHLIGHT, ItemFlags & DIF_LISTAUTOHIGHLIGHT);
829 if (ItemFlags & DIF_LISTAUTOHIGHLIGHT)
830 ListPtr->AssignHighlights(FALSE);
832 ListPtr->SetDialogStyle(DialogMode.Check(DMODE_WARNINGSTYLE));
833 ListPtr->SetPosition(X1 + CurItem->X1, Y1 + CurItem->Y1, X1 + CurItem->X2, Y1 + CurItem->Y2);
834 ListPtr->SetBoxType(SHORT_SINGLE_BOX);
836 // поле FarDialogItem.Data для DI_LISTBOX используется как верхний заголовок листа
837 if (!(ItemFlags & DIF_LISTNOBOX) && !DialogMode.Check(DMODE_CREATEOBJECTS)) {
838 ListPtr->SetTitle(CurItem->strData);
841 // удалим все итемы
842 // ListBox->DeleteItems(); //???? А НАДО ЛИ ????
843 if (CurItem->ListItems && !DialogMode.Check(DMODE_CREATEOBJECTS)) {
844 ListPtr->AddItem(CurItem->ListItems);
847 ListPtr->ChangeFlags(VMENU_LISTHASFOCUS, CurItem->Focus);
850 // "редакторы" - разговор особый...
851 else if (FarIsEdit(Type)) {
853 сбросим флаг DIF_EDITOR для строки ввода, отличной от DI_EDIT,
854 DI_FIXEDIT и DI_PSWEDIT
856 if (Type != DI_COMBOBOX)
857 if ((ItemFlags & DIF_EDITOR) && Type != DI_EDIT && Type != DI_FIXEDIT && Type != DI_PSWEDIT)
858 ItemFlags&= ~DIF_EDITOR;
860 if (!DialogMode.Check(DMODE_CREATEOBJECTS)) {
861 CurItem->ObjPtr =
862 new DlgEdit(this, I, Type == DI_MEMOEDIT ? DLGEDIT_MULTILINE : DLGEDIT_SINGLELINE);
864 if (Type == DI_COMBOBOX) {
865 CurItem->ListPtr = new VMenu(L"", nullptr, 0, Opt.Dialogs.CBoxMaxHeight,
866 VMENU_ALWAYSSCROLLBAR | VMENU_NOTCHANGE, nullptr, this);
867 CurItem->ListPtr->SetVDialogItemID(I);
870 CurItem->SelStart = -1;
873 DlgEdit *DialogEdit = (DlgEdit *)CurItem->ObjPtr;
874 // Mantis#58 - символ-маска с кодом 0х0А - пропадает
875 // DialogEdit->SetDialogParent((Type != DI_COMBOBOX && (ItemFlags & DIF_EDITOR) || (CurItem->Type==DI_PSWEDIT || CurItem->Type==DI_FIXEDIT))?
876 // FEDITLINE_PARENT_SINGLELINE:FEDITLINE_PARENT_MULTILINE);
877 DialogEdit->SetDialogParent(
878 Type == DI_MEMOEDIT ? FEDITLINE_PARENT_MULTILINE : FEDITLINE_PARENT_SINGLELINE);
879 DialogEdit->SetReadOnly(0);
881 if (Type == DI_COMBOBOX) {
882 if (CurItem->ListPtr) {
883 VMenu *ListPtr = CurItem->ListPtr;
884 ListPtr->SetBoxType(SHORT_SINGLE_BOX);
885 DialogEdit->SetDropDownBox(ItemFlags & DIF_DROPDOWNLIST);
886 ListPtr->ChangeFlags(VMENU_WRAPMODE, ItemFlags & DIF_LISTWRAPMODE);
887 ListPtr->ChangeFlags(VMENU_DISABLED, ItemFlags & DIF_DISABLE);
888 ListPtr->ChangeFlags(VMENU_SHOWAMPERSAND, !(ItemFlags & DIF_LISTNOAMPERSAND));
889 ListPtr->ChangeFlags(VMENU_AUTOHIGHLIGHT, ItemFlags & DIF_LISTAUTOHIGHLIGHT);
891 if (ItemFlags & DIF_LISTAUTOHIGHLIGHT)
892 ListPtr->AssignHighlights(FALSE);
894 if (CurItem->ListItems && !DialogMode.Check(DMODE_CREATEOBJECTS))
895 ListPtr->AddItem(CurItem->ListItems);
897 ListPtr->SetFlags(VMENU_COMBOBOX);
898 ListPtr->SetDialogStyle(DialogMode.Check(DMODE_WARNINGSTYLE));
903 $ 15.10.2000 tran
904 строка редакторирование должна иметь максимум в 511 символов
905 выставляем максимальный размер в том случае, если он еще не выставлен
908 // BUGBUG
909 if (DialogEdit->GetMaxLength() == -1)
910 DialogEdit->SetMaxLength(CurItem->nMaxLength ? (int)CurItem->nMaxLength : -1);
912 DialogEdit->SetPosition(X1 + CurItem->X1, Y1 + CurItem->Y1, X1 + CurItem->X2, Y1 + CurItem->Y2);
915 DialogEdit->SetObjectColor(
916 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE) ?
917 ((ItemFlags&DIF_DISABLE)?COL_WARNDIALOGEDITDISABLED:COL_WARNDIALOGEDIT):
918 ((ItemFlags&DIF_DISABLE)?COL_DIALOGEDITDISABLED:COL_DIALOGEDIT)),
919 FarColorToReal((ItemFlags&DIF_DISABLE)?COL_DIALOGEDITDISABLED:COL_DIALOGEDITSELECTED)
922 if (CurItem->Type == DI_PSWEDIT) {
923 DialogEdit->SetPasswordMode(TRUE);
924 // ...Что бы небыло повадно... и для повыщения защиты, т.с.
925 ItemFlags&= ~DIF_HISTORY;
928 if (Type == DI_FIXEDIT) {
929 // DIF_HISTORY имеет более высокий приоритет, чем DIF_MASKEDIT
930 if (ItemFlags & DIF_HISTORY)
931 ItemFlags&= ~DIF_MASKEDIT;
934 если DI_FIXEDIT, то курсор сразу ставится на замену...
935 ай-ай - было недокументированно :-)
937 DialogEdit->SetMaxLength(CurItem->X2 - CurItem->X1 + 1
938 + (CurItem->X2 == CurItem->X1 || !(ItemFlags & DIF_HISTORY) ? 0 : 1));
939 DialogEdit->SetOvertypeMode(TRUE);
941 $ 12.08.2000 KM
942 Если тип строки ввода DI_FIXEDIT и установлен флаг DIF_MASKEDIT
943 и непустой параметр CurItem->Mask, то вызываем новую функцию
944 для установки маски в объект DlgEdit.
947 // Маска не должна быть пустой (строка из пробелов не учитывается)!
948 if ((ItemFlags & DIF_MASKEDIT) && !CurItem->strMask.IsEmpty()) {
949 RemoveExternalSpaces(CurItem->strMask);
950 if (!CurItem->strMask.IsEmpty()) {
951 DialogEdit->SetInputMask(CurItem->strMask);
952 } else {
953 ItemFlags&= ~DIF_MASKEDIT;
956 } else
959 "мини-редактор"
960 Последовательно определенные поля ввода (edit controls),
961 имеющие этот флаг группируются в редактор с возможностью
962 вставки и удаления строк
964 if (!(ItemFlags & DIF_EDITOR) && CurItem->Type != DI_COMBOBOX) {
965 DialogEdit->SetEditBeyondEnd(FALSE);
967 if (!DialogMode.Check(DMODE_INITOBJECTS))
968 DialogEdit->SetClearFlag(1);
971 if (CurItem->Type == DI_COMBOBOX)
972 DialogEdit->SetClearFlag(1);
975 $ 01.08.2000 SVS
976 Еже ли стоит флаг DIF_USELASTHISTORY и непустая строка ввода,
977 то подстанавливаем первое значение из History
979 if (CurItem->Type == DI_EDIT
980 && (ItemFlags & (DIF_HISTORY | DIF_USELASTHISTORY))
981 == (DIF_HISTORY | DIF_USELASTHISTORY)) {
982 ProcessLastHistory(CurItem, -1);
985 if ((ItemFlags & DIF_MANUALADDHISTORY) && !(ItemFlags & DIF_HISTORY))
986 ItemFlags&= ~DIF_MANUALADDHISTORY; // сбросим нафиг.
989 $ 18.03.2000 SVS
990 Если это ComBoBox и данные не установлены, то берем из списка
991 при условии, что хоть один из пунктов имеет Selected
994 if (Type == DI_COMBOBOX && CurItem->strData.IsEmpty() && CurItem->ListItems) {
995 FarListItem *ListItems = CurItem->ListItems->Items;
996 unsigned Length = CurItem->ListItems->ItemsNumber;
997 // CurItem->ListPtr->AddItem(CurItem->ListItems);
999 for (J = 0; J < Length; J++) {
1000 if (ListItems[J].Flags & LIF_SELECTED) {
1001 if (ItemFlags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND))
1002 HiText2Str(CurItem->strData, ListItems[J].Text);
1003 else
1004 CurItem->strData = ListItems[J].Text;
1006 break;
1011 DialogEdit->SetCallbackState(false);
1012 DialogEdit->SetString(CurItem->strData);
1013 DialogEdit->SetCallbackState(true);
1015 if (Type == DI_FIXEDIT)
1016 DialogEdit->SetCurPos(0);
1018 // Для обычных строк отрубим постоянные блоки
1019 if (!(ItemFlags & DIF_EDITOR))
1020 DialogEdit->SetPersistentBlocks(Opt.Dialogs.EditBlock);
1022 DialogEdit->SetDelRemovesBlocks(Opt.Dialogs.DelRemovesBlocks);
1024 if (ItemFlags & DIF_READONLY)
1025 DialogEdit->SetReadOnly(1);
1026 } else if (Type == DI_USERCONTROL) {
1027 if (!DialogMode.Check(DMODE_CREATEOBJECTS))
1028 CurItem->UCData = new DlgUserControl;
1031 CurItem->Flags = ItemFlags;
1034 // если будет редактор, то обязательно будет выделен.
1035 SelectOnEntry(FocusPos, TRUE);
1036 // все объекты созданы!
1037 DialogMode.Set(DMODE_CREATEOBJECTS);
1038 return FocusPos;
1041 const wchar_t *Dialog::GetDialogTitle()
1043 CriticalSectionLock Lock(CS);
1044 DialogItemEx *CurItem, *CurItemList = nullptr;
1046 for (unsigned I = 0; I < ItemCount; I++) {
1047 CurItem = Item[I];
1049 // по первому попавшемуся "тексту" установим заголовок консоли!
1050 if ((CurItem->Type == DI_TEXT || CurItem->Type == DI_DOUBLEBOX || CurItem->Type == DI_SINGLEBOX)) {
1051 const wchar_t *Ptr = CurItem->strData;
1053 for (; *Ptr; Ptr++)
1054 if (IsAlpha(*Ptr) || iswdigit(*Ptr))
1055 return (Ptr);
1056 } else if (CurItem->Type == DI_LISTBOX && !I)
1057 CurItemList = CurItem;
1060 if (CurItemList) {
1061 return CurItemList->ListPtr->GetPtrTitle();
1064 return nullptr; //""
1067 void Dialog::ProcessLastHistory(DialogItemEx *CurItem, int MsgIndex)
1069 CriticalSectionLock Lock(CS);
1070 FARString &strData = CurItem->strData;
1072 if (strData.IsEmpty()) {
1073 FARString strRegKey = fmtSavedDialogHistory;
1074 strRegKey+= CurItem->strHistory;
1075 History::ReadLastItem(strRegKey.GetMB().c_str(), strData);
1077 if (MsgIndex != -1) {
1078 // обработка DM_SETHISTORY => надо пропустить изменение текста через
1079 // диалоговую функцию
1080 FarDialogItemData IData;
1081 IData.PtrData = const_cast<wchar_t *>(strData.CPtr());
1082 IData.PtrLength = (int)strData.GetLength();
1083 SendDlgMessage(this, DM_SETTEXT, MsgIndex, (LONG_PTR)&IData);
1089 static int ToRange(int Val, int Min, int Max)
1091 return std::min(std::max(Val, Min), Max);
1094 // Изменение координат и/или размеров итема диалога.
1095 BOOL Dialog::SetItemRect(unsigned ID, SMALL_RECT *aRect)
1097 CriticalSectionLock Lock(CS);
1099 if (ID >= ItemCount)
1100 return FALSE;
1103 auto Rect = *aRect;
1104 Rect.Left = ToRange(Rect.Left, 0, X2-X1);
1105 Rect.Top = ToRange(Rect.Top, 0, Y2-Y1);
1106 Rect.Right = ToRange(Rect.Right, Rect.Left, X2-X1);
1107 Rect.Bottom = ToRange(Rect.Bottom, Rect.Top, Y2-Y1);
1109 DialogItemEx *CurItem = Item[ID];
1110 int Type = CurItem->Type;
1111 CurItem->X1 = Rect.Left;
1112 CurItem->Y1 = (Rect.Top < 0) ? 0 : Rect.Top;
1114 if (FarIsEdit(Type)) {
1115 DlgEdit *DialogEdit = (DlgEdit *)CurItem->ObjPtr;
1116 CurItem->X2 = Rect.Right;
1117 CurItem->Y2 = (Type == DI_MEMOEDIT ? Rect.Bottom : 0);
1118 DialogEdit->SetPosition(X1 + Rect.Left, Y1 + Rect.Top, X1 + Rect.Right, Y1 + Rect.Top);
1119 } else if (Type == DI_LISTBOX) {
1120 CurItem->X2 = Rect.Right;
1121 CurItem->Y2 = Rect.Bottom;
1122 CurItem->ListPtr->SetPosition(X1 + Rect.Left, Y1 + Rect.Top, X1 + Rect.Right, Y1 + Rect.Bottom);
1123 CurItem->ListPtr->SetMaxHeight(CurItem->Y2 - CurItem->Y1 + 1);
1126 switch (Type) {
1127 case DI_TEXT:
1128 CurItem->X2 = Rect.Right;
1129 CurItem->Y2 = 0; // ???
1130 break;
1131 case DI_VTEXT:
1132 CurItem->X2 = 0; // ???
1133 CurItem->Y2 = Rect.Bottom;
1134 case DI_DOUBLEBOX:
1135 case DI_SINGLEBOX:
1136 case DI_USERCONTROL:
1137 CurItem->X2 = Rect.Right;
1138 CurItem->Y2 = Rect.Bottom;
1139 break;
1142 if (DialogMode.Check(DMODE_SHOW)) {
1143 ShowDialog((unsigned)-1);
1144 ScrBuf.Flush();
1147 return TRUE;
1150 BOOL Dialog::GetItemRect(unsigned I, SMALL_RECT &Rect)
1152 CriticalSectionLock Lock(CS);
1154 if (I >= ItemCount)
1155 return FALSE;
1157 DialogItemEx *CurItem = Item[I];
1158 DWORD ItemFlags = CurItem->Flags;
1159 int Type = CurItem->Type;
1160 int Len = 0;
1161 Rect.Left = CurItem->X1;
1162 Rect.Top = CurItem->Y1;
1163 Rect.Right = CurItem->X2;
1164 Rect.Bottom = CurItem->Y2;
1166 switch (Type) {
1167 case DI_COMBOBOX:
1168 case DI_EDIT:
1169 case DI_FIXEDIT:
1170 case DI_PSWEDIT:
1171 case DI_LISTBOX:
1172 case DI_MEMOEDIT:
1173 break;
1174 default:
1175 Len = ((ItemFlags & DIF_SHOWAMPERSAND)
1176 ? (int)CurItem->strData.CellsCount()
1177 : HiStrCellsCount(CurItem->strData));
1178 break;
1181 switch (Type) {
1182 case DI_TEXT:
1184 if (CurItem->X1 == -1)
1185 Rect.Left = (X2 - X1 + 1 - Len) / 2;
1187 if (Rect.Left < 0)
1188 Rect.Left = 0;
1190 if (CurItem->Y1 == -1)
1191 Rect.Top = (Y2 - Y1 + 1) / 2;
1193 if (Rect.Top < 0)
1194 Rect.Top = 0;
1196 Rect.Bottom = Rect.Top;
1198 if (!Rect.Right || Rect.Right == Rect.Left)
1199 Rect.Right = Rect.Left + Len - (Len ? 1 : 0);
1201 if (ItemFlags & (DIF_SEPARATOR | DIF_SEPARATOR2)) {
1202 Rect.Bottom = Rect.Top;
1203 Rect.Left = (!DialogMode.Check(DMODE_SMALLDIALOG) ? 3 : 0); //???
1204 Rect.Right = X2 - X1 - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 5 : 0); //???
1207 break;
1208 case DI_VTEXT:
1210 if (CurItem->X1 == -1)
1211 Rect.Left = (X2 - X1 + 1) / 2;
1213 if (Rect.Left < 0)
1214 Rect.Left = 0;
1216 if (CurItem->Y1 == -1)
1217 Rect.Top = (Y2 - Y1 + 1 - Len) / 2;
1219 if (Rect.Top < 0)
1220 Rect.Top = 0;
1222 Rect.Right = Rect.Left;
1224 // Rect.bottom=Rect.top+Len;
1225 if (!Rect.Bottom || Rect.Bottom == Rect.Top)
1226 Rect.Bottom = Rect.Top + Len - (Len ? 1 : 0);
1228 #if defined(VTEXT_ADN_SEPARATORS)
1230 if (ItemFlags & (DIF_SEPARATOR | DIF_SEPARATOR2)) {
1231 Rect.Right = Rect.Left;
1232 Rect.Top = (!DialogMode.Check(DMODE_SMALLDIALOG) ? 1 : 0); //???
1233 Rect.Bottom = Y2 - Y1 - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 3 : 0); //???
1234 break;
1237 #endif
1238 break;
1239 case DI_BUTTON:
1240 Rect.Bottom = Rect.Top;
1241 Rect.Right = Rect.Left + Len;
1242 break;
1243 case DI_CHECKBOX:
1244 case DI_RADIOBUTTON:
1245 Rect.Bottom = Rect.Top;
1246 Rect.Right = Rect.Left + Len + ((Type == DI_CHECKBOX) ? 4 : (ItemFlags & DIF_MOVESELECT ? 3 : 4));
1247 break;
1248 case DI_COMBOBOX:
1249 case DI_EDIT:
1250 case DI_FIXEDIT:
1251 case DI_PSWEDIT:
1252 Rect.Bottom = Rect.Top;
1253 break;
1256 return TRUE;
1259 bool Dialog::ItemHasDropDownArrow(const DialogItemEx *Item)
1261 return ((!Item->strHistory.IsEmpty() && (Item->Flags & DIF_HISTORY) && Opt.Dialogs.EditHistory)
1262 || (Item->Type == DI_COMBOBOX && Item->ListPtr && Item->ListPtr->GetItemCount() > 0));
1265 //////////////////////////////////////////////////////////////////////////
1267 Private:
1268 Получение данных и удаление "редакторов"
1270 void Dialog::DeleteDialogObjects()
1272 CriticalSectionLock Lock(CS);
1273 DialogItemEx *CurItem;
1275 for (unsigned I = 0; I < ItemCount; I++) {
1276 CurItem = Item[I];
1278 switch (CurItem->Type) {
1279 case DI_EDIT:
1280 case DI_FIXEDIT:
1281 case DI_PSWEDIT:
1282 case DI_COMBOBOX:
1283 case DI_MEMOEDIT:
1285 if (CurItem->ObjPtr)
1286 delete (DlgEdit *)(CurItem->ObjPtr);
1288 case DI_LISTBOX:
1290 if ((CurItem->Type == DI_COMBOBOX || CurItem->Type == DI_LISTBOX) && CurItem->ListPtr)
1291 delete CurItem->ListPtr;
1293 break;
1294 case DI_USERCONTROL:
1296 if (CurItem->UCData)
1297 delete CurItem->UCData;
1299 break;
1302 if (CurItem->Flags & DIF_AUTOMATION)
1303 if (CurItem->AutoPtr)
1304 free(CurItem->AutoPtr);
1308 //////////////////////////////////////////////////////////////////////////
1310 Public:
1311 Сохраняет значение из полей редактирования.
1312 При установленном флаге DIF_HISTORY, сохраняет данные в реестре.
1314 void Dialog::GetDialogObjectsData()
1316 CriticalSectionLock Lock(CS);
1317 int Type;
1318 DialogItemEx *CurItem;
1320 for (unsigned I = 0; I < ItemCount; I++) {
1321 CurItem = Item[I];
1322 DWORD IFlags = CurItem->Flags;
1324 switch (Type = CurItem->Type) {
1325 case DI_MEMOEDIT:
1326 break; //????
1327 case DI_EDIT:
1328 case DI_FIXEDIT:
1329 case DI_PSWEDIT:
1330 case DI_COMBOBOX: {
1331 if (CurItem->ObjPtr) {
1332 FARString strData;
1333 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
1336 подготовим данные
1337 получим данные
1339 EditPtr->GetString(strData);
1341 if (ExitCode >= 0 && (IFlags & DIF_HISTORY) && !(IFlags & DIF_MANUALADDHISTORY) && // при мануале не добавляем
1342 !CurItem->strHistory.IsEmpty() && Opt.Dialogs.EditHistory) {
1343 AddToEditHistory(strData, CurItem->strHistory);
1347 $ 01.08.2000 SVS
1348 ! В History должно заносится значение (для DIF_EXPAND...) перед
1349 расширением среды!
1353 $ 05.07.2000 SVS $
1354 Проверка - этот элемент предполагает расширение переменных среды?
1355 т.к. функция GetDialogObjectsData() может вызываться самостоятельно
1356 Но надо проверить!
1360 $ 04.12.2000 SVS
1361 ! Для DI_PSWEDIT и DI_FIXEDIT обработка DIF_EDITEXPAND не нужна
1362 (DI_FIXEDIT допускается для случая если нету маски)
1365 if ((IFlags & DIF_EDITEXPAND) && Type != DI_PSWEDIT && Type != DI_FIXEDIT) {
1366 apiExpandEnvironmentStrings(strData, strData);
1367 // как бы грязный хак, нам нужно обновить строку чтоб отдавалась правильная строка
1368 // для различных DM_* после закрытия диалога, но ни в коем случае нельзя чтоб
1369 // высылался DN_EDITCHANGE для этого изменения, ибо диалог уже закрыт.
1370 EditPtr->SetCallbackState(false);
1371 EditPtr->SetString(strData);
1372 EditPtr->SetCallbackState(true);
1375 CurItem->strData = strData;
1378 break;
1380 case DI_LISTBOX:
1382 if(CurItem->ListPtr)
1384 CurItem->ListPos=CurItem->ListPtr->GetSelectPos();
1385 break;
1388 break;
1391 #if 0
1393 if ((Type == DI_COMBOBOX || Type == DI_LISTBOX) && CurItem->ListPtr && CurItem->ListItems && DlgProc == DefDlgProc)
1395 int ListPos=CurItem->ListPtr->GetSelectPos();
1397 if (ListPos < CurItem->ListItems->ItemsNumber)
1399 for (int J=0; J < CurItem->ListItems->ItemsNumber; ++J)
1400 CurItem->ListItems->Items[J].Flags&=~LIF_SELECTED;
1402 CurItem->ListItems->Items[ListPos].Flags|=LIF_SELECTED;
1406 #else
1408 if ((Type == DI_COMBOBOX || Type == DI_LISTBOX)) {
1409 CurItem->ListPos = CurItem->ListPtr ? CurItem->ListPtr->GetSelectPos() : 0;
1412 #endif
1416 // Функция формирования и запроса цветов.
1417 DWORD Dialog::CtlColorDlgItem(int ItemPos, const DialogItemEx *CurItem, uint64_t *Color)
1419 CriticalSectionLock Lock(CS);
1420 const int Type = CurItem->Type;
1421 const int Focus = CurItem->Focus;
1422 const int Default = CurItem->DefaultButton;
1423 const DWORD Flags = CurItem->Flags;
1425 const bool IsWarning = DialogMode.Check(DMODE_WARNINGSTYLE);
1426 const bool DisabledItem = (Flags & DIF_DISABLE) != 0;
1428 switch (Type) {
1429 case DI_SINGLEBOX:
1430 case DI_DOUBLEBOX: {
1432 // Title
1433 Color[0] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGBOXTITLE) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGBOXTITLE));
1434 // HiText
1435 Color[1] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGHIGHLIGHTBOXTITLE) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGHIGHLIGHTBOXTITLE));
1436 // Box
1437 Color[2] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGBOX) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGBOX));
1438 break;
1441 if (Flags & DIF_SETCOLOR)
1442 Attr = Flags & DIF_COLORMASK;
1443 else {
1444 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1445 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1446 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGBOX);
1449 Attr = MAKELONG(MAKEWORD(FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1450 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOXTITLE)
1451 : (DisabledItem ? COL_DIALOGDISABLED
1452 : COL_DIALOGBOXTITLE)), // Title LOBYTE
1453 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1454 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1455 : COL_WARNDIALOGHIGHLIGHTBOXTITLE)
1456 : (DisabledItem ? COL_DIALOGDISABLED
1457 : COL_DIALOGHIGHLIGHTBOXTITLE))), // HiText HIBYTE
1458 MAKEWORD(FarColorToReal(Attr), // Box LOBYTE
1459 0) // HIBYTE
1461 break;
1464 #if defined(VTEXT_ADN_SEPARATORS)
1465 case DI_VTEXT:
1466 #endif
1467 case DI_TEXT: {
1469 Color[0] = FarColorToReal((Flags & DIF_BOXCOLOR)? (IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGBOX) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGBOX)) : (IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGTEXT) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGTEXT)));
1470 // HiText
1471 Color[1] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGHIGHLIGHTTEXT) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGHIGHLIGHTTEXT));
1472 if (Flags & (DIF_SEPARATORUSER|DIF_SEPARATOR|DIF_SEPARATOR2))
1474 // Box
1475 Color[2] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGBOX) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGBOX));
1477 break;
1480 if (Flags & DIF_SETCOLOR)
1481 Attr = Flags & DIF_COLORMASK;
1482 else {
1483 if (Flags & DIF_BOXCOLOR)
1484 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1485 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1486 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGBOX);
1487 else
1488 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1489 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)
1490 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT);
1493 Attr = MAKELONG(MAKEWORD(FarColorToReal(Attr),
1494 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1495 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGHIGHLIGHTTEXT)
1496 : (DisabledItem ? COL_DIALOGDISABLED
1497 : COL_DIALOGHIGHLIGHTTEXT) // HIBYTE HiText
1499 ((Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2)) ? (
1500 MAKEWORD(FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1501 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1502 : (DisabledItem ? COL_DIALOGDISABLED
1503 : COL_DIALOGBOX) // Box LOBYTE
1506 : 0));
1507 break;
1510 #if 0
1511 #if !defined(VTEXT_ADN_SEPARATORS)
1512 case DI_VTEXT: {
1513 if (Flags & DIF_BOXCOLOR)
1514 Attr = DialogMode.Check(DMODE_WARNINGSTYLE)
1515 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGBOX)
1516 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGBOX);
1517 else if (Flags & DIF_SETCOLOR)
1518 Attr = (Flags & DIF_COLORMASK);
1519 else
1520 Attr = (DialogMode.Check(DMODE_WARNINGSTYLE)
1521 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)
1522 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT));
1524 Attr = MAKEWORD(MAKEWORD(FarColorToReal(Attr), 0), MAKEWORD(0, 0));
1525 break;
1527 #endif
1528 #endif
1529 case DI_CHECKBOX:
1530 case DI_RADIOBUTTON: {
1532 Color[0] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGTEXT) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGTEXT));
1533 // HiText
1534 Color[1] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:COL_WARNDIALOGHIGHLIGHTTEXT) : (DisabledItem?COL_DIALOGDISABLED:COL_DIALOGHIGHLIGHTTEXT));
1535 break;
1537 if (Flags & DIF_SETCOLOR)
1538 Attr = (Flags & DIF_COLORMASK);
1539 else
1540 Attr = (DialogMode.Check(DMODE_WARNINGSTYLE)
1541 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)
1542 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT));
1544 Attr = MAKEWORD(FarColorToReal(Attr),
1545 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1546 ? (DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGHIGHLIGHTTEXT)
1547 : (DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGHIGHLIGHTTEXT))); // HiText
1548 break;
1551 case DI_BUTTON: {
1553 if (Focus)
1555 SetCursorType(0, 10);
1556 // TEXT
1557 Color[0] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:(Default?COL_WARNDIALOGSELECTEDDEFAULTBUTTON:COL_WARNDIALOGSELECTEDBUTTON)) : (DisabledItem?COL_DIALOGDISABLED:(Default?COL_DIALOGSELECTEDDEFAULTBUTTON:COL_DIALOGSELECTEDBUTTON)));
1558 // HiText
1559 Color[1] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:(Default?COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON:COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON)) : (DisabledItem?COL_DIALOGDISABLED:(Default?COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON:COL_DIALOGHIGHLIGHTSELECTEDBUTTON)));
1561 else
1563 // TEXT
1564 Color[0] = FarColorToReal(IsWarning?
1565 (DisabledItem?COL_WARNDIALOGDISABLED:(Default?COL_WARNDIALOGDEFAULTBUTTON:COL_WARNDIALOGBUTTON)):
1566 (DisabledItem?COL_DIALOGDISABLED:(Default?COL_DIALOGDEFAULTBUTTON:COL_DIALOGBUTTON)));
1567 // HiText
1568 Color[1] = FarColorToReal(IsWarning? (DisabledItem?COL_WARNDIALOGDISABLED:(Default?COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON:COL_WARNDIALOGHIGHLIGHTBUTTON)) : (DisabledItem?COL_DIALOGDISABLED:(Default?COL_DIALOGHIGHLIGHTDEFAULTBUTTON:COL_DIALOGHIGHLIGHTBUTTON)));
1570 break;
1573 if (Focus) {
1574 SetCursorType(0, 10);
1575 Attr = MAKEWORD((Flags & DIF_SETCOLOR)
1576 ? (Flags & DIF_COLORMASK)
1577 : FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1578 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1579 : (Default ? COL_WARNDIALOGSELECTEDDEFAULTBUTTON
1580 : COL_WARNDIALOGSELECTEDBUTTON))
1581 : (DisabledItem ? COL_DIALOGDISABLED
1582 : (Default ? COL_DIALOGSELECTEDDEFAULTBUTTON
1583 : COL_DIALOGSELECTEDBUTTON))), // TEXT
1584 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1585 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1586 : (Default ? COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON
1587 : COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON))
1588 : (DisabledItem ? COL_DIALOGDISABLED
1589 : (Default ? COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON
1590 : COL_DIALOGHIGHLIGHTSELECTEDBUTTON)))); // HiText
1591 } else {
1592 Attr = MAKEWORD((Flags & DIF_SETCOLOR)
1593 ? (Flags & DIF_COLORMASK)
1594 : FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1595 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1596 : (Default ? COL_WARNDIALOGDEFAULTBUTTON
1597 : COL_WARNDIALOGBUTTON))
1598 : (DisabledItem ? COL_DIALOGDISABLED
1599 : (Default ? COL_DIALOGDEFAULTBUTTON
1600 : COL_DIALOGBUTTON))), // TEXT
1601 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE)
1602 ? (DisabledItem ? COL_WARNDIALOGDISABLED
1603 : (Default ? COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON
1604 : COL_WARNDIALOGHIGHLIGHTBUTTON))
1605 : (DisabledItem ? COL_DIALOGDISABLED
1606 : (Default ? COL_DIALOGHIGHLIGHTDEFAULTBUTTON
1607 : COL_DIALOGHIGHLIGHTBUTTON)))); // HiText
1610 break;
1613 case DI_EDIT:
1614 case DI_FIXEDIT:
1615 case DI_PSWEDIT:
1616 case DI_COMBOBOX:
1617 case DI_MEMOEDIT: {
1619 if (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST))
1621 if (IsWarning)
1623 // Text
1624 Color[0] = FarColorToReal(DisabledItem? COL_WARNDIALOGEDITDISABLED: Focus? COL_WARNDIALOGEDITSELECTED : COL_WARNDIALOGEDIT);
1625 // Select
1626 Color[1] = FarColorToReal(DisabledItem? COL_WARNDIALOGEDITDISABLED : Focus? COL_WARNDIALOGEDITSELECTED : COL_WARNDIALOGEDIT);
1627 // Unchanged
1628 Color[2] = FarColorToReal(DisabledItem? COL_WARNDIALOGEDITDISABLED : Focus? COL_WARNDIALOGEDITSELECTED : COL_WARNDIALOGEDITUNCHANGED);
1629 // History
1630 Color[3] = FarColorToReal(DisabledItem? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT);
1632 else
1634 // Text
1635 Color[0] = FarColorToReal(DisabledItem? COL_DIALOGEDITDISABLED : Focus? COL_DIALOGEDITSELECTED : COL_DIALOGEDIT);
1636 // Select
1637 Color[1] = FarColorToReal(DisabledItem? COL_DIALOGEDITDISABLED: Focus? COL_DIALOGEDITSELECTED : COL_DIALOGEDIT);
1638 // Unchanged
1639 Color[2] = FarColorToReal(DisabledItem? COL_DIALOGEDITDISABLED : Focus? COL_DIALOGEDITSELECTED : COL_DIALOGEDITUNCHANGED);
1640 // History
1641 Color[3] = FarColorToReal(DisabledItem? COL_DIALOGDISABLED : COL_DIALOGTEXT);
1644 else
1646 if (IsWarning)
1648 // Text
1649 Color[0] = FarColorToReal(DisabledItem? COL_WARNDIALOGEDITDISABLED : Flags & DIF_NOFOCUS? COL_WARNDIALOGEDITUNCHANGED : COL_WARNDIALOGEDIT);
1650 // Select
1651 Color[1] = FarColorToReal(DisabledItem? COL_WARNDIALOGEDITDISABLED : COL_WARNDIALOGEDITSELECTED);
1652 // Unchanged
1653 Color[2] = FarColorToReal(DisabledItem? COL_WARNDIALOGEDITDISABLED : COL_WARNDIALOGEDITUNCHANGED);
1654 // History
1655 Color[3] = FarColorToReal(DisabledItem? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT);
1657 else
1659 // Text
1660 Color[0] = FarColorToReal(DisabledItem? COL_DIALOGEDITDISABLED : Flags & DIF_NOFOCUS? COL_DIALOGEDITUNCHANGED : COL_DIALOGEDIT);
1661 // Select
1662 Color[1] = FarColorToReal(DisabledItem? COL_DIALOGEDITDISABLED : COL_DIALOGEDITSELECTED);
1663 // Unchanged
1664 Color[2] = FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED : COL_DIALOGEDITUNCHANGED);
1665 // History
1666 Color[3] = FarColorToReal(DisabledItem? COL_DIALOGDISABLED : COL_DIALOGTEXT);
1669 break;
1671 if (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST)) {
1672 if (DialogMode.Check(DMODE_WARNINGSTYLE))
1673 Attr = MAKELONG(MAKEWORD( // LOWORD
1674 // LOLO (Text)
1675 FarColorToReal(DisabledItem ? COL_WARNDIALOGEDITDISABLED
1676 : COL_WARNDIALOGEDIT),
1677 // LOHI (Select)
1678 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1679 : COL_DIALOGEDITSELECTED)),
1680 MAKEWORD( // HIWORD
1681 // HILO (Unchanged)
1682 FarColorToReal(DisabledItem ? COL_WARNDIALOGEDITDISABLED
1683 : COL_DIALOGEDITUNCHANGED), //???
1684 // HIHI (History)
1685 FarColorToReal(
1686 DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)));
1687 else
1688 Attr = MAKELONG(MAKEWORD( // LOWORD
1689 // LOLO (Text)
1690 FarColorToReal(DisabledItem
1691 ? COL_DIALOGEDITDISABLED
1692 : (!Focus ? COL_DIALOGEDIT
1693 : COL_DIALOGEDITSELECTED)),
1694 // LOHI (Select)
1695 FarColorToReal(DisabledItem
1696 ? COL_DIALOGEDITDISABLED
1697 : (!Focus ? COL_DIALOGEDIT
1698 : COL_DIALOGEDITSELECTED))),
1699 MAKEWORD( // HIWORD
1700 // HILO (Unchanged)
1701 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1702 : COL_DIALOGEDITUNCHANGED), //???
1703 // HIHI (History)
1704 FarColorToReal(DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT)));
1705 } else {
1706 if (DialogMode.Check(DMODE_WARNINGSTYLE))
1707 Attr = MAKELONG(MAKEWORD( // LOWORD
1708 // LOLO (Text)
1709 FarColorToReal(DisabledItem
1710 ? COL_WARNDIALOGEDITDISABLED
1711 : (Flags & DIF_NOFOCUS ? COL_DIALOGEDITUNCHANGED
1712 : COL_WARNDIALOGEDIT)),
1713 // LOHI (Select)
1714 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1715 : COL_DIALOGEDITSELECTED)),
1716 MAKEWORD( // HIWORD
1717 // HILO (Unchanged)
1718 FarColorToReal(DisabledItem ? COL_WARNDIALOGEDITDISABLED
1719 : COL_DIALOGEDITUNCHANGED), //???
1720 // HIHI (History)
1721 FarColorToReal(
1722 DisabledItem ? COL_WARNDIALOGDISABLED : COL_WARNDIALOGTEXT)));
1723 else
1724 Attr = MAKELONG(MAKEWORD( // LOWORD
1725 // LOLO (Text)
1726 FarColorToReal(DisabledItem
1727 ? COL_DIALOGEDITDISABLED
1728 : (Flags & DIF_NOFOCUS ? COL_DIALOGEDITUNCHANGED
1729 : COL_DIALOGEDIT)),
1730 // LOHI (Select)
1731 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1732 : COL_DIALOGEDITSELECTED)),
1733 MAKEWORD( // HIWORD
1734 // HILO (Unchanged)
1735 FarColorToReal(DisabledItem ? COL_DIALOGEDITDISABLED
1736 : COL_DIALOGEDITUNCHANGED), //???
1737 // HIHI (History)
1738 FarColorToReal(DisabledItem ? COL_DIALOGDISABLED : COL_DIALOGTEXT)));
1741 break;
1744 case DI_LISTBOX: {
1745 Item[ItemPos]->ListPtr->SetColors(nullptr);
1746 return 0;
1748 default: {
1749 return 0;
1753 ++InCtlColorDlgItem;
1754 DWORD out = DlgProc((HANDLE)this, DN_CTLCOLORDLGITEM, ItemPos, (LONG_PTR)Color);
1755 --InCtlColorDlgItem;
1756 return out;
1760 static void SetColorNormal(DWORD Attr, const std::unique_ptr<DialogItemTrueColors> &TrueColors)
1762 ComposeAndSetColor(Attr & 0xff, TrueColors ? &TrueColors->Normal : nullptr);
1765 static void SetColorFrame(DWORD Attr, const std::unique_ptr<DialogItemTrueColors> &TrueColors)
1767 ComposeAndSetColor(LOBYTE(HIWORD(Attr)), TrueColors ? &TrueColors->Frame : nullptr);
1771 //////////////////////////////////////////////////////////////////////////
1773 Private:
1774 Отрисовка элементов диалога на экране.
1776 void Dialog::ShowDialog(unsigned ID)
1778 CriticalSectionLock Lock(CS);
1780 if (Locked())
1781 return;
1783 FARString strStr;
1784 DialogItemEx *CurItem;
1785 int X, Y;
1786 // size_t I, DrawItemCount;
1787 unsigned I, DrawItemCount;
1788 uint64_t ItemColor[4];
1790 // Если не разрешена отрисовка, то вываливаем.
1791 if (IsEnableRedraw || // разрешена прорисовка ?
1792 (ID + 1 > ItemCount) || // а номер в рамках дозволенного?
1793 DialogMode.Check(DMODE_DRAWING) || // диалог рисуется?
1794 !DialogMode.Check(DMODE_SHOW) || // если не видим, то и не отрисовываем.
1795 !DialogMode.Check(DMODE_INITOBJECTS))
1796 return;
1798 DialogMode.Set(DMODE_DRAWING); // диалог рисуется!!!
1799 ChangePriority ChPriority(ChangePriority::NORMAL);
1801 if (ID == (unsigned)-1) // рисуем все?
1803 // Перед прорисовкой диалога посылаем сообщение в обработчик
1804 if (!DlgProc((HANDLE)this, DN_DRAWDIALOG, 0, 0)) {
1805 DialogMode.Clear(DMODE_DRAWING); // конец отрисовки диалога!!!
1806 return;
1809 // перед прорисовкой подложки окна диалога
1810 if (!DialogMode.Check(DMODE_NODRAWSHADOW))
1811 Shadow(DialogMode.Check(DMODE_FULLSHADOW) != FALSE); // "наводим" тень
1813 if (!DialogMode.Check(DMODE_NODRAWPANEL)) {
1815 uint64_t Color[4];
1817 Color[0] = FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE) ? COL_WARNDIALOGTEXT:COL_DIALOGTEXT);
1818 DlgProc((HANDLE)this, DN_CTLCOLORDIALOG, 0, (LONG_PTR)Color);
1819 SetScreen(X1, Y1, X2, Y2, L' ', Color[0]);
1822 ID = 0;
1823 DrawItemCount = ItemCount;
1824 } else {
1825 DrawItemCount = ID + 1;
1829 IFlags.Set(DIMODE_REDRAW)
1830 TODO:
1831 если рисуется контрол и по Z-order`у он пересекается с
1832 другим контролом (по координатам), то для "позднего"
1833 контрола тоже нужна прорисовка.
1836 bool CursorVisible = false;
1837 DWORD CursorSize = 0;
1839 if (ID != (unsigned)-1 && FocusPos != ID) {
1840 if (Item[FocusPos]->Type == DI_USERCONTROL && Item[FocusPos]->UCData->CursorPos.X != -1
1841 && Item[FocusPos]->UCData->CursorPos.Y != -1) {
1842 CursorVisible = Item[FocusPos]->UCData->CursorVisible;
1843 CursorSize = Item[FocusPos]->UCData->CursorSize;
1847 SetCursorType(CursorVisible, CursorSize);
1850 for (I = ID; I < DrawItemCount; I++) {
1851 CurItem = Item[I];
1853 if (CurItem->Flags & DIF_HIDDEN)
1854 continue;
1857 $ 28.07.2000 SVS
1858 Перед прорисовкой каждого элемента посылаем сообщение
1859 посредством функции SendDlgMessage - в ней делается все!
1861 if (!SendDlgMessage((HANDLE)this, DN_DRAWDLGITEM, I, 0))
1862 continue;
1864 int LenText;
1865 short CX1 = CurItem->X1;
1866 short CY1 = CurItem->Y1;
1867 short CX2 = CurItem->X2;
1868 short CY2 = CurItem->Y2;
1870 if (CX2 > X2 - X1)
1871 CX2 = X2 - X1;
1873 if (CY2 > Y2 - Y1)
1874 CY2 = Y2 - Y1;
1876 short CW = CX2 - CX1 + 1;
1877 short CH = CY2 - CY1 + 1;
1879 CtlColorDlgItem(I, CurItem, ItemColor);
1881 for (size_t g = 0; g < 4; g++)
1882 if (CurItem->customItemColor[g])
1883 ItemColor[g] = CurItem->customItemColor[g];
1885 #if 0
1887 // TODO: прежде чем эту строку применять... нужно проверить _ВСЕ_ диалоги на предмет X2, Y2. !!!
1888 if (((CX1 > -1) && (CX2 > 0) && (CX2 > CX1)) &&
1889 ((CY1 > -1) && (CY2 > 0) && (CY2 > CY1)))
1890 SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1892 #endif
1894 switch (CurItem->Type) {
1895 /* ***************************************************************** */
1896 case DI_SINGLEBOX:
1897 case DI_DOUBLEBOX: {
1898 BOOL IsDrawTitle = TRUE;
1899 GotoXY(X1 + CX1, Y1 + CY1);
1900 // SetColorFrame(Attr, CurItem->TrueColors);
1901 SetColor(ItemColor[2]);
1903 if (CY1 == CY2) {
1904 DrawLine(CX2 - CX1 + 1, CurItem->Type == DI_SINGLEBOX ? 8 : 9); //???
1905 } else if (CX1 == CX2) {
1906 DrawLine(CY2 - CY1 + 1, CurItem->Type == DI_SINGLEBOX ? 10 : 11);
1907 IsDrawTitle = FALSE;
1908 } else {
1909 Box(X1 + CX1, Y1 + CY1, X1 + CX2, Y1 + CY2, ItemColor[2],
1910 (CurItem->Type == DI_SINGLEBOX) ? SINGLE_BOX : DOUBLE_BOX);
1913 if (!CurItem->strData.IsEmpty() && IsDrawTitle) {
1914 // ! Пусть диалог сам заботится о ширине собственного заголовка.
1915 strStr = CurItem->strData;
1916 TruncStrFromEnd(strStr, CW - 2); // 5 ???
1917 LenText = LenStrItem(I, strStr);
1919 if (LenText < CW - 2 && !strStr.Begins(L' ') ) {
1920 strStr.Insert(0, L' ');
1921 LenText = LenStrItem(I, strStr);
1924 if (LenText < CW - 2 && !strStr.Ends(L' ') ) { // пробел после текста заголовка и рамкой
1925 strStr.Append(L' ');
1926 LenText = LenStrItem(I, strStr);
1929 X = X1 + CX1 + (CW - LenText) / 2;
1931 if ((CurItem->Flags & DIF_LEFTTEXT) && X1 + CX1 + 1 < X)
1932 X = X1 + CX1 + 1;
1934 // SetColorNormal(Attr, CurItem->TrueColors);
1935 SetColor(ItemColor[0]);
1936 GotoXY(X, Y1 + CY1);
1938 if (CurItem->Flags & DIF_SHOWAMPERSAND)
1939 Text(strStr);
1940 else
1941 HiText(strStr, ItemColor[1]);
1944 if (CurItem->Flags & DIF_SHOWAMPERSAND)
1945 Text(strStr);
1946 else if (CurItem->TrueColors)
1947 HiText(strStr, ComposeColor(ItemColor[1] & 0xFF, &CurItem->TrueColors->Hilighted));
1948 else
1949 HiText(strStr, ItemColor[1]);
1954 break;
1956 /* ***************************************************************** */
1957 case DI_TEXT: {
1958 strStr = CurItem->strData;
1959 LenText = LenStrItem(I, strStr);
1961 if (!(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))
1962 && (CurItem->Flags & DIF_CENTERTEXT) && CX1 != -1)
1963 LenText = LenStrItem(I, CenterStr(strStr, strStr, CX2 - CX1 + 1));
1965 X = (CX1 == -1 || (CurItem->Flags & (DIF_SEPARATOR | DIF_SEPARATOR2)))
1966 ? (X2 - X1 + 1 - LenText) / 2
1967 : CX1;
1968 Y = (CY1 == -1) ? (Y2 - Y1 + 1) / 2 : CY1;
1970 if (X < 0)
1971 X = 0;
1973 if ((CX2 <= 0) || (CX2 < CX1))
1974 CW = LenText;
1976 if (X1 + X + LenText > X2) {
1977 int tmpCW = ObjWidth;
1979 if (CW < ObjWidth)
1980 tmpCW = CW + 1;
1982 strStr.TruncateByCells(tmpCW - 1);
1985 // нужно ЭТО
1986 // SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1987 // вместо этого:
1988 if (CX1 > -1 && CX2 > CX1
1989 && !(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))) { // половинчатое решение
1991 int CntChr = CX2 - CX1 + 1;
1992 // SetColorNormal(Attr, CurItem->TrueColors);
1993 SetColor(ItemColor[0]);
1994 GotoXY(X1 + X, Y1 + Y);
1996 if (X1 + X + CntChr - 1 > X2)
1997 CntChr = X2 - (X1 + X) + 1;
1999 FS << fmt::Cells() << fmt::Expand(CntChr) << L"";
2001 if (CntChr < LenText)
2002 strStr.TruncateByCells(CntChr);
2005 /// if (CX1 > -1 && CX2 > CX1 && !(Item.Flags & (DIF_SEPARATORUSER|DIF_SEPARATOR|DIF_SEPARATOR2))) //половинчатое решение
2006 /// {
2007 /// SetScreen({ m_Where.left + CX1, m_Where.top + Y, m_Where.left + CX2, m_Where.top + Y }, L' ', ItemColor[0]);
2009 int CntChr=CX2-CX1+1;
2010 SetColor(ItemColor[0]);
2011 GotoXY(X1+X,Y1+Y);
2013 if (X1+X+CntChr-1 > X2)
2014 CntChr=X2-(X1+X)+1;
2016 Text(string(CntChr, L' '));
2018 if (CntChr < LenText)
2019 strStr.SetLength(CntChr);
2021 /// }
2023 if (CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2)) {
2024 // SetColorFrame(Attr, CurItem->TrueColors);
2025 SetColor(ItemColor[2]);
2026 GotoXY(X1
2027 + ((CurItem->Flags & DIF_SEPARATORUSER)
2029 : (!DialogMode.Check(DMODE_SMALLDIALOG) ? 3 : 0)),
2030 Y1 + Y); //????
2031 ShowUserSeparator((CurItem->Flags & DIF_SEPARATORUSER)
2032 ? X2 - X1 + 1
2033 : RealWidth - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 6 : 0 /* -1 */),
2034 (CurItem->Flags & DIF_SEPARATORUSER)
2035 ? 12
2036 : (CurItem->Flags & DIF_SEPARATOR2 ? 3 : 1),
2037 CurItem->strMask);
2040 // SetColorNormal(Attr, CurItem->TrueColors);
2041 SetColor(ItemColor[0]);
2042 GotoXY(X1 + X, Y1 + Y);
2044 if (CurItem->Flags & DIF_SHOWAMPERSAND) {
2045 // MessageBox(0, strStr, strStr, MB_OK);
2046 Text(strStr);
2047 } else {
2048 // MessageBox(0, strStr, strStr, MB_OK);
2049 HiText(strStr, ItemColor[1]);
2052 break;
2054 /* ***************************************************************** */
2055 case DI_VTEXT: {
2056 strStr = CurItem->strData;
2057 LenText = LenStrItem(I, strStr);
2059 if (!(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))
2060 && (CurItem->Flags & DIF_CENTERTEXT) && CY1 != -1)
2061 LenText = StrLength(CenterStr(strStr, strStr, CY2 - CY1 + 1));
2063 X = (CX1 == -1) ? (X2 - X1 + 1) / 2 : CX1;
2064 Y = (CY1 == -1 || (CurItem->Flags & (DIF_SEPARATOR | DIF_SEPARATOR2)))
2065 ? (Y2 - Y1 + 1 - LenText) / 2
2066 : CY1;
2068 if (Y < 0)
2069 Y = 0;
2071 if ((CY2 <= 0) || (CY2 < CY1))
2072 CH = LenStrItem(I, strStr);
2074 if (Y1 + Y + LenText > Y2) {
2075 int tmpCH = ObjHeight;
2077 if (CH < ObjHeight)
2078 tmpCH = CH + 1;
2080 strStr.TruncateByCells(tmpCH - 1);
2083 // нужно ЭТО
2084 // SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
2085 // вместо этого:
2086 if (CY1 > -1 && CY2 > 0 && CY2 > CY1
2087 && !(CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2))) { // половинчатое решение
2089 int CntChr = CY2 - CY1 + 1;
2090 SetColor(ItemColor[0]);
2091 // SetColorNormal(Attr, CurItem->TrueColors);
2092 GotoXY(X1 + X, Y1 + Y);
2094 if (Y1 + Y + CntChr - 1 > Y2)
2095 CntChr = Y2 - (Y1 + Y) + 1;
2097 vmprintf(L"%*ls", CntChr, L"");
2100 // нужно ЭТО
2101 //SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
2102 // вместо этого:
2103 /// if (CY1 > -1 && CY2 > CY1 && !(Item.Flags & (DIF_SEPARATORUSER|DIF_SEPARATOR|DIF_SEPARATOR2))) //половинчатое решение
2104 /// {
2105 /// SetScreen({ m_Where.left + X, m_Where.top + CY1, m_Where.left + X, m_Where.top + CY2 }, L' ', ItemColor[0]);
2107 int CntChr=CY2-CY1+1;
2108 SetColor(ItemColor[0]);
2109 GotoXY(X1+X,Y1+Y);
2111 if (Y1+Y+CntChr-1 > Y2)
2112 CntChr=Y2-(Y1+Y)+1;
2114 vmprintf(L"%*s",CntChr,L"");
2116 /// }
2121 #if defined(VTEXT_ADN_SEPARATORS)
2123 if (CurItem->Flags & (DIF_SEPARATORUSER | DIF_SEPARATOR | DIF_SEPARATOR2)) {
2124 // SetColorFrame(Attr, CurItem->TrueColors);
2125 SetColor(ItemColor[2]);
2126 GotoXY(X1 + X,
2128 + ((CurItem->Flags & DIF_SEPARATORUSER)
2130 : (!DialogMode.Check(DMODE_SMALLDIALOG) ? 1 : 0))); //????
2131 ShowUserSeparator((CurItem->Flags & DIF_SEPARATORUSER)
2132 ? Y2 - Y1 + 1
2133 : RealHeight - (!DialogMode.Check(DMODE_SMALLDIALOG) ? 2 : 0),
2134 (CurItem->Flags & DIF_SEPARATORUSER)
2135 ? 13
2136 : (CurItem->Flags & DIF_SEPARATOR2 ? 7 : 5),
2137 CurItem->strMask);
2140 #endif
2141 SetColor(ItemColor[0]);
2142 // SetColorNormal(Attr, CurItem->TrueColors);
2143 GotoXY(X1 + X, Y1 + Y);
2145 if (CurItem->Flags & DIF_SHOWAMPERSAND)
2146 VText(strStr);
2147 else
2148 HiText(strStr, ItemColor[1], TRUE);
2150 break;
2152 /* ***************************************************************** */
2153 case DI_CHECKBOX:
2154 case DI_RADIOBUTTON: {
2155 // SetColorNormal(Attr, CurItem->TrueColors);
2156 SetColor(ItemColor[0]);
2157 GotoXY(X1 + CX1, Y1 + CY1);
2159 if (CurItem->Type == DI_CHECKBOX) {
2160 const wchar_t Check[] = {L'[',
2161 (CurItem->Selected ? (((CurItem->Flags & DIF_3STATE) && CurItem->Selected == 2)
2162 ? *Msg::CheckBox2State
2163 : L'x')
2164 : L' '),
2165 L']', L'\0'};
2166 strStr = Check;
2168 if (CurItem->strData.GetLength())
2169 strStr+= L" ";
2170 } else {
2171 wchar_t Dot[] = {L' ', CurItem->Selected ? L'\x2022' : L' ', L' ', L'\0'};
2173 if (CurItem->Flags & DIF_MOVESELECT) {
2174 strStr = Dot;
2175 } else {
2176 Dot[0] = L'(';
2177 Dot[2] = L')';
2178 strStr = Dot;
2180 if (CurItem->strData.GetLength())
2181 strStr+= L" ";
2185 strStr+= CurItem->strData;
2186 LenText = LenStrItem(I, strStr);
2188 if (X1 + CX1 + LenText > X2)
2189 strStr.TruncateByCells(ObjWidth - 1);
2191 if (CurItem->Flags & DIF_SHOWAMPERSAND)
2192 Text(strStr);
2193 else
2194 HiText(strStr, ItemColor[1]);
2196 if (CurItem->Focus) {
2197 // Отключение мигающего курсора при перемещении диалога
2198 if (!DialogMode.Check(DMODE_DRAGGED))
2199 SetCursorType(1, -1);
2201 MoveCursor(X1 + CX1 + 1, Y1 + CY1);
2204 break;
2206 /* ***************************************************************** */
2207 case DI_BUTTON: {
2208 strStr = CurItem->strData;
2209 SetColor(ItemColor[0]);
2210 // SetColorNormal(Attr, CurItem->TrueColors);
2211 GotoXY(X1 + CX1, Y1 + CY1);
2213 if (CurItem->Flags & DIF_SHOWAMPERSAND)
2214 Text(strStr);
2215 else
2216 HiText(strStr,ItemColor[1]);
2217 // HiText(strStr, HIBYTE(LOWORD(Attr)));
2219 if (CurItem->Flags & DIF_SETSHIELD) {
2220 int startx = X1 + CX1 + (CurItem->Flags & DIF_NOBRACKETS ? 0 : 2);
2221 ScrBuf.ApplyColor(startx, Y1 + CY1, startx + 1, Y1 + CY1, 0xE9);
2223 break;
2225 /* ***************************************************************** */
2226 case DI_EDIT:
2227 case DI_FIXEDIT:
2228 case DI_PSWEDIT:
2229 case DI_COMBOBOX:
2230 case DI_MEMOEDIT: {
2231 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
2233 if (!EditPtr)
2234 break;
2236 // EditPtr->SetObjectColor(Attr & 0xFF, HIBYTE(LOWORD(Attr)), LOBYTE(HIWORD(Attr)));
2237 EditPtr->SetObjectColor(ItemColor[0],ItemColor[1],ItemColor[2]);
2239 if (CurItem->Focus) {
2240 // Отключение мигающего курсора при перемещении диалога
2241 if (!DialogMode.Check(DMODE_DRAGGED))
2242 SetCursorType(1, -1);
2244 EditPtr->Show();
2245 } else {
2246 EditPtr->FastShow();
2247 EditPtr->SetLeftPos(0);
2250 // Отключение мигающего курсора при перемещении диалога
2251 if (DialogMode.Check(DMODE_DRAGGED))
2252 SetCursorType(0, 0);
2254 if (ItemHasDropDownArrow(CurItem)) {
2255 int EditX1, EditY1, EditX2, EditY2;
2256 EditPtr->GetPosition(EditX1, EditY1, EditX2, EditY2);
2257 // Text((CurItem->Type == DI_COMBOBOX?"\x1F":"\x19"));
2258 Text(EditX2 + 1, EditY1, ItemColor[3], L"\x2193");
2261 if (CurItem->Type == DI_COMBOBOX && GetDropDownOpened() && CurItem->ListPtr->IsVisible()) // need redraw VMenu?
2263 CurItem->ListPtr->Hide();
2264 CurItem->ListPtr->Show();
2267 break;
2269 /* ***************************************************************** */
2270 case DI_LISTBOX: {
2271 if (CurItem->ListPtr) {
2272 // Перед отрисовкой спросим об изменении цветовых атрибутов
2273 uint64_t RealColors[VMENU_COLOR_COUNT];
2274 FarListColors ListColors = {0};
2275 ListColors.ColorCount = VMENU_COLOR_COUNT;
2276 ListColors.Colors = RealColors;
2277 CurItem->ListPtr->GetColors(&ListColors);
2279 if (DlgProc((HANDLE)this, DN_CTLCOLORDLGLIST, I, (LONG_PTR)&ListColors))
2280 CurItem->ListPtr->SetColors(&ListColors);
2282 // Курсор запоминаем...
2283 bool CursorVisible = false;
2284 DWORD CursorSize = 0;
2285 GetCursorType(CursorVisible, CursorSize);
2286 CurItem->ListPtr->Show();
2288 // .. а теперь восстановим!
2289 if (FocusPos != I)
2290 SetCursorType(CursorVisible, CursorSize);
2293 break;
2295 /* 01.08.2000 SVS $ */
2296 /* ***************************************************************** */
2297 case DI_USERCONTROL:
2299 if (CurItem->VBuf) {
2300 PutText(X1 + CX1, Y1 + CY1, X1 + CX2, Y1 + CY2, CurItem->VBuf);
2302 // не забудем переместить курсор, если он позиционирован.
2303 if (FocusPos == I) {
2304 if (CurItem->UCData->CursorPos.X != -1 && CurItem->UCData->CursorPos.Y != -1) {
2305 MoveCursor(CurItem->UCData->CursorPos.X + CX1 + X1,
2306 CurItem->UCData->CursorPos.Y + CY1 + Y1);
2307 SetCursorType(CurItem->UCData->CursorVisible, CurItem->UCData->CursorSize);
2308 } else
2309 SetCursorType(0, -1);
2313 break; // уже наприсовали :-)))
2314 /* ***************************************************************** */
2315 //.........
2316 } // end switch(...
2317 } // end for (I=...
2319 // КОСТЫЛЬ!
2320 // но работает ;-)
2321 for (I = 0; I < ItemCount; I++) {
2322 CurItem = Item[I];
2324 if (CurItem->ListPtr && GetDropDownOpened() && CurItem->ListPtr->IsVisible()) {
2325 if ((CurItem->Type == DI_COMBOBOX)
2326 || ((CurItem->Type == DI_EDIT || CurItem->Type == DI_FIXEDIT)
2327 && !(CurItem->Flags & DIF_HIDDEN) && (CurItem->Flags & DIF_HISTORY))) {
2328 CurItem->ListPtr->Show();
2333 // Включим индикатор перемещения...
2334 if (!DialogMode.Check(DMODE_DRAGGED)) // если диалог таскается
2337 $ 03.06.2001 KM
2338 + При каждой перерисовке диалога, кроме режима перемещения, устанавливаем
2339 заголовок консоли, в противном случае он не всегда восстанавливался.
2341 if (!DialogMode.Check(DMODE_KEEPCONSOLETITLE))
2342 ConsoleTitle::SetFarTitle(GetDialogTitle());
2345 DialogMode.Clear(DMODE_DRAWING); // конец отрисовки диалога!!!
2346 DialogMode.Set(DMODE_SHOW); // диалог на экране!
2348 if (DialogMode.Check(DMODE_DRAGGED)) {
2350 - BugZ#813 - DM_RESIZEDIALOG в DN_DRAWDIALOG -> проблема: Ctrl-F5 - отрисовка только полозьев.
2351 Убираем вызов плагиновго обработчика.
2353 // DlgProc((HANDLE)this,DN_DRAWDIALOGDONE,1,0);
2354 DefDlgProc((HANDLE)this, DN_DRAWDIALOGDONE, 1, 0);
2355 } else
2356 DlgProc((HANDLE)this, DN_DRAWDIALOGDONE, 0, 0);
2359 int Dialog::LenStrItem(int ID, const wchar_t *lpwszStr)
2361 CriticalSectionLock Lock(CS);
2363 if (!lpwszStr)
2364 lpwszStr = Item[ID]->strData;
2366 return (Item[ID]->Flags & DIF_SHOWAMPERSAND) ? StrZCellsCount(lpwszStr) : HiStrCellsCount(lpwszStr);
2369 int Dialog::ProcessMoveDialog(DWORD Key)
2371 CriticalSectionLock Lock(CS);
2373 if (DialogMode.Check(DMODE_DRAGGED)) // если диалог таскается
2376 TODO: Здесь проверить "уже здесь" и не делать лишних движений
2377 Т.е., если нажали End, то при следующем End ненужно ничего делать! - сравнить координаты !!!
2379 int rr = 1;
2381 // При перемещении диалога повторяем поведение "бормандовых" сред.
2382 switch (Key) {
2383 case KEY_CTRLLEFT:
2384 case KEY_CTRLNUMPAD4:
2385 case KEY_CTRLHOME:
2386 case KEY_CTRLNUMPAD7:
2387 case KEY_HOME:
2388 case KEY_NUMPAD7:
2389 rr = Key == KEY_CTRLLEFT || Key == KEY_CTRLNUMPAD4 ? 10 : X1;
2390 case KEY_LEFT:
2391 case KEY_NUMPAD4:
2392 Hide();
2394 for (int i = 0; i < rr; i++)
2395 if (X2 > 0) {
2396 X1--;
2397 X2--;
2398 AdjustEditPos(-1, 0);
2401 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2402 Show();
2404 break;
2405 case KEY_CTRLRIGHT:
2406 case KEY_CTRLNUMPAD6:
2407 case KEY_CTRLEND:
2408 case KEY_CTRLNUMPAD1:
2409 case KEY_END:
2410 case KEY_NUMPAD1:
2411 rr = Key == KEY_CTRLRIGHT || Key == KEY_CTRLNUMPAD6 ? 10 : Max(0, ScrX - X2);
2412 case KEY_RIGHT:
2413 case KEY_NUMPAD6:
2414 Hide();
2416 for (int i = 0; i < rr; i++)
2417 if (X1 < ScrX) {
2418 X1++;
2419 X2++;
2420 AdjustEditPos(1, 0);
2423 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2424 Show();
2426 break;
2427 case KEY_PGUP:
2428 case KEY_NUMPAD9:
2429 case KEY_CTRLPGUP:
2430 case KEY_CTRLNUMPAD9:
2431 case KEY_CTRLUP:
2432 case KEY_CTRLNUMPAD8:
2433 rr = Key == KEY_CTRLUP || Key == KEY_CTRLNUMPAD8 ? 5 : Y1;
2434 case KEY_UP:
2435 case KEY_NUMPAD8:
2436 Hide();
2438 for (int i = 0; i < rr; i++)
2439 if (Y2 > 0) {
2440 Y1--;
2441 Y2--;
2442 AdjustEditPos(0, -1);
2445 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2446 Show();
2448 break;
2449 case KEY_CTRLDOWN:
2450 case KEY_CTRLNUMPAD2:
2451 case KEY_CTRLPGDN:
2452 case KEY_CTRLNUMPAD3:
2453 case KEY_PGDN:
2454 case KEY_NUMPAD3:
2455 rr = Key == KEY_CTRLDOWN || Key == KEY_CTRLNUMPAD2 ? 5 : Max(0, ScrY - Y2);
2456 case KEY_DOWN:
2457 case KEY_NUMPAD2:
2458 Hide();
2460 for (int i = 0; i < rr; i++)
2461 if (Y1 < ScrY) {
2462 Y1++;
2463 Y2++;
2464 AdjustEditPos(0, 1);
2467 if (!DialogMode.Check(DMODE_ALTDRAGGED))
2468 Show();
2470 break;
2471 case KEY_NUMENTER:
2472 case KEY_ENTER:
2473 case KEY_CTRLF5:
2474 DialogMode.Clear(DMODE_DRAGGED); // закончим движение!
2476 if (!DialogMode.Check(DMODE_ALTDRAGGED)) {
2477 DlgProc((HANDLE)this, DN_DRAGGED, 1, 0);
2478 Show();
2481 break;
2482 case KEY_ESC:
2483 Hide();
2484 AdjustEditPos(OldX1 - X1, OldY1 - Y1);
2485 X1 = OldX1;
2486 X2 = OldX2;
2487 Y1 = OldY1;
2488 Y2 = OldY2;
2489 DialogMode.Clear(DMODE_DRAGGED);
2491 if (!DialogMode.Check(DMODE_ALTDRAGGED)) {
2492 DlgProc((HANDLE)this, DN_DRAGGED, 1, TRUE);
2493 Show();
2496 break;
2499 if (DialogMode.Check(DMODE_ALTDRAGGED)) {
2500 DialogMode.Clear(DMODE_DRAGGED | DMODE_ALTDRAGGED);
2501 DlgProc((HANDLE)this, DN_DRAGGED, 1, 0);
2502 Show();
2505 return (TRUE);
2508 if (Key == KEY_CTRLF5 && DialogMode.Check(DMODE_ISCANMOVE)) {
2509 if (DlgProc((HANDLE)this, DN_DRAGGED, 0, 0)) // если разрешили перемещать!
2511 // включаем флаг и запоминаем координаты
2512 DialogMode.Set(DMODE_DRAGGED);
2513 OldX1 = X1;
2514 OldX2 = X2;
2515 OldY1 = Y1;
2516 OldY2 = Y2;
2517 // # GetText(0,0,3,0,LV);
2518 Show();
2521 return (TRUE);
2524 return (FALSE);
2527 int64_t Dialog::VMProcess(MacroOpcode OpCode, void *vParam, int64_t iParam)
2529 switch (OpCode) {
2530 case MCODE_F_MENU_CHECKHOTKEY:
2531 case MCODE_F_MENU_GETHOTKEY:
2532 case MCODE_F_MENU_SELECT:
2533 case MCODE_F_MENU_GETVALUE:
2534 case MCODE_F_MENU_ITEMSTATUS:
2535 case MCODE_V_MENU_VALUE: {
2536 const wchar_t *str = (const wchar_t *)vParam;
2538 if (GetDropDownOpened() || Item[FocusPos]->Type == DI_LISTBOX) {
2539 if (Item[FocusPos]->ListPtr)
2540 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2541 } else if (OpCode == MCODE_F_MENU_CHECKHOTKEY)
2542 return (int64_t)(CheckHighlights(*str, (int)iParam) + 1);
2544 return 0;
2548 switch (OpCode) {
2549 case MCODE_C_EOF:
2550 case MCODE_C_BOF:
2551 case MCODE_C_SELECTED:
2552 case MCODE_C_EMPTY: {
2553 if (FarIsEdit(Item[FocusPos]->Type)) {
2554 if (Item[FocusPos]->Type == DI_COMBOBOX && GetDropDownOpened())
2555 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2556 else
2557 return ((DlgEdit *)(Item[FocusPos]->ObjPtr))->VMProcess(OpCode, vParam, iParam);
2558 } else if (Item[FocusPos]->Type == DI_LISTBOX && OpCode != MCODE_C_SELECTED)
2559 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2561 return 0;
2563 case MCODE_V_DLGITEMTYPE: {
2564 switch (Item[FocusPos]->Type) {
2565 case DI_BUTTON:
2566 return 7; // Кнопка (Push Button).
2567 case DI_CHECKBOX:
2568 return 8; // Контрольный переключатель (Check Box).
2569 case DI_COMBOBOX:
2570 return (DropDownOpened ? 0x800A : 10); // Комбинированный список.
2571 case DI_DOUBLEBOX:
2572 return 3; // Двойная рамка.
2573 case DI_EDIT:
2574 return DropDownOpened ? 0x8004 : 4; // Поле ввода.
2575 case DI_FIXEDIT:
2576 return 6; // Поле ввода фиксированного размера.
2577 case DI_LISTBOX:
2578 return 11; // Окно списка.
2579 case DI_PSWEDIT:
2580 return 5; // Поле ввода пароля.
2581 case DI_RADIOBUTTON:
2582 return 9; // Селекторная кнопка (Radio Button).
2583 case DI_SINGLEBOX:
2584 return 2; // Одиночная рамка.
2585 case DI_TEXT:
2586 return 0; // Текстовая строка.
2587 case DI_USERCONTROL:
2588 return 255; // Элемент управления, определяемый программистом.
2589 case DI_VTEXT:
2590 return 1; // Вертикальная текстовая строка.
2593 return -1;
2595 case MCODE_V_DLGITEMCOUNT: // Dlg.ItemCount
2597 return ItemCount;
2599 case MCODE_V_DLGCURPOS: // Dlg.CurPos
2601 return FocusPos + 1;
2603 case MCODE_V_DLGINFOID: // Dlg.Info.Id
2605 static FARString strId;
2606 strId.Format(L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", Id.Data1, Id.Data2, Id.Data3,
2607 Id.Data4[0], Id.Data4[1], Id.Data4[2], Id.Data4[3], Id.Data4[4], Id.Data4[5], Id.Data4[6],
2608 Id.Data4[7]);
2609 return reinterpret_cast<INT64>(strId.CPtr());
2611 case MCODE_V_ITEMCOUNT:
2612 case MCODE_V_CURPOS: {
2613 switch (Item[FocusPos]->Type) {
2614 case DI_COMBOBOX:
2616 if (DropDownOpened || (Item[FocusPos]->Flags & DIF_DROPDOWNLIST))
2617 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2619 case DI_EDIT:
2620 case DI_PSWEDIT:
2621 case DI_FIXEDIT:
2622 return ((DlgEdit *)(Item[FocusPos]->ObjPtr))->VMProcess(OpCode, vParam, iParam);
2623 case DI_LISTBOX:
2624 return Item[FocusPos]->ListPtr->VMProcess(OpCode, vParam, iParam);
2625 case DI_USERCONTROL:
2627 if (OpCode == MCODE_V_CURPOS)
2628 return Item[FocusPos]->UCData->CursorPos.X;
2630 case DI_BUTTON:
2631 case DI_CHECKBOX:
2632 case DI_RADIOBUTTON:
2633 return 0;
2636 return 0;
2638 case MCODE_F_EDITOR_SEL: {
2639 if (FarIsEdit(Item[FocusPos]->Type)
2640 || (Item[FocusPos]->Type == DI_COMBOBOX
2641 && !(DropDownOpened || (Item[FocusPos]->Flags & DIF_DROPDOWNLIST)))) {
2642 return ((DlgEdit *)(Item[FocusPos]->ObjPtr))->VMProcess(OpCode, vParam, iParam);
2645 return 0;
2649 return 0;
2652 //////////////////////////////////////////////////////////////////////////
2654 Public, Virtual:
2655 Обработка данных от клавиатуры.
2656 Перекрывает BaseInput::ProcessKey.
2658 int Dialog::ProcessKey(FarKey Key)
2660 CriticalSectionLock Lock(CS);
2661 _DIALOG(CleverSysLog CL(L"Dialog::ProcessKey"));
2662 _DIALOG(SysLog(L"Param: Key=%ls", _FARKEY_ToName(Key)));
2663 unsigned I;
2664 FARString strStr;
2666 if (Key == KEY_NONE || Key == KEY_IDLE) {
2667 DlgProc((HANDLE)this, DN_ENTERIDLE, 0, 0); // $ 28.07.2000 SVS Передадим этот факт в обработчик :-)
2668 return FALSE;
2671 if (Key == KEY_KILLFOCUS || Key == KEY_GOTFOCUS) {
2672 DlgProc((HANDLE)this, DN_ACTIVATEAPP, Key == KEY_KILLFOCUS ? FALSE : TRUE, 0);
2673 return FALSE;
2676 if (ProcessMoveDialog(Key))
2677 return TRUE;
2679 // BugZ#488 - Shift=enter
2680 if (ShiftPressed && (Key == KEY_ENTER || Key == KEY_NUMENTER) && !CtrlObject->Macro.IsExecuting()
2681 && Item[FocusPos]->Type != DI_BUTTON) {
2682 Key = Key == KEY_ENTER ? KEY_SHIFTENTER : KEY_SHIFTNUMENTER;
2685 if (!(
2686 /*(Key>=KEY_MACRO_BASE && Key <=KEY_MACRO_ENDBASE) ||*/
2687 ((unsigned int)Key >= KEY_OP_BASE && (unsigned int)Key <= KEY_OP_ENDBASE))
2688 && !DialogMode.Check(DMODE_KEY))
2689 if (DlgProc((HANDLE)this, DN_KEY, FocusPos, Key))
2690 return TRUE;
2692 if (!DialogMode.Check(DMODE_SHOW))
2693 return TRUE;
2695 // А ХЗ, может в этот момент изменилось состояние элемента!
2696 if (Item[FocusPos]->Flags & DIF_HIDDEN)
2697 return TRUE;
2699 // небольшая оптимизация
2700 if (Item[FocusPos]->Type == DI_CHECKBOX) {
2701 if (!(Item[FocusPos]->Flags & DIF_3STATE)) {
2702 if (Key == KEY_MULTIPLY) // в CheckBox 2-state Gray* не работает!
2703 Key = KEY_NONE;
2705 if ((Key == KEY_ADD && !Item[FocusPos]->Selected)
2706 || (Key == KEY_SUBTRACT && Item[FocusPos]->Selected))
2707 Key = KEY_SPACE;
2710 // блок else не нужен, т.к. ниже клавиши будут обработаны...
2711 } else if (Key == KEY_ADD)
2712 Key = '+';
2713 else if (Key == KEY_SUBTRACT)
2714 Key = '-';
2715 else if (Key == KEY_MULTIPLY)
2716 Key = '*';
2718 if (Item[FocusPos]->Type == DI_BUTTON && Key == KEY_SPACE)
2719 Key = KEY_ENTER;
2721 if (Item[FocusPos]->Type == DI_LISTBOX) {
2722 switch (Key) {
2723 case KEY_HOME:
2724 case KEY_NUMPAD7:
2725 case KEY_LEFT:
2726 case KEY_NUMPAD4:
2727 case KEY_END:
2728 case KEY_NUMPAD1:
2729 case KEY_RIGHT:
2730 case KEY_NUMPAD6:
2731 case KEY_UP:
2732 case KEY_NUMPAD8:
2733 case KEY_DOWN:
2734 case KEY_NUMPAD2:
2735 case KEY_PGUP:
2736 case KEY_NUMPAD9:
2737 case KEY_PGDN:
2738 case KEY_NUMPAD3:
2739 case KEY_MSWHEEL_UP:
2740 case KEY_MSWHEEL_DOWN:
2741 case KEY_MSWHEEL_LEFT:
2742 case KEY_MSWHEEL_RIGHT:
2743 case KEY_NUMENTER:
2744 case KEY_ENTER:
2745 VMenu *List = Item[FocusPos]->ListPtr;
2746 int CurListPos = List->GetSelectPos();
2747 auto CheckedListItem = List->GetCheck(-1);
2748 List->ProcessKey(Key);
2749 int NewListPos = List->GetSelectPos();
2751 if (NewListPos != CurListPos && !DlgProc((HANDLE)this, DN_LISTCHANGE, FocusPos, NewListPos)) {
2752 if (!DialogMode.Check(DMODE_SHOW))
2753 return TRUE;
2755 List->SetCheck(CheckedListItem, CurListPos);
2757 if (DialogMode.Check(DMODE_SHOW) && !(Item[FocusPos]->Flags & DIF_HIDDEN))
2758 ShowDialog(FocusPos); // FocusPos
2761 if (!(Key == KEY_ENTER || Key == KEY_NUMENTER) || (Item[FocusPos]->Flags & DIF_LISTNOCLOSE))
2762 return TRUE;
2766 switch (Key) {
2767 case KEY_F1:
2770 Перед выводом диалога посылаем сообщение в обработчик
2771 и если вернули что надо, то выводим подсказку
2773 if (!Help::MkTopic(PluginNumber,
2774 (const wchar_t *)DlgProc((HANDLE)this, DN_HELP, FocusPos,
2775 (HelpTopic ? (LONG_PTR)HelpTopic : 0)),
2776 strStr)
2777 .IsEmpty()) {
2778 Help::Present(strStr);
2781 return TRUE;
2782 case KEY_ESC:
2783 case KEY_BREAK:
2784 case KEY_F10:
2785 ExitCode = (Key == KEY_BREAK) ? -2 : -1;
2786 CloseDialog();
2787 return TRUE;
2788 case KEY_HOME:
2789 case KEY_NUMPAD7:
2791 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2792 return TRUE;
2794 return Do_ProcessFirstCtrl();
2795 case KEY_TAB:
2796 case KEY_SHIFTTAB:
2797 return Do_ProcessTab(Key == KEY_TAB);
2798 case KEY_SPACE:
2799 return Do_ProcessSpace();
2800 case KEY_CTRLNUMENTER:
2801 case KEY_CTRLENTER: {
2802 for (I = 0; I < ItemCount; I++)
2803 if (Item[I]->DefaultButton) {
2804 if (Item[I]->Flags & DIF_DISABLE) {
2805 // ProcessKey(KEY_DOWN); // на твой вкус :-)
2806 return TRUE;
2809 if (!FarIsEdit(Item[I]->Type))
2810 Item[I]->Selected = 1;
2812 ExitCode = I;
2813 /* $ 18.05.2001 DJ */
2814 CloseDialog();
2815 /* DJ $ */
2816 return TRUE;
2819 if (!DialogMode.Check(DMODE_OLDSTYLE)) {
2820 DialogMode.Clear(DMODE_ENDLOOP); // только если есть
2821 return TRUE; // делать больше не чего
2824 case KEY_NUMENTER:
2825 case KEY_ENTER: {
2826 if (Item[FocusPos]->Type != DI_COMBOBOX && FarIsEdit(Item[FocusPos]->Type)
2827 && (Item[FocusPos]->Flags & DIF_EDITOR) && !(Item[FocusPos]->Flags & DIF_READONLY)) {
2828 unsigned EditorLastPos;
2830 for (EditorLastPos = I = FocusPos; I < ItemCount; I++)
2831 if (FarIsEdit(Item[I]->Type) && (Item[I]->Flags & DIF_EDITOR))
2832 EditorLastPos = I;
2833 else
2834 break;
2836 if (((DlgEdit *)(Item[EditorLastPos]->ObjPtr))->GetLength())
2837 return TRUE;
2839 for (I = EditorLastPos; I > FocusPos; I--) {
2840 int CurPos;
2842 if (I == FocusPos + 1)
2843 CurPos = ((DlgEdit *)(Item[I - 1]->ObjPtr))->GetCurPos();
2844 else
2845 CurPos = 0;
2847 ((DlgEdit *)(Item[I - 1]->ObjPtr))->GetString(strStr);
2848 int Length = (int)strStr.GetLength();
2849 ((DlgEdit *)(Item[I]->ObjPtr))
2850 ->SetString(CurPos >= Length ? L"" : strStr.CPtr() + CurPos);
2852 if (CurPos < Length)
2853 strStr.Truncate(CurPos);
2855 ((DlgEdit *)(Item[I]->ObjPtr))->SetCurPos(0);
2856 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(strStr);
2859 if (EditorLastPos > FocusPos) {
2860 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->SetCurPos(0);
2861 Do_ProcessNextCtrl(FALSE, FALSE);
2864 ShowDialog();
2865 return TRUE;
2866 } else if (Item[FocusPos]->Type == DI_BUTTON) {
2867 Item[FocusPos]->Selected = 1;
2869 // сообщение - "Кнокна кликнута"
2870 if (SendDlgMessage((HANDLE)this, DN_BTNCLICK, FocusPos, 0))
2871 return TRUE;
2873 if (Item[FocusPos]->Flags & DIF_BTNNOCLOSE)
2874 return TRUE;
2876 ExitCode = FocusPos;
2877 CloseDialog();
2878 return TRUE;
2879 } else {
2880 ExitCode = -1;
2882 for (I = 0; I < ItemCount; I++) {
2883 if (Item[I]->DefaultButton && !(Item[I]->Flags & DIF_BTNNOCLOSE)) {
2884 if (Item[I]->Flags & DIF_DISABLE) {
2885 // ProcessKey(KEY_DOWN); // на твой вкус :-)
2886 return TRUE;
2889 // if (!(FarIsEdit(Item[I].Type) || Item[I].Type == DI_CHECKBOX || Item[I].Type == DI_RADIOBUTTON))
2890 // Item[I].Selected=1;
2891 ExitCode = I;
2892 break;
2897 if (ExitCode == -1)
2898 ExitCode = FocusPos;
2900 CloseDialog();
2901 return TRUE;
2904 3-х уровневое состояние
2905 Для чекбокса сюда попадем только в случае, если контрол
2906 имеет флаг DIF_3STATE
2908 case KEY_ADD:
2909 case KEY_SUBTRACT:
2910 case KEY_MULTIPLY:
2912 if (Item[FocusPos]->Type == DI_CHECKBOX) {
2913 unsigned int CHKState = (Key == KEY_ADD
2915 : (Key == KEY_SUBTRACT
2917 : ((Key == KEY_MULTIPLY) ? 2 : Item[FocusPos]->Selected)));
2919 if (Item[FocusPos]->Selected != (int)CHKState)
2920 if (SendDlgMessage((HANDLE)this, DN_BTNCLICK, FocusPos, CHKState)) {
2921 Item[FocusPos]->Selected = CHKState;
2922 ShowDialog();
2926 return TRUE;
2927 case KEY_LEFT:
2928 case KEY_NUMPAD4:
2929 case KEY_SHIFTNUMPAD4:
2930 case KEY_MSWHEEL_LEFT:
2931 case KEY_RIGHT:
2932 case KEY_NUMPAD6:
2933 case KEY_SHIFTNUMPAD6:
2934 case KEY_MSWHEEL_RIGHT: {
2935 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2936 return TRUE;
2938 if (FarIsEdit(Item[FocusPos]->Type)) {
2939 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(Key);
2940 return TRUE;
2941 } else {
2942 return MoveToCtrlHorizontal(Key == KEY_RIGHT || Key == KEY_NUMPAD6);
2945 case KEY_UP:
2946 case KEY_NUMPAD8:
2947 case KEY_DOWN:
2948 case KEY_NUMPAD2: {
2949 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2950 return TRUE;
2952 return MoveToCtrlVertical(Key == KEY_UP || Key == KEY_NUMPAD8);
2954 // $ 27.04.2001 VVM - Обработка колеса мышки
2955 case KEY_MSWHEEL_UP:
2956 case KEY_MSWHEEL_DOWN:
2957 case KEY_CTRLUP:
2958 case KEY_CTRLNUMPAD8:
2959 case KEY_CTRLDOWN:
2960 case KEY_CTRLNUMPAD2:
2961 return ProcessOpenComboBox(Item[FocusPos]->Type, Item[FocusPos], FocusPos);
2962 // ЭТО перед default предпоследний!!!
2963 case KEY_END:
2964 case KEY_NUMPAD1:
2966 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2967 return TRUE;
2969 if (FarIsEdit(Item[FocusPos]->Type)) {
2970 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(Key);
2971 return TRUE;
2974 // ???
2975 // ЭТО перед default последний!!!
2976 case KEY_PGDN:
2977 case KEY_NUMPAD3:
2979 if (Item[FocusPos]->Type == DI_USERCONTROL) // для user-типа вываливаем
2980 return TRUE;
2982 if (!(Item[FocusPos]->Flags & DIF_EDITOR)) {
2983 for (I = 0; I < ItemCount; I++)
2984 if (Item[I]->DefaultButton) {
2985 ChangeFocus2(I);
2986 ShowDialog();
2987 return TRUE;
2990 return TRUE;
2992 break;
2994 case KEY_F11: {
2995 if (!CheckDialogMode(DMODE_NOPLUGINS)) {
2996 return FrameManager->ProcessKey(Key);
2998 } break;
3000 // для DIF_EDITOR будет обработано ниже
3001 default: {
3002 // if(Item[FocusPos].Type == DI_USERCONTROL) // для user-типа вываливаем
3003 // return TRUE;
3004 if (Item[FocusPos]->Type == DI_LISTBOX) {
3005 VMenu *List = Item[FocusPos]->ListPtr;
3006 int CurListPos = List->GetSelectPos();
3007 auto CheckedListItem = List->GetCheck(-1);
3008 List->ProcessKey(Key);
3009 int NewListPos = List->GetSelectPos();
3011 if (NewListPos != CurListPos && !DlgProc((HANDLE)this, DN_LISTCHANGE, FocusPos, NewListPos)) {
3012 if (!DialogMode.Check(DMODE_SHOW))
3013 return TRUE;
3015 List->SetCheck(CheckedListItem, CurListPos);
3017 if (DialogMode.Check(DMODE_SHOW) && !(Item[FocusPos]->Flags & DIF_HIDDEN))
3018 ShowDialog(FocusPos); // FocusPos
3021 return TRUE;
3024 if (FarIsEdit(Item[FocusPos]->Type)) {
3025 DlgEdit *edt = (DlgEdit *)Item[FocusPos]->ObjPtr;
3027 if (Key == KEY_CTRLL) // исключим смену режима RO для поля ввода с клавиатуры
3029 return TRUE;
3030 } else if (Key == KEY_CTRLU) {
3031 edt->SetClearFlag(0);
3032 edt->Select(-1, 0);
3033 edt->Show();
3034 return TRUE;
3035 } else if ((Item[FocusPos]->Flags & DIF_EDITOR) && !(Item[FocusPos]->Flags & DIF_READONLY)) {
3036 switch (Key) {
3037 case KEY_BS: {
3038 int CurPos = edt->GetCurPos();
3040 // В начале строки????
3041 if (!edt->GetCurPos()) {
3042 // а "выше" тоже DIF_EDITOR?
3043 if (FocusPos > 0 && (Item[FocusPos - 1]->Flags & DIF_EDITOR)) {
3044 // добавляем к предыдущему и...
3045 DlgEdit *edt_1 = (DlgEdit *)Item[FocusPos - 1]->ObjPtr;
3046 edt_1->GetString(strStr);
3047 CurPos = static_cast<int>(strStr.GetLength());
3048 FARString strAdd;
3049 edt->GetString(strAdd);
3050 strStr+= strAdd;
3051 edt_1->SetString(strStr);
3053 for (I = FocusPos + 1; I < ItemCount; I++) {
3054 if (Item[I]->Flags & DIF_EDITOR) {
3055 if (I > FocusPos) {
3056 ((DlgEdit *)(Item[I]->ObjPtr))->GetString(strStr);
3057 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(strStr);
3060 ((DlgEdit *)(Item[I]->ObjPtr))->SetString(L"");
3061 } else // ага, значит FocusPos это есть последний из DIF_EDITOR
3063 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(L"");
3064 break;
3068 Do_ProcessNextCtrl(TRUE);
3069 edt_1->SetCurPos(CurPos);
3071 } else {
3072 edt->ProcessKey(Key);
3075 ShowDialog();
3076 return TRUE;
3078 case KEY_CTRLY: {
3079 for (I = FocusPos; I < ItemCount; I++)
3080 if (Item[I]->Flags & DIF_EDITOR) {
3081 if (I > FocusPos) {
3082 ((DlgEdit *)(Item[I]->ObjPtr))->GetString(strStr);
3083 ((DlgEdit *)(Item[I - 1]->ObjPtr))->SetString(strStr);
3086 ((DlgEdit *)(Item[I]->ObjPtr))->SetString(L"");
3087 } else
3088 break;
3090 ShowDialog();
3091 return TRUE;
3093 case KEY_NUMDEL:
3094 case KEY_DEL: {
3096 $ 19.07.2000 SVS
3097 ! "...В редакторе команд меню нажмите home shift+end del
3098 блок не удаляется..."
3099 DEL у итемов, имеющих DIF_EDITOR, работал без учета
3100 выделения...
3102 if (FocusPos < ItemCount + 1 && (Item[FocusPos + 1]->Flags & DIF_EDITOR)) {
3103 int CurPos = edt->GetCurPos();
3104 int Length = edt->GetLength();
3105 int SelStart, SelEnd;
3106 edt->GetSelection(SelStart, SelEnd);
3107 edt->GetString(strStr);
3109 if (SelStart > -1) {
3110 FARString strEnd = strStr.CPtr() + SelEnd;
3111 strStr.Truncate(SelStart);
3112 strStr+= strEnd;
3113 edt->SetString(strStr);
3114 edt->SetCurPos(SelStart);
3115 ShowDialog();
3116 return TRUE;
3117 } else if (CurPos >= Length) {
3118 DlgEdit *edt_1 = (DlgEdit *)Item[FocusPos + 1]->ObjPtr;
3121 $ 12.09.2000 SVS
3122 Решаем проблему, если Del нажали в позиции
3123 большей, чем длина строки
3125 if (CurPos > Length) {
3126 strStr.Append(L' ', CurPos - Length);
3129 FARString strAdd;
3130 edt_1->GetString(strAdd);
3131 edt_1->SetString(strStr + strAdd);
3132 ProcessKey(KEY_CTRLY);
3133 edt->SetCurPos(CurPos);
3134 ShowDialog();
3135 return TRUE;
3139 break;
3141 case KEY_PGDN:
3142 case KEY_NUMPAD3:
3143 case KEY_PGUP:
3144 case KEY_NUMPAD9: {
3145 I = FocusPos;
3147 while (Item[I]->Flags & DIF_EDITOR)
3148 I = ChangeFocus(I, (Key == KEY_PGUP || Key == KEY_NUMPAD9) ? -1 : 1, FALSE);
3150 if (!(Item[I]->Flags & DIF_EDITOR))
3151 I = ChangeFocus(I, (Key == KEY_PGUP || Key == KEY_NUMPAD9) ? 1 : -1, FALSE);
3153 ChangeFocus2(I);
3154 ShowDialog();
3156 return TRUE;
3161 if (Key == KEY_OP_XLAT && !(Item[FocusPos]->Flags & DIF_READONLY)) {
3162 edt->SetClearFlag(0);
3163 edt->Xlat();
3165 // иначе неправильно работает ctrl-end
3166 edt->strLastStr = edt->GetStringAddr();
3167 edt->LastPartLength = static_cast<int>(edt->strLastStr.GetLength());
3169 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3170 return TRUE;
3173 if (!(Item[FocusPos]->Flags & DIF_READONLY) || IsNavKey(Key)) {
3174 // "только что ломанулись и начинать выделение с нуля"?
3175 if ((Opt.Dialogs.EditLine & DLGEDITLINE_NEWSELONGOTFOCUS) && Item[FocusPos]->SelStart != -1
3176 && PrevFocusPos != FocusPos) { // && Item[FocusPos].SelEnd)
3178 edt->Flags().Clear(FEDITLINE_MARKINGBLOCK);
3179 PrevFocusPos = FocusPos;
3182 if (edt->ProcessKey(Key)) {
3183 if (Item[FocusPos]->Flags & DIF_READONLY)
3184 return TRUE;
3186 if ((Key == KEY_CTRLEND || Key == KEY_CTRLNUMPAD1)
3187 && edt->GetCurPos() == edt->GetLength()) {
3188 if (edt->LastPartLength == -1)
3189 edt->strLastStr = edt->GetStringAddr();
3191 strStr = edt->strLastStr;
3192 int CurCmdPartLength = static_cast<int>(strStr.GetLength());
3193 edt->HistoryGetSimilar(strStr, edt->LastPartLength);
3195 if (edt->LastPartLength == -1) {
3196 edt->strLastStr = edt->GetStringAddr();
3197 edt->LastPartLength = CurCmdPartLength;
3199 edt->DisableAC();
3200 edt->SetString(strStr);
3201 edt->Select(edt->LastPartLength, static_cast<int>(strStr.GetLength()));
3202 edt->RevertAC();
3203 Show();
3204 return TRUE;
3207 edt->LastPartLength = -1;
3209 if (Key == KEY_CTRLSHIFTEND || Key == KEY_CTRLSHIFTNUMPAD1) {
3210 edt->EnableAC();
3211 edt->AutoComplete(true, false);
3212 edt->RevertAC();
3215 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3216 return TRUE;
3218 } else if (!(Key & (KEY_ALT | KEY_RALT)))
3219 return TRUE;
3222 if (ProcessHighlighting(Key, FocusPos, FALSE))
3223 return TRUE;
3225 return (Opt.XLat.EnableForDialogs && ProcessHighlighting(Key, FocusPos, TRUE));
3228 return FALSE;
3231 void Dialog::ProcessKey(FarKey Key, unsigned ItemPos)
3233 unsigned SavedFocusPos = FocusPos;
3234 FocusPos = ItemPos;
3235 ProcessKey(Key);
3236 if (FocusPos == ItemPos)
3237 FocusPos = SavedFocusPos;
3240 //////////////////////////////////////////////////////////////////////////
3242 Public, Virtual:
3243 Обработка данных от "мыши".
3244 Перекрывает BaseInput::ProcessMouse.
3247 $ 18.08.2000 SVS
3248 + DN_MOUSECLICK
3250 int Dialog::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
3252 CriticalSectionLock Lock(CS);
3253 unsigned I;
3254 int MsX, MsY;
3255 int Type;
3256 SMALL_RECT Rect;
3258 if (!DialogMode.Check(DMODE_SHOW))
3259 return FALSE;
3261 if (DialogMode.Check(DMODE_MOUSEEVENT)) {
3262 if (!DlgProc((HANDLE)this, DN_MOUSEEVENT, 0, (LONG_PTR)MouseEvent))
3263 return TRUE;
3266 if (!DialogMode.Check(DMODE_SHOW))
3267 return FALSE;
3269 MsX = MouseEvent->dwMousePosition.X;
3270 MsY = MouseEvent->dwMousePosition.Y;
3272 // for (I=0;I<ItemCount;I++)
3273 for (I = ItemCount - 1; I != (unsigned)-1; I--) {
3274 if (Item[I]->Flags & (DIF_DISABLE | DIF_HIDDEN))
3275 continue;
3277 Type = Item[I]->Type;
3279 if (Type == DI_LISTBOX && MsY >= Y1 + Item[I]->Y1 && MsY <= Y1 + Item[I]->Y2
3280 && MsX >= X1 + Item[I]->X1 && MsX <= X1 + Item[I]->X2) {
3281 VMenu *List = Item[I]->ListPtr;
3282 int Pos = List->GetSelectPos();
3283 auto CheckedListItem = List->GetCheck(-1);
3285 if ((MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) {
3286 if (FocusPos != I) {
3287 ChangeFocus2(I);
3288 ShowDialog();
3291 if (MouseEvent->dwEventFlags != DOUBLE_CLICK
3292 && !(Item[I]->IFlags.Flags
3293 & (DLGIIF_LISTREACTIONFOCUS | DLGIIF_LISTREACTIONNOFOCUS))) {
3295 List->ProcessMouse(MouseEvent);
3296 int NewListPos = List->GetSelectPos();
3298 if (NewListPos != Pos
3299 && !SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)NewListPos)) {
3300 List->SetCheck(CheckedListItem, Pos);
3302 if (DialogMode.Check(DMODE_SHOW) && !(Item[I]->Flags & DIF_HIDDEN))
3303 ShowDialog(I); // FocusPos
3304 } else {
3305 Pos = NewListPos;
3307 } else if (!SendDlgMessage((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent)) {
3308 #if 1
3309 List->ProcessMouse(MouseEvent);
3310 int NewListPos = List->GetSelectPos();
3311 int InScroolBar =
3312 (MsX == X1 + Item[I]->X2 && MsY >= Y1 + Item[I]->Y1 && MsY <= Y1 + Item[I]->Y2)
3313 && (List->CheckFlags(VMENU_LISTBOX | VMENU_ALWAYSSCROLLBAR)
3314 || Opt.ShowMenuScrollbar);
3316 if (!InScroolBar && // вне скроллбара и
3317 NewListPos != Pos && // позиция изменилась и
3318 !SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)NewListPos)) // и плагин сказал в морг
3320 List->SetCheck(CheckedListItem, Pos);
3322 if (DialogMode.Check(DMODE_SHOW) && !(Item[I]->Flags & DIF_HIDDEN))
3323 ShowDialog(I); // FocusPos
3324 } else {
3325 Pos = NewListPos;
3327 if (!InScroolBar && !(Item[I]->Flags & DIF_LISTNOCLOSE)) {
3328 ExitCode = I;
3329 CloseDialog();
3330 return TRUE;
3334 #else
3336 if (SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)Pos)) {
3337 if (MsX == X1 + Item[I]->X2 && MsY >= Y1 + Item[I]->Y1 && MsY <= Y1 + Item[I]->Y2)
3338 List->ProcessMouse(MouseEvent); // забыл проверить на клик на скролбар (KM)
3339 else
3340 ProcessKey(KEY_ENTER, I);
3343 #endif
3346 return TRUE;
3347 } else {
3348 if (!MouseEvent->dwButtonState
3349 || SendDlgMessage((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent)) {
3350 if ((I == FocusPos && (Item[I]->IFlags.Flags & DLGIIF_LISTREACTIONFOCUS))
3351 || (I != FocusPos && (Item[I]->IFlags.Flags & DLGIIF_LISTREACTIONNOFOCUS))) {
3352 List->ProcessMouse(MouseEvent);
3353 int NewListPos = List->GetSelectPos();
3355 if (NewListPos != Pos
3356 && !SendDlgMessage((HANDLE)this, DN_LISTCHANGE, I, (LONG_PTR)NewListPos)) {
3357 List->SetCheck(CheckedListItem, Pos);
3359 if (DialogMode.Check(DMODE_SHOW) && !(Item[I]->Flags & DIF_HIDDEN))
3360 ShowDialog(I); // FocusPos
3361 } else
3362 Pos = NewListPos;
3367 return TRUE;
3371 if (MsX < X1 || MsY < Y1 || MsX > X2 || MsY > Y2) {
3372 if (DialogMode.Check(DMODE_CLICKOUTSIDE)
3373 && !DlgProc((HANDLE)this, DN_MOUSECLICK, -1, (LONG_PTR)MouseEvent)) {
3374 if (!DialogMode.Check(DMODE_SHOW))
3375 return FALSE;
3377 // if (!(MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) && PrevLButtonPressed && ScreenObject::CaptureMouseObject)
3378 if (!(MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
3379 && (PrevMouseButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
3380 && (Opt.Dialogs.MouseButton & DMOUSEBUTTON_LEFT))
3381 ProcessKey(KEY_ESC);
3382 // else if (!(MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) && PrevRButtonPressed && ScreenObject::CaptureMouseObject)
3383 else if (!(MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED)
3384 && (PrevMouseButtonState & RIGHTMOST_BUTTON_PRESSED)
3385 && (Opt.Dialogs.MouseButton & DMOUSEBUTTON_RIGHT))
3386 ProcessKey(KEY_ENTER);
3389 if (MouseEvent->dwButtonState)
3390 DialogMode.Set(DMODE_CLICKOUTSIDE);
3392 // ScreenObject::SetCapture(this);
3393 return TRUE;
3396 if (!MouseEvent->dwButtonState) {
3397 DialogMode.Clear(DMODE_CLICKOUTSIDE);
3398 // ScreenObject::SetCapture(nullptr);
3399 return FALSE;
3402 if (!MouseEvent->dwEventFlags || MouseEvent->dwEventFlags == DOUBLE_CLICK) {
3403 // первый цикл - все за исключением рамок.
3404 // for (I=0; I < ItemCount;I++)
3405 for (I = ItemCount - 1; I != (unsigned)-1; I--) {
3406 if (Item[I]->Flags & (DIF_DISABLE | DIF_HIDDEN))
3407 continue;
3409 GetItemRect(I, Rect);
3410 Rect.Left+= X1;
3411 Rect.Top+= Y1;
3412 Rect.Right+= X1;
3413 Rect.Bottom+= Y1;
3414 //_D(SysLog(L"? %2d) Rect (%2d,%2d) (%2d,%2d) '%ls'",I,Rect.left,Rect.top,Rect.right,Rect.bottom,Item[I].Data));
3416 if (MsX >= Rect.Left && MsY >= Rect.Top && MsX <= Rect.Right && MsY <= Rect.Bottom) {
3417 // для прозрачных :-)
3418 if (Item[I]->Type == DI_SINGLEBOX || Item[I]->Type == DI_DOUBLEBOX) {
3419 // если на рамке, то...
3420 if (((MsX == Rect.Left || MsX == Rect.Right) && MsY >= Rect.Top && MsY <= Rect.Bottom)
3421 || // vert
3422 ((MsY == Rect.Top || MsY == Rect.Bottom) && MsX >= Rect.Left
3423 && MsX <= Rect.Right)) // hor
3425 if (DlgProc((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent))
3426 return TRUE;
3428 if (!DialogMode.Check(DMODE_SHOW))
3429 return FALSE;
3430 } else
3431 continue;
3434 if (Item[I]->Type == DI_USERCONTROL) {
3435 // для user-типа подготовим координаты мыши
3436 MouseEvent->dwMousePosition.X-= Rect.Left;
3437 MouseEvent->dwMousePosition.Y-= Rect.Top;
3440 //_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));
3441 if (DlgProc((HANDLE)this, DN_MOUSECLICK, I, (LONG_PTR)MouseEvent))
3442 return TRUE;
3444 if (!DialogMode.Check(DMODE_SHOW))
3445 return TRUE;
3447 if (Item[I]->Type == DI_USERCONTROL) {
3448 ChangeFocus2(I);
3449 ShowDialog();
3450 return TRUE;
3453 break;
3457 if ((MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) {
3458 // for (I=0;I<ItemCount;I++)
3460 for (I = ItemCount - 1; I != (unsigned)-1; I--) {
3461 // Исключаем из списка оповещаемых о мыши недоступные элементы
3462 if (Item[I]->Flags & (DIF_DISABLE | DIF_HIDDEN))
3463 continue;
3465 Type = Item[I]->Type;
3467 GetItemRect(I, Rect);
3468 Rect.Left+= X1;
3469 Rect.Top+= Y1;
3470 Rect.Right+= X1;
3471 Rect.Bottom+= Y1;
3472 if (ItemHasDropDownArrow(Item[I]))
3473 Rect.Right++;
3475 if (MsX >= Rect.Left && MsY >= Rect.Top && MsX <= Rect.Right && MsY <= Rect.Bottom) {
3476 /* ********************************************************** */
3477 if (FarIsEdit(Type)) {
3479 $ 15.08.2000 SVS
3480 + Сделаем так, чтобы ткнув мышкой в DropDownList
3481 список раскрывался сам.
3482 Есть некоторая глюкавость - когда список раскрыт и мы
3483 мышой переваливаем на другой элемент, то список закрывается
3484 но перехода реального на указанный элемент диалога не происходит
3486 int EditX1, EditY1, EditX2, EditY2;
3487 DlgEdit *EditLine = (DlgEdit *)(Item[I]->ObjPtr);
3488 EditLine->GetPosition(EditX1, EditY1, EditX2, EditY2);
3490 if (MsY == EditY1 && Type == DI_COMBOBOX && (Item[I]->Flags & DIF_DROPDOWNLIST)
3491 && MsX >= EditX1 && MsX <= EditX2 + 1) {
3492 EditLine->SetClearFlag(0);
3494 ChangeFocus2(I);
3495 ShowDialog();
3497 ProcessOpenComboBox(Item[I]->Type, Item[I], I);
3499 return TRUE;
3502 ChangeFocus2(I);
3504 if (EditLine->ProcessMouse(MouseEvent)) {
3505 EditLine->SetClearFlag(0); // а может это делать в самом edit?
3508 $ 23.06.2001 KM
3509 ! Оказалось нужно перерисовывать весь диалог иначе
3510 не снимался признак активности с комбобокса с которго уходим.
3512 ShowDialog(); // нужен ли только один контрол или весь диалог?
3513 return TRUE;
3514 } else {
3515 // Проверка на DI_COMBOBOX здесь лишняя. Убрана (KM).
3516 if (MsX == EditX2 + 1 && MsY == EditY1 && ItemHasDropDownArrow(Item[I])) {
3517 EditLine->SetClearFlag(0); // раз уж покусились на, то и...
3519 ChangeFocus2(I);
3521 if (!(Item[I]->Flags & DIF_HIDDEN))
3522 ShowDialog(I);
3524 ProcessOpenComboBox(Item[I]->Type, Item[I], I);
3526 return TRUE;
3531 /* ********************************************************** */
3532 if (Type == DI_BUTTON && MsY == Y1 + Item[I]->Y1
3533 && MsX < X1 + Item[I]->X1 + HiStrCellsCount(Item[I]->strData)) {
3534 ChangeFocus2(I);
3535 ShowDialog();
3537 while (IsMouseButtonPressed())
3540 if (MouseX < X1 || MouseX > X1 + Item[I]->X1 + HiStrCellsCount(Item[I]->strData) + 4
3541 || MouseY != Y1 + Item[I]->Y1) {
3542 ChangeFocus2(I);
3543 ShowDialog();
3545 return TRUE;
3548 ProcessKey(KEY_ENTER, I);
3549 return TRUE;
3552 /* ********************************************************** */
3553 if ((Type == DI_CHECKBOX || Type == DI_RADIOBUTTON) && MsY == Y1 + Item[I]->Y1
3554 && MsX < (X1 + Item[I]->X1 + HiStrCellsCount(Item[I]->strData) + 4
3555 - ((Item[I]->Flags & DIF_MOVESELECT) != 0))) {
3556 ChangeFocus2(I);
3557 ProcessKey(KEY_SPACE, I);
3558 return TRUE;
3561 } // for (I=0;I<ItemCount;I++)
3563 // ДЛЯ MOUSE-Перемещалки:
3564 // Сюда попадаем в том случае, если мышь не попала на активные элементы
3567 if (DialogMode.Check(DMODE_ISCANMOVE)) {
3568 // DialogMode.Set(DMODE_DRAGGED);
3569 OldX1 = X1;
3570 OldX2 = X2;
3571 OldY1 = Y1;
3572 OldY2 = Y2;
3573 // запомним delta места хватания и Left-Top диалогового окна
3574 MsX = abs(X1 - MouseX);
3575 MsY = abs(Y1 - MouseY);
3576 int NeedSendMsg = 0;
3578 for (;;) {
3579 DWORD Mb = IsMouseButtonPressed();
3580 int mx, my, X0, Y0;
3582 if (Mb == FROM_LEFT_1ST_BUTTON_PRESSED) // still dragging
3584 int AdjX = 0, AdjY = 0;
3585 int OX1 = X1;
3586 int OY1 = Y1;
3587 int NX1 = X0 = X1;
3588 int NX2 = X2;
3589 int NY1 = Y0 = Y1;
3590 int NY2 = Y2;
3592 if (MouseX == PrevMouseX)
3593 mx = X1;
3594 else
3595 mx = MouseX - MsX;
3597 if (MouseY == PrevMouseY)
3598 my = Y1;
3599 else
3600 my = MouseY - MsY;
3602 NX2 = mx + (X2 - X1);
3603 NX1 = mx;
3604 AdjX = NX1 - X0;
3605 NY2 = my + (Y2 - Y1);
3606 NY1 = my;
3607 AdjY = NY1 - Y0;
3609 // "А был ли мальчик?" (про холостой ход)
3610 if (OX1 != NX1 || OY1 != NY1) {
3611 if (!NeedSendMsg) // тыкс, а уже посылку делали в диалоговую процедуру?
3613 NeedSendMsg++;
3615 if (!DlgProc((HANDLE)this, DN_DRAGGED, 0, 0)) // а может нас обломали?
3616 break; // валим отсель...плагин сказал - в морг перемещения
3618 if (!DialogMode.Check(DMODE_SHOW))
3619 break;
3622 // Да, мальчик был. Зачнем...
3624 LockScreen LckScr;
3625 Hide();
3626 X1 = NX1;
3627 X2 = NX2;
3628 Y1 = NY1;
3629 Y2 = NY2;
3631 if (AdjX || AdjY)
3632 AdjustEditPos(AdjX, AdjY); //?
3634 Show();
3637 } else if (Mb == RIGHTMOST_BUTTON_PRESSED) // abort
3639 LockScreen LckScr;
3640 Hide();
3641 AdjustEditPos(OldX1 - X1, OldY1 - Y1);
3642 X1 = OldX1;
3643 X2 = OldX2;
3644 Y1 = OldY1;
3645 Y2 = OldY2;
3646 DialogMode.Clear(DMODE_DRAGGED);
3647 DlgProc((HANDLE)this, DN_DRAGGED, 1, TRUE);
3649 if (DialogMode.Check(DMODE_SHOW))
3650 Show();
3652 break;
3653 } else // release key, drop dialog
3655 if (OldX1 != X1 || OldX2 != X2 || OldY1 != Y1 || OldY2 != Y2) {
3656 LockScreen LckScr;
3657 DialogMode.Clear(DMODE_DRAGGED);
3658 DlgProc((HANDLE)this, DN_DRAGGED, 1, 0);
3660 if (DialogMode.Check(DMODE_SHOW))
3661 Show();
3664 break;
3666 } // while (1)
3671 return FALSE;
3674 int Dialog::ProcessOpenComboBox(int Type, DialogItemEx *CurItem, unsigned CurFocusPos)
3676 CriticalSectionLock Lock(CS);
3677 FARString strStr;
3678 DlgEdit *CurEditLine;
3680 // для user-типа вываливаем
3681 if (Type == DI_USERCONTROL)
3682 return TRUE;
3684 CurEditLine = ((DlgEdit *)(CurItem->ObjPtr));
3686 if (FarIsEdit(Type) && (CurItem->Flags & DIF_HISTORY) && Opt.Dialogs.EditHistory
3687 && !CurItem->strHistory.IsEmpty() && !(CurItem->Flags & DIF_READONLY)) {
3688 // Передаем то, что в строке ввода в функцию выбора из истории для выделения нужного пункта в истории.
3689 CurEditLine->GetString(strStr);
3690 SelectFromEditHistory(CurItem, CurEditLine, CurItem->strHistory, strStr);
3692 // $ 18.07.2000 SVS: +обработка DI_COMBOBOX - выбор из списка!
3693 else if (Type == DI_COMBOBOX && CurItem->ListPtr && !(CurItem->Flags & DIF_READONLY)
3694 && CurItem->ListPtr->GetItemCount() > 0) //??
3696 SelectFromComboBox(CurItem, CurEditLine, CurItem->ListPtr);
3699 return TRUE;
3702 unsigned Dialog::ProcessRadioButton(unsigned CurRB)
3704 CriticalSectionLock Lock(CS);
3705 unsigned PrevRB = CurRB, J;
3706 unsigned I;
3708 for (I = CurRB;; I--) {
3709 if (!I)
3710 break;
3712 if (Item[I]->Type == DI_RADIOBUTTON && (Item[I]->Flags & DIF_GROUP))
3713 break;
3715 if (Item[I - 1]->Type != DI_RADIOBUTTON)
3716 break;
3719 do {
3721 $ 28.07.2000 SVS
3722 При изменении состояния каждого элемента посылаем сообщение
3723 посредством функции SendDlgMessage - в ней делается все!
3725 J = Item[I]->Selected;
3726 Item[I]->Selected = 0;
3728 if (J) {
3729 PrevRB = I;
3732 ++I;
3733 } while (I < ItemCount && Item[I]->Type == DI_RADIOBUTTON && !(Item[I]->Flags & DIF_GROUP));
3735 Item[CurRB]->Selected = 1;
3738 $ 28.07.2000 SVS
3739 При изменении состояния каждого элемента посылаем сообщение
3740 посредством функции SendDlgMessage - в ней делается все!
3742 if (!SendDlgMessage((HANDLE)this, DN_BTNCLICK, PrevRB, 0)
3743 || !SendDlgMessage((HANDLE)this, DN_BTNCLICK, CurRB, 1)) {
3744 // вернем назад, если пользователь не захотел...
3745 Item[CurRB]->Selected = 0;
3746 Item[PrevRB]->Selected = 1;
3747 return PrevRB;
3750 return CurRB;
3753 int Dialog::Do_ProcessFirstCtrl()
3755 CriticalSectionLock Lock(CS);
3757 if (FarIsEdit(Item[FocusPos]->Type)) {
3758 ((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(KEY_HOME);
3759 return TRUE;
3760 } else {
3761 for (unsigned I = 0; I < ItemCount; I++)
3762 if (IsItemFocusable(Item[I])) {
3763 ChangeFocus2(I);
3764 ShowDialog();
3765 break;
3769 return TRUE;
3772 int Dialog::Do_ProcessNextCtrl(int Up, BOOL IsRedraw)
3774 CriticalSectionLock Lock(CS);
3775 unsigned OldPos = FocusPos;
3776 unsigned PrevPos = 0;
3778 if (FarIsEdit(Item[FocusPos]->Type) && (Item[FocusPos]->Flags & DIF_EDITOR))
3779 PrevPos = ((DlgEdit *)(Item[FocusPos]->ObjPtr))->GetCurPos();
3781 unsigned I = ChangeFocus(FocusPos, Up ? -1 : 1, FALSE);
3782 Item[FocusPos]->Focus = 0;
3783 Item[I]->Focus = 1;
3784 ChangeFocus2(I);
3786 if (FarIsEdit(Item[I]->Type) && (Item[I]->Flags & DIF_EDITOR))
3787 ((DlgEdit *)(Item[I]->ObjPtr))->SetCurPos(PrevPos);
3789 if (Item[FocusPos]->Type == DI_RADIOBUTTON && (Item[I]->Flags & DIF_MOVESELECT))
3790 ProcessKey(KEY_SPACE);
3791 else if (IsRedraw) {
3792 ShowDialog(OldPos);
3793 ShowDialog(FocusPos);
3796 return TRUE;
3799 int Dialog::MoveToCtrlHorizontal(int right)
3801 int MinDist = RealWidth,
3802 LeftBorder = 0,
3803 RightBorder = RealWidth,
3804 Dist = 0,
3805 MinPos = 0;
3807 for (unsigned int I = 0; I < ItemCount; I++) {
3808 //first, let's find nearest borders
3809 if (IsItemHorizontalSeparator(Item[I])) {
3810 if (Item[I]->X1 < Item[FocusPos]->X1){
3811 if (LeftBorder < Item[I]->X1) {
3812 LeftBorder = Item[I]->X1;
3814 } else if (Item[I]->X1 > Item[FocusPos]->X1) {
3815 if (RightBorder > Item[I]->X1) {
3816 RightBorder = Item[I]->X1;
3821 //find nearest item _inside_ nearest borders
3822 if (I != FocusPos && IsItemFocusable(Item[I]) && Item[I]->Y1 == Item[FocusPos]->Y1) {
3823 Dist = Item[I]->X1 - Item[FocusPos]->X1;
3825 if ((!right && Dist < 0 &&(Item[I]->X1 > LeftBorder))
3826 || (right && Dist > 0 &&(Item[I]->X1 < RightBorder))
3828 if (abs(Dist) < MinDist) {
3829 MinDist = abs(Dist);
3830 MinPos = I;
3836 //MinDist still equal to RealWidth,
3837 //it means current line inside block of items has no focusable controls
3838 //fallback to Do_ProcessNextCtrl
3839 if (MinDist < RealWidth) {
3840 ChangeFocus2(MinPos);
3842 if (Item[MinPos]->Flags & DIF_MOVESELECT) {
3843 Do_ProcessSpace();
3844 } else {
3845 ShowDialog();
3847 } else {
3848 return Do_ProcessNextCtrl(!right);
3852 return TRUE;
3855 int Dialog::MoveToCtrlVertical(int up)
3857 int MinDist = RealHeight,
3858 UpperBorder = 0,
3859 BottomBorder = RealHeight,
3860 Dist = 0,
3861 MinPos = 0;
3863 for (unsigned int I = 0; I < ItemCount; I++) {
3864 //first, let's find nearest borders
3865 if (IsItemVerticalSeparator(Item[I])) {
3866 if (Item[I]->Y1 < Item[FocusPos]->Y1){
3867 if (UpperBorder < Item[I]->Y1) {
3868 UpperBorder = Item[I]->Y1;
3870 } else if (Item[I]->Y1 > Item[FocusPos]->Y1) {
3871 if (BottomBorder > Item[I]->Y1) {
3872 BottomBorder = Item[I]->Y1;
3877 //find nearest item _inside_ nearest borders
3878 if (I != FocusPos && IsItemFocusable(Item[I]) && Item[I]->X1 == Item[FocusPos]->X1) {
3879 Dist = Item[I]->Y1 - Item[FocusPos]->Y1;
3881 if ((up && Dist < 0 && (Item[I]->Y1 > UpperBorder))
3882 || (!up && Dist > 0 && (Item[I]->Y1 < BottomBorder))
3884 if (abs(Dist) < MinDist) {
3885 MinDist = abs(Dist);
3886 MinPos = I;
3892 //current column inside block of items has no focusable controls
3893 //gap more than one line considered as "native" block separator
3894 //fallback to Do_ProcessNextCtrl
3895 if (MinDist < 3) {
3896 ChangeFocus2(MinPos);
3898 if (Item[MinPos]->Flags & DIF_MOVESELECT) {
3899 Do_ProcessSpace();
3900 } else {
3901 ShowDialog();
3903 } else {
3904 return Do_ProcessNextCtrl(up);
3907 return TRUE;
3910 int Dialog::Do_ProcessTab(int Next)
3912 CriticalSectionLock Lock(CS);
3913 unsigned I;
3915 if (ItemCount > 1) {
3916 // Must check for DI_EDIT since DIF_EDITOR and DIF_LISTNOAMPERSAND are equal
3917 if (Item[FocusPos]->Type==DI_EDIT && (Item[FocusPos]->Flags & DIF_EDITOR)) {
3918 I = FocusPos;
3920 while (Item[I]->Type==DI_EDIT && (Item[I]->Flags & DIF_EDITOR))
3921 I = ChangeFocus(I, Next ? 1 : -1, TRUE);
3922 } else {
3923 I = ChangeFocus(FocusPos, Next ? 1 : -1, TRUE);
3925 if (!Next)
3926 while (I > 0
3927 && Item[I]->Type == DI_EDIT && Item[I - 1]->Type == DI_EDIT
3928 && (Item[I]->Flags & DIF_EDITOR) && (Item[I - 1]->Flags & DIF_EDITOR)
3929 && !((DlgEdit *)Item[I]->ObjPtr)->GetLength())
3930 I--;
3932 } else
3933 I = FocusPos;
3935 ChangeFocus2(I);
3936 ShowDialog();
3938 return TRUE;
3941 int Dialog::Do_ProcessSpace()
3943 CriticalSectionLock Lock(CS);
3944 int OldFocusPos;
3946 if (Item[FocusPos]->Type == DI_CHECKBOX) {
3947 int OldSelected = Item[FocusPos]->Selected;
3949 if (Item[FocusPos]->Flags & DIF_3STATE) {
3950 Item[FocusPos]->Selected = (Item[FocusPos]->Selected + 1) % 3;
3951 } else
3952 Item[FocusPos]->Selected = !Item[FocusPos]->Selected;
3954 OldFocusPos = FocusPos;
3956 if (!SendDlgMessage((HANDLE)this, DN_BTNCLICK, FocusPos, Item[FocusPos]->Selected))
3957 Item[OldFocusPos]->Selected = OldSelected;
3959 ShowDialog();
3960 return TRUE;
3961 } else if (Item[FocusPos]->Type == DI_RADIOBUTTON) {
3962 FocusPos = ProcessRadioButton(FocusPos);
3963 ShowDialog();
3964 return TRUE;
3965 } else if (FarIsEdit(Item[FocusPos]->Type) && !(Item[FocusPos]->Flags & DIF_READONLY)) {
3966 if (((DlgEdit *)(Item[FocusPos]->ObjPtr))->ProcessKey(KEY_SPACE)) {
3967 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3970 return TRUE;
3973 return TRUE;
3976 //////////////////////////////////////////////////////////////////////////
3978 Private:
3979 Изменяет фокус ввода (воздействие клавишами
3980 KEY_TAB, KEY_SHIFTTAB, KEY_UP, KEY_DOWN,
3981 а так же Alt-HotKey)
3984 $ 28.07.2000 SVS
3985 Довесок для сообщений DN_KILLFOCUS & DN_SETFOCUS
3988 $ 24.08.2000 SVS
3989 Добавка для DI_USERCONTROL
3991 unsigned Dialog::ChangeFocus(unsigned CurFocusPos, int Step, int SkipGroup)
3993 CriticalSectionLock Lock(CS);
3994 unsigned OrigFocusPos = CurFocusPos;
3996 for (;;) {
3997 CurFocusPos += Step;
3999 if ((int)CurFocusPos < 0) {
4000 CurFocusPos = ItemCount - 1;
4003 if (CurFocusPos >= ItemCount) {
4004 CurFocusPos = 0;
4007 if (IsItemFocusable(Item[CurFocusPos])) {
4008 //move straight to selected radio when SkipGroup is true
4009 if (Item[CurFocusPos]->Type == DI_RADIOBUTTON && !(SkipGroup && Item[CurFocusPos]->Selected)) {
4010 continue;
4011 } else {
4012 break;
4016 // убираем зацикливание с последующим подвисанием :-)
4017 if (OrigFocusPos == CurFocusPos) {
4018 break;
4022 return (CurFocusPos);
4025 //////////////////////////////////////////////////////////////////////////
4027 Private:
4028 Изменяет фокус ввода между двумя элементами.
4029 Вынесен отдельно с тем, чтобы обработать DN_KILLFOCUS & DM_SETFOCUS
4031 void Dialog::ChangeFocus2(unsigned SetFocusPos)
4033 CriticalSectionLock Lock(CS);
4034 int FocusPosNeed = -1;
4036 if (IsItemFocusable(Item[SetFocusPos])) {
4037 if (DialogMode.Check(DMODE_INITOBJECTS)) {
4038 FocusPosNeed = (int)DlgProc((HANDLE)this, DN_KILLFOCUS, FocusPos, 0);
4040 if (!DialogMode.Check(DMODE_SHOW))
4041 return;
4044 if (FocusPosNeed >= 0 && FocusPosNeed < (int)ItemCount && IsItemFocusable(Item[FocusPosNeed]))
4045 SetFocusPos = FocusPosNeed;
4047 Item[FocusPos]->Focus = 0;
4049 // "снимать выделение при потере фокуса?"
4050 if (FarIsEdit(Item[FocusPos]->Type)
4051 && !(Item[FocusPos]->Type == DI_COMBOBOX && (Item[FocusPos]->Flags & DIF_DROPDOWNLIST))) {
4052 DlgEdit *EditPtr = (DlgEdit *)Item[FocusPos]->ObjPtr;
4053 EditPtr->GetSelection(Item[FocusPos]->SelStart, Item[FocusPos]->SelEnd);
4055 if ((Opt.Dialogs.EditLine & DLGEDITLINE_CLEARSELONKILLFOCUS)) {
4056 EditPtr->Select(-1, 0);
4060 Item[SetFocusPos]->Focus = 1;
4062 // "не восстанавливать выделение при получении фокуса?"
4063 if (FarIsEdit(Item[SetFocusPos]->Type)
4064 && !(Item[SetFocusPos]->Type == DI_COMBOBOX
4065 && (Item[SetFocusPos]->Flags & DIF_DROPDOWNLIST))) {
4066 DlgEdit *EditPtr = (DlgEdit *)Item[SetFocusPos]->ObjPtr;
4068 if (!(Opt.Dialogs.EditLine & DLGEDITLINE_NOTSELONGOTFOCUS)) {
4069 if (Opt.Dialogs.EditLine & DLGEDITLINE_SELALLGOTFOCUS)
4070 EditPtr->Select(0, EditPtr->GetStrSize());
4071 else
4072 EditPtr->Select(Item[SetFocusPos]->SelStart, Item[SetFocusPos]->SelEnd);
4073 } else {
4074 EditPtr->Select(-1, 0);
4077 // при получении фокуса ввода переместить курсор в конец строки?
4078 if (Opt.Dialogs.EditLine & DLGEDITLINE_GOTOEOLGOTFOCUS) {
4079 EditPtr->SetCurPos(EditPtr->GetStrSize());
4083 // проинформируем листбокс, есть ли у него фокус
4084 if (Item[FocusPos]->Type == DI_LISTBOX)
4085 Item[FocusPos]->ListPtr->ClearFlags(VMENU_LISTHASFOCUS);
4087 if (Item[SetFocusPos]->Type == DI_LISTBOX)
4088 Item[SetFocusPos]->ListPtr->SetFlags(VMENU_LISTHASFOCUS);
4090 SelectOnEntry(FocusPos, FALSE);
4091 SelectOnEntry(SetFocusPos, TRUE);
4093 PrevFocusPos = FocusPos;
4094 FocusPos = SetFocusPos;
4096 if (DialogMode.Check(DMODE_INITOBJECTS))
4097 DlgProc((HANDLE)this, DN_GOTFOCUS, FocusPos, 0);
4102 Функция SelectOnEntry - выделение строки редактирования
4103 Обработка флага DIF_SELECTONENTRY
4105 void Dialog::SelectOnEntry(unsigned Pos, BOOL Selected)
4107 // if(!DialogMode.Check(DMODE_SHOW))
4108 // return;
4109 if (FarIsEdit(Item[Pos]->Type) && (Item[Pos]->Flags & DIF_SELECTONENTRY)
4110 // && PrevFocusPos != -1 && PrevFocusPos != Pos
4112 DlgEdit *edt = (DlgEdit *)Item[Pos]->ObjPtr;
4114 if (edt) {
4115 if (Selected)
4116 edt->Select(0, edt->GetLength());
4117 else
4118 edt->Select(-1, 0);
4120 //_SVS(SysLog(L"Selected=%d edt->GetLength()=%d",Selected,edt->GetLength()));
4125 int Dialog::SetAutomation(WORD IDParent, WORD id, FarDialogItemFlags UncheckedSet,
4126 FarDialogItemFlags UncheckedSkip, FarDialogItemFlags CheckedSet, FarDialogItemFlags CheckedSkip,
4127 FarDialogItemFlags Checked3Set, FarDialogItemFlags Checked3Skip)
4129 CriticalSectionLock Lock(CS);
4130 int Ret = FALSE;
4132 if (IDParent < ItemCount && (Item[IDParent]->Flags & DIF_AUTOMATION) && id < ItemCount
4133 && IDParent != id) // Сами себя не юзаем!
4135 Ret = Item[IDParent]->AddAutomation(id, UncheckedSet, UncheckedSkip, CheckedSet, CheckedSkip,
4136 Checked3Set, Checked3Skip);
4139 return Ret;
4142 //////////////////////////////////////////////////////////////////////////
4144 Private:
4145 Заполняем выпадающий список для ComboBox
4147 int Dialog::SelectFromComboBox(DialogItemEx *CurItem,
4148 DlgEdit *EditLine, // строка редактирования
4149 VMenu *ComboBox) // список строк
4151 CriticalSectionLock Lock(CS);
4152 FARString strStr;
4153 int I, Dest, OriginalPos;
4154 unsigned CurFocusPos = FocusPos;
4156 // if (EditX2 - EditX1 < 20)
4157 // EditX2 = EditX1 + 20;
4159 SetDropDownOpened(TRUE); // Установим флаг "открытия" комбобокса.
4160 SetComboBoxPos(CurItem);
4161 // Перед отрисовкой спросим об изменении цветовых атрибутов
4162 uint64_t RealColors[VMENU_COLOR_COUNT];
4163 FarListColors ListColors = {0};
4164 ListColors.ColorCount = VMENU_COLOR_COUNT;
4165 ListColors.Colors = RealColors;
4166 ComboBox->SetColors(nullptr);
4167 ComboBox->GetColors(&ListColors);
4169 if (DlgProc((HANDLE)this, DN_CTLCOLORDLGLIST, CurItem->ID, (LONG_PTR)&ListColors))
4170 ComboBox->SetColors(&ListColors);
4172 // Выставим то, что есть в строке ввода!
4173 // if(EditLine->GetDropDownBox()) //???
4174 EditLine->GetString(strStr);
4176 if (CurItem->Flags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND))
4177 HiText2Str(strStr, strStr);
4179 ComboBox->SetSelectPos(ComboBox->FindItem(0, strStr, LIFIND_EXACTMATCH), 1);
4180 ComboBox->Show();
4181 OriginalPos = Dest = ComboBox->GetSelectPos();
4182 CurItem->IFlags.Set(DLGIIF_COMBOBOXNOREDRAWEDIT);
4184 while (!ComboBox->Done()) {
4185 if (!GetDropDownOpened()) {
4186 ComboBox->ProcessKey(KEY_ESC);
4187 continue;
4190 INPUT_RECORD ReadRec;
4191 FarKey Key = ComboBox->ReadInput(&ReadRec);
4193 if (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTKEY) && ReadRec.EventType == KEY_EVENT) {
4194 if (DlgProc((HANDLE)this, DN_KEY, FocusPos, Key))
4195 continue;
4196 } else if (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTMOUSE) && ReadRec.EventType == MOUSE_EVENT)
4197 if (!DlgProc((HANDLE)this, DN_MOUSEEVENT, 0, (LONG_PTR)&ReadRec.Event.MouseEvent))
4198 continue;
4200 // здесь можно добавить что-то свое, например,
4201 I = ComboBox->GetSelectPos();
4203 if (Key == KEY_TAB) // Tab в списке - аналог Enter
4205 ComboBox->ProcessKey(KEY_ENTER);
4206 continue; //??
4209 if (I != Dest) {
4210 if (!DlgProc((HANDLE)this, DN_LISTCHANGE, CurFocusPos, I))
4211 ComboBox->SetSelectPos(Dest, Dest < I ? -1 : 1); //????
4212 else
4213 Dest = I;
4215 #if 0
4217 // во время навигации по DropDown листу - отобразим ЭТО дело в
4218 // связанной строке
4219 // ВНИМАНИЕ!!!
4220 // Очень медленная реакция!
4221 if (EditLine->GetDropDownBox())
4223 MenuItem *CurCBItem=ComboBox->GetItemPtr();
4224 EditLine->SetString(CurCBItem->Name);
4225 EditLine->Show();
4226 //EditLine->FastShow();
4229 #endif
4232 // обработку multiselect ComboBox
4233 // ...
4234 ComboBox->ProcessInput();
4237 CurItem->IFlags.Clear(DLGIIF_COMBOBOXNOREDRAWEDIT);
4238 ComboBox->ClearDone();
4239 ComboBox->Hide();
4241 if (GetDropDownOpened()) // Закрылся не программным путём?
4242 Dest = ComboBox->Modal::GetExitCode();
4243 else
4244 Dest = -1;
4246 if (Dest == -1)
4247 ComboBox->SetSelectPos(OriginalPos, 0); //????
4249 SetDropDownOpened(FALSE); // Установим флаг "закрытия" комбобокса.
4251 if (Dest < 0) {
4252 Redraw();
4253 return KEY_ESC;
4256 // ComboBox->GetUserData(Str,MaxLen,Dest);
4257 MenuItemEx *ItemPtr = ComboBox->GetItemPtr(Dest);
4259 if (CurItem->Flags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND)) {
4260 HiText2Str(strStr, ItemPtr->strName);
4261 EditLine->SetString(strStr);
4262 } else
4263 EditLine->SetString(ItemPtr->strName);
4265 EditLine->SetLeftPos(0);
4266 Redraw();
4267 return KEY_ENTER;
4270 //////////////////////////////////////////////////////////////////////////
4272 Private:
4273 Заполняем выпадающий список из истории
4275 BOOL Dialog::SelectFromEditHistory(DialogItemEx *CurItem, DlgEdit *EditLine, const wchar_t *HistoryName,
4276 FARString &strIStr)
4278 CriticalSectionLock Lock(CS);
4280 if (!EditLine)
4281 return FALSE;
4283 FARString strStr;
4284 int ret = 0;
4285 FARString strRegKey = fmtSavedDialogHistory;
4286 strRegKey+= HistoryName;
4287 History DlgHist(HISTORYTYPE_DIALOG, Opt.DialogsHistoryCount, strRegKey.GetMB(), &Opt.Dialogs.EditHistory,
4288 false);
4289 DlgHist.ResetPosition();
4291 // создание пустого вертикального меню
4292 VMenu HistoryMenu(L"", nullptr, 0, Opt.Dialogs.CBoxMaxHeight,
4293 VMENU_ALWAYSSCROLLBAR | VMENU_COMBOBOX | VMENU_NOTCHANGE);
4294 HistoryMenu.SetFlags(VMENU_SHOWAMPERSAND);
4295 HistoryMenu.SetBoxType(SHORT_SINGLE_BOX);
4296 SetDropDownOpened(TRUE); // Установим флаг "открытия" комбобокса.
4297 // запомним (для прорисовки)
4298 CurItem->ListPtr = &HistoryMenu;
4299 ret = DlgHist.Select(HistoryMenu, Opt.Dialogs.CBoxMaxHeight, this, strStr);
4300 // забудим (не нужен)
4301 CurItem->ListPtr = nullptr;
4302 SetDropDownOpened(FALSE); // Установим флаг "закрытия" комбобокса.
4305 if (ret > 0) {
4306 EditLine->SetString(strStr);
4307 EditLine->SetLeftPos(0);
4308 EditLine->SetClearFlag(0);
4309 Redraw();
4310 return TRUE;
4313 return FALSE;
4316 //////////////////////////////////////////////////////////////////////////
4318 Private:
4319 Работа с историей - добавление и reorder списка
4321 int Dialog::AddToEditHistory(const wchar_t *AddStr, const wchar_t *HistoryName)
4323 CriticalSectionLock Lock(CS);
4325 if (!*AddStr) {
4326 return FALSE;
4329 FARString strRegKey = fmtSavedDialogHistory;
4330 strRegKey+= HistoryName;
4331 History DlgHist(HISTORYTYPE_DIALOG, Opt.DialogsHistoryCount, strRegKey.GetMB(), &Opt.Dialogs.EditHistory,
4332 false);
4333 DlgHist.AddToHistory(AddStr);
4334 return TRUE;
4337 int Dialog::CheckHighlights(WORD CheckSymbol, int StartPos)
4339 CriticalSectionLock Lock(CS);
4340 int Type, I;
4341 DWORD Flags;
4343 if (StartPos < 0)
4344 StartPos = 0;
4346 for (I = StartPos; I < (int)ItemCount; I++) {
4347 Type = Item[I]->Type;
4348 Flags = Item[I]->Flags;
4350 if ((!FarIsEdit(Type) || (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST)))
4351 && !(Flags & (DIF_SHOWAMPERSAND | DIF_DISABLE | DIF_HIDDEN))) {
4352 const wchar_t *ChPtr = wcschr(Item[I]->strData, L'&');
4354 if (ChPtr) {
4355 WORD Ch = ChPtr[1];
4357 if (Ch && Upper(CheckSymbol) == Upper(Ch))
4358 return I;
4359 } else if (!CheckSymbol)
4360 return I;
4364 return -1;
4367 //////////////////////////////////////////////////////////////////////////
4369 Private:
4370 Если жмакнули Alt-???
4372 int Dialog::ProcessHighlighting(FarKey Key, unsigned FocusPos, int Translate)
4374 CriticalSectionLock Lock(CS);
4375 int Type;
4376 DWORD Flags;
4378 for (unsigned I = 0; I < ItemCount; I++) {
4379 Type = Item[I]->Type;
4380 Flags = Item[I]->Flags;
4382 if ((!FarIsEdit(Type) || (Type == DI_COMBOBOX && (Flags & DIF_DROPDOWNLIST)))
4383 && !(Flags & (DIF_SHOWAMPERSAND | DIF_DISABLE | DIF_HIDDEN)))
4384 if (IsKeyHighlighted(Item[I]->strData, Key, Translate)) {
4385 int DisableSelect = FALSE;
4387 // Если ЭТО: DlgEdit(пред контрол) и DI_TEXT в одну строку, то...
4388 if (I > 0 && Type == DI_TEXT && // DI_TEXT
4389 FarIsEdit(Item[I - 1]->Type) && // и редактор
4390 Item[I]->Y1 == Item[I - 1]->Y1 && // и оба в одну строку
4391 (I + 1 < ItemCount && Item[I]->Y1 != Item[I + 1]->Y1)) // ...и следующий контрол в другой строке
4393 // Сначала сообщим о случившемся факте процедуре обработки диалога, а потом...
4394 if (!DlgProc((HANDLE)this, DN_HOTKEY, I, Key))
4395 break; // сказали не продолжать обработку...
4397 // ... если предыдущий контрол задизаблен или невидим, тогда выходим.
4398 if ((Item[I - 1]->Flags & (DIF_DISABLE | DIF_HIDDEN))) // и не задисаблен
4399 break;
4401 I = ChangeFocus(I, -1, FALSE);
4402 DisableSelect = TRUE;
4403 } else if (Item[I]->Type == DI_TEXT || Item[I]->Type == DI_VTEXT
4404 || Item[I]->Type == DI_SINGLEBOX || Item[I]->Type == DI_DOUBLEBOX) {
4405 if (I + 1 < ItemCount) // ...и следующий контрол
4407 // Сначала сообщим о случившемся факте процедуре обработки диалога, а потом...
4408 if (!DlgProc((HANDLE)this, DN_HOTKEY, I, Key))
4409 break; // сказали не продолжать обработку...
4411 // ... если следующий контрол задизаблен или невидим, тогда выходим.
4412 if ((Item[I + 1]->Flags & (DIF_DISABLE | DIF_HIDDEN))) // и не задисаблен
4413 break;
4415 I = ChangeFocus(I, 1, FALSE);
4416 DisableSelect = TRUE;
4420 // Сообщим о случивщемся факте процедуре обработки диалога
4421 if (!DlgProc((HANDLE)this, DN_HOTKEY, I, Key))
4422 break; // сказали не продолжать обработку...
4424 ChangeFocus2(I);
4425 ShowDialog();
4427 if ((Item[I]->Type == DI_CHECKBOX || Item[I]->Type == DI_RADIOBUTTON)
4428 && (!DisableSelect || (Item[I]->Flags & DIF_MOVESELECT))) {
4429 Do_ProcessSpace();
4430 return TRUE;
4431 } else if (Item[I]->Type == DI_BUTTON) {
4432 ProcessKey(KEY_ENTER, I);
4433 return TRUE;
4435 // при ComboBox`е - "вываливаем" последний //????
4436 else if (Item[I]->Type == DI_COMBOBOX) {
4437 ProcessOpenComboBox(Item[I]->Type, Item[I], I);
4438 // ProcessKey(KEY_CTRLDOWN);
4439 return TRUE;
4442 return TRUE;
4446 return FALSE;
4449 //////////////////////////////////////////////////////////////////////////
4451 функция подравнивания координат edit классов
4453 void Dialog::AdjustEditPos(int dx, int dy)
4455 CriticalSectionLock Lock(CS);
4456 DialogItemEx *CurItem;
4457 int x1, x2, y1, y2;
4459 if (!DialogMode.Check(DMODE_CREATEOBJECTS))
4460 return;
4462 ScreenObject *DialogScrObject;
4464 for (unsigned I = 0; I < ItemCount; I++) {
4465 CurItem = Item[I];
4466 int Type = CurItem->Type;
4468 if ((CurItem->ObjPtr && FarIsEdit(Type)) || (CurItem->ListPtr && Type == DI_LISTBOX)) {
4469 if (Type == DI_LISTBOX)
4470 DialogScrObject = (ScreenObject *)CurItem->ListPtr;
4471 else
4472 DialogScrObject = (ScreenObject *)CurItem->ObjPtr;
4474 DialogScrObject->GetPosition(x1, y1, x2, y2);
4475 x1+= dx;
4476 x2+= dx;
4477 y1+= dy;
4478 y2+= dy;
4479 DialogScrObject->SetPosition(x1, y1, x2, y2);
4483 ProcessCenterGroup();
4486 //////////////////////////////////////////////////////////////////////////
4488 Работа с доп. данными экземпляра диалога
4489 Пока простое копирование (присвоение)
4491 void Dialog::SetDialogData(LONG_PTR NewDataDialog)
4493 DataDialog = NewDataDialog;
4496 //////////////////////////////////////////////////////////////////////////
4498 $ 29.06.2007 yjh\
4499 При расчётах времён копирования проще/надёжнее учитывать время ожидания
4500 пользовательских ответов в одном месте (здесь).
4501 Сброс этой переменной должен осуществляться перед общим началом операции
4503 long WaitUserTime;
4506 $ 11.08.2000 SVS
4507 + Для того, чтобы послать DM_CLOSE нужно переопределить Process
4509 static std::atomic<int> s_in_dialog{0};
4511 void Dialog::Process()
4513 // if(DialogMode.Check(DMODE_SMALLDIALOG))
4514 SetRestoreScreenMode(TRUE);
4515 ClearDone();
4516 InitDialog();
4518 if (ExitCode == -1) {
4519 clock_t btm = 0;
4520 long save = 0;
4521 DialogMode.Set(DMODE_BEGINLOOP);
4523 if (1 == ++s_in_dialog) {
4524 btm = GetProcessUptimeMSec();
4525 save = WaitUserTime;
4526 WaitUserTime = -1;
4529 FrameManager->ExecuteModal(this);
4530 save+= (GetProcessUptimeMSec() - btm);
4532 if (0 == --s_in_dialog)
4533 WaitUserTime = save;
4536 if (pSaveItemEx)
4537 for (unsigned i = 0; i < ItemCount; i++)
4538 DialogItemExToDialogItemEx(Item[i], &pSaveItemEx[i]);
4541 void Dialog::CloseDialog()
4543 CriticalSectionLock Lock(CS);
4544 GetDialogObjectsData();
4546 if (DlgProc((HANDLE)this, DN_CLOSE, ExitCode, 0)) {
4547 DialogMode.Set(DMODE_ENDLOOP);
4548 Hide();
4550 if (DialogMode.Check(DMODE_BEGINLOOP)
4551 && (DialogMode.Check(DMODE_MSGINTERNAL) || FrameManager->ManagerStarted())) {
4552 DialogMode.Clear(DMODE_BEGINLOOP);
4553 FrameManager->DeleteFrame(this);
4556 _DIALOG(CleverSysLog CL(L"Close Dialog"));
4561 $ 17.05.2001 DJ
4562 установка help topic'а и прочие радости, временно перетащенные сюда
4563 из Modal
4565 void Dialog::SetHelp(const wchar_t *Topic)
4567 CriticalSectionLock Lock(CS);
4569 if (HelpTopic)
4570 delete[] HelpTopic;
4572 HelpTopic = nullptr;
4574 if (Topic && *Topic) {
4575 HelpTopic = new (std::nothrow) wchar_t[wcslen(Topic) + 1];
4577 if (HelpTopic)
4578 wcscpy(HelpTopic, Topic);
4582 void Dialog::ShowHelp()
4584 CriticalSectionLock Lock(CS);
4586 if (HelpTopic && *HelpTopic) {
4587 Help::Present(HelpTopic);
4591 void Dialog::ClearDone()
4593 CriticalSectionLock Lock(CS);
4594 ExitCode = -1;
4595 DialogMode.Clear(DMODE_ENDLOOP);
4598 void Dialog::SetExitCode(int Code)
4600 CriticalSectionLock Lock(CS);
4601 ExitCode = Code;
4602 DialogMode.Set(DMODE_ENDLOOP);
4603 // CloseDialog();
4607 $ 19.05.2001 DJ
4608 возвращаем наше название для меню по F12
4610 int Dialog::GetTypeAndName(FARString &strType, FARString &strName)
4612 CriticalSectionLock Lock(CS);
4613 strType = Msg::DialogType;
4614 strName.Clear();
4615 const wchar_t *lpwszTitle = GetDialogTitle();
4617 if (lpwszTitle)
4618 strName = lpwszTitle;
4620 return MODALTYPE_DIALOG;
4623 int Dialog::GetMacroMode()
4625 return MACRO_DIALOG;
4628 int Dialog::FastHide()
4630 return Opt.AllCtrlAltShiftRule & CASR_DIALOG;
4633 void Dialog::ResizeConsole()
4635 CriticalSectionLock Lock(CS);
4637 DialogMode.Set(DMODE_RESIZED);
4639 if (IsVisible()) {
4640 Hide();
4643 COORD c = {(SHORT)(ScrX + 1), (SHORT)(ScrY + 1)};
4644 SendDlgMessage(reinterpret_cast<HANDLE>(this), DN_RESIZECONSOLE, 0, reinterpret_cast<LONG_PTR>(&c));
4646 int x1, y1, x2, y2;
4647 GetPosition(x1, y1, x2, y2);
4648 c.X = Min(x1, ScrX - 1);
4649 c.Y = Min(y1, ScrY - 1);
4650 if (c.X != x1 || c.Y != y1) {
4651 c.X = x1;
4652 c.Y = y1;
4653 SendDlgMessage(reinterpret_cast<HANDLE>(this), DM_MOVEDIALOG, TRUE, reinterpret_cast<LONG_PTR>(&c));
4654 Dialog::SetComboBoxPos();
4658 // void Dialog::OnDestroy()
4660 // /*
4661 // $ 21.04.2002 KM
4662 // Эта функция потеряла своё значение при текущем менеджере
4663 // и системе создания и уничтожения фреймов.
4664 // */
4665 // if(DialogMode.Check(DMODE_RESIZED))
4666 // {
4667 // Frame *BFrame=FrameManager->GetBottomFrame();
4668 // if(BFrame)
4669 // BFrame->UnlockRefresh();
4670 // /*
4671 // $ 21.04.2002 KM
4672 // А вот этот DM_KILLSAVESCREEN здесь только вредит. Удаление
4673 // диалога происходит без восстановления ShadowSaveScr и вот
4674 // они: "артефакты" непрорисовки.
4675 // */
4676 // SendDlgMessage((HANDLE)this,DM_KILLSAVESCREEN,0,0);
4677 // }
4678 // };
4680 LONG_PTR WINAPI Dialog::DlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
4682 if (DialogMode.Check(DMODE_ENDLOOP))
4683 return 0;
4685 LONG_PTR Result;
4686 FarDialogEvent de = {hDlg, Msg, Param1, Param2, 0};
4688 if (!reinterpret_cast<Dialog *>(hDlg)->CheckDialogMode(DMODE_NOPLUGINS)) {
4689 if (CtrlObject->Plugins.ProcessDialogEvent(DE_DLGPROCINIT, &de))
4690 return de.Result;
4692 Result = RealDlgProc(hDlg, Msg, Param1, Param2);
4693 if (!reinterpret_cast<Dialog *>(hDlg)->CheckDialogMode(DMODE_NOPLUGINS)) {
4694 de.Result = Result;
4695 if (CtrlObject->Plugins.ProcessDialogEvent(DE_DLGPROCEND, &de))
4696 return de.Result;
4698 return Result;
4701 //////////////////////////////////////////////////////////////////////////
4703 $ 28.07.2000 SVS
4704 функция обработки диалога (по умолчанию)
4705 Вот именно эта функция и является последним рубежом обработки диалога.
4706 Т.е. здесь должна быть ВСЯ обработка ВСЕХ сообщений!!!
4708 LONG_PTR WINAPI DefDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
4710 _DIALOG(CleverSysLog CL(L"Dialog.DefDlgProc()"));
4711 _DIALOG(SysLog(L"hDlg=%p, Msg=%ls, Param1=%d (0x%08X), Param2=%d (0x%08X)", hDlg, _DLGMSG_ToName(Msg),
4712 Param1, Param1, Param2, Param2));
4714 if (!hDlg || hDlg == INVALID_HANDLE_VALUE)
4715 return 0;
4717 FarDialogEvent de = {hDlg, Msg, Param1, Param2, 0};
4719 if (!reinterpret_cast<Dialog *>(hDlg)->CheckDialogMode(DMODE_NOPLUGINS)) {
4720 if (CtrlObject->Plugins.ProcessDialogEvent(DE_DEFDLGPROCINIT, &de)) {
4721 return de.Result;
4724 Dialog *Dlg = (Dialog *)hDlg;
4725 CriticalSectionLock Lock(Dlg->CS);
4726 DialogItemEx *CurItem = nullptr;
4727 int Type = 0;
4729 switch (Msg) {
4730 case DN_INITDIALOG:
4731 return FALSE; // изменений не было!
4732 case DM_CLOSE:
4733 return TRUE; // согласен с закрытием
4734 case DN_KILLFOCUS:
4735 return -1; // "Согласен с потерей фокуса"
4736 case DN_GOTFOCUS:
4737 return 0; // always 0
4738 case DN_HELP:
4739 return Param2; // что передали, то и...
4740 case DN_DRAGGED:
4741 return TRUE; // согласен с перемещалкой.
4742 case DN_DRAWDIALOGDONE: {
4743 if (Param1 == 1) // Нужно отрисовать "салазки"?
4746 $ 03.08.2000 tran
4747 вывод текста в углу может приводить к ошибкам изображения
4748 1) когда диалог перемещается в угол
4749 2) когда диалог перемещается из угла
4750 сделал вывод красных палочек по углам
4752 Text(Dlg->X1, Dlg->Y1, 0xCE, L"\\");
4753 Text(Dlg->X1, Dlg->Y2, 0xCE, L"/");
4754 Text(Dlg->X2, Dlg->Y1, 0xCE, L"/");
4755 Text(Dlg->X2, Dlg->Y2, 0xCE, L"\\");
4758 return TRUE;
4760 case DN_DRAWDIALOG: {
4761 return TRUE;
4763 case DN_CTLCOLORDIALOG:
4764 return Param2;
4765 case DN_CTLCOLORDLGITEM:
4766 return Param2;
4767 case DN_CTLCOLORDLGLIST:
4768 return FALSE;
4769 case DN_ENTERIDLE:
4770 return 0; // always 0
4771 case DM_GETDIALOGINFO: {
4772 bool Result = false;
4774 if (Param2) {
4775 if (Dlg->IdExist) {
4776 DialogInfo *di = reinterpret_cast<DialogInfo *>(Param2);
4778 if (static_cast<size_t>(di->StructSize) >= offsetof(DialogInfo, Id) + sizeof(di->Id)) {
4779 di->Id = Dlg->Id;
4780 Result = true;
4785 return Result;
4789 // предварительно проверим...
4790 if (Param1 < 0 || (unsigned)Param1 >= Dlg->ItemCount || !Dlg->Item)
4791 return 0;
4793 CurItem = Dlg->Item[Param1];
4794 Type = CurItem->Type;
4796 switch (Msg) {
4797 case DN_MOUSECLICK:
4798 return FALSE;
4799 case DN_DRAWDLGITEM:
4800 return TRUE;
4801 case DN_HOTKEY:
4802 return TRUE;
4803 case DN_EDITCHANGE:
4804 return TRUE;
4805 case DN_BTNCLICK:
4806 return ((Type == DI_BUTTON && !(CurItem->Flags & DIF_BTNNOCLOSE)) ? FALSE : TRUE);
4807 case DN_LISTCHANGE:
4808 return TRUE;
4809 case DN_KEY:
4810 return FALSE;
4811 case DN_MOUSEEVENT:
4812 return TRUE;
4813 case DM_GETSELECTION: // Msg=DM_GETSELECTION, Param1=ID, Param2=*EditorSelect
4814 return FALSE;
4815 case DM_SETSELECTION:
4816 return FALSE;
4819 return 0;
4822 LONG_PTR Dialog::CallDlgProc(int nMsg, int nParam1, LONG_PTR nParam2)
4824 CriticalSectionLock Lock(CS);
4825 return Dialog::DlgProc((HANDLE)this, nMsg, nParam1, nParam2);
4828 //////////////////////////////////////////////////////////////////////////
4829 LONG_PTR SendDlgMessageSynched(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
4831 Dialog *Dlg = (Dialog *)hDlg;
4832 CriticalSectionLock Lock(Dlg->CS);
4833 _DIALOG(CleverSysLog CL(L"Dialog.SendDlgMessage()"));
4834 _DIALOG(SysLog(L"hDlg=%p, Msg=%ls, Param1=%d (0x%08X), Param2=%d (0x%08X)", hDlg, _DLGMSG_ToName(Msg),
4835 Param1, Param1, Param2, Param2));
4837 // Сообщения, касаемые только диалога и не затрагивающие элементы
4838 switch (Msg) {
4839 /*****************************************************************/
4840 case DM_RESIZEDIALOG:
4841 // изменим вызов RESIZE.
4842 Param1 = -1;
4843 /*****************************************************************/
4844 case DM_MOVEDIALOG: {
4845 int W1, H1;
4846 W1 = Dlg->X2 - Dlg->X1 + 1;
4847 H1 = Dlg->Y2 - Dlg->Y1 + 1;
4848 Dlg->OldX1 = Dlg->X1;
4849 Dlg->OldY1 = Dlg->Y1;
4850 Dlg->OldX2 = Dlg->X2;
4851 Dlg->OldY2 = Dlg->Y2;
4853 // переместили
4854 if (Param1 > 0) // абсолютно?
4856 Dlg->X1 = ((COORD *)Param2)->X;
4857 Dlg->Y1 = ((COORD *)Param2)->Y;
4858 Dlg->X2 = W1;
4859 Dlg->Y2 = H1;
4860 Dlg->CheckDialogCoord();
4861 } else if (!Param1) // значит относительно
4863 Dlg->X1+= ((COORD *)Param2)->X;
4864 Dlg->Y1+= ((COORD *)Param2)->Y;
4865 } else // Resize, Param2=width/height
4867 int OldW1, OldH1;
4868 OldW1 = W1;
4869 OldH1 = H1;
4870 W1 = ((COORD *)Param2)->X;
4871 H1 = ((COORD *)Param2)->Y;
4872 Dlg->RealWidth = W1;
4873 Dlg->RealHeight = H1;
4875 if (W1 < OldW1 || H1 < OldH1) {
4876 Dlg->DialogMode.Set(DMODE_DRAWING);
4877 DialogItemEx *Item;
4878 SMALL_RECT Rect;
4880 for (unsigned int I = 0; I < Dlg->ItemCount; I++) {
4881 Item = Dlg->Item[I];
4883 if (Item->Flags & DIF_HIDDEN)
4884 continue;
4886 Rect.Left = Item->X1;
4887 Rect.Top = Item->Y1;
4889 if (Item->X2 >= W1) {
4890 Rect.Right = Item->X2 - (OldW1 - W1);
4891 Rect.Bottom = Item->Y2;
4892 Dlg->SetItemRect(I, &Rect);
4895 if (Item->Y2 >= H1) {
4896 Rect.Right = Item->X2;
4897 Rect.Bottom = Item->Y2 - (OldH1 - H1);
4898 Dlg->SetItemRect(I, &Rect);
4902 Dlg->DialogMode.Clear(DMODE_DRAWING);
4906 // проверили и скорректировали
4907 if (Dlg->X1 + W1 < 0)
4908 Dlg->X1 = -W1 + 1;
4910 if (Dlg->Y1 + H1 < 0)
4911 Dlg->Y1 = -H1 + 1;
4913 if (Dlg->X1 > ScrX)
4914 Dlg->X1 = ScrX;
4916 if (Dlg->Y1 > ScrY)
4917 Dlg->Y1 = ScrY;
4919 Dlg->X2 = Dlg->X1 + W1 - 1;
4920 Dlg->Y2 = Dlg->Y1 + H1 - 1;
4922 if (Param1 > 0) // абсолютно?
4924 Dlg->CheckDialogCoord();
4927 if (Param1 < 0) // размер?
4929 ((COORD *)Param2)->X = Dlg->X2 - Dlg->X1 + 1;
4930 ((COORD *)Param2)->Y = Dlg->Y2 - Dlg->Y1 + 1;
4931 } else {
4932 ((COORD *)Param2)->X = Dlg->X1;
4933 ((COORD *)Param2)->Y = Dlg->Y1;
4936 int I = Dlg->IsVisible(); // && Dlg->DialogMode.Check(DMODE_INITOBJECTS);
4938 if (I)
4939 Dlg->Hide();
4941 // приняли.
4942 Dlg->AdjustEditPos(Dlg->X1 - Dlg->OldX1, Dlg->Y1 - Dlg->OldY1);
4944 if (I)
4945 Dlg->Show(); // только если диалог был виден
4947 return Param2;
4949 /*****************************************************************/
4950 case DM_REDRAW: {
4951 if (Dlg->DialogMode.Check(DMODE_INITOBJECTS))
4952 Dlg->Show();
4954 return 0;
4956 /*****************************************************************/
4957 case DM_ENABLEREDRAW: {
4958 int Prev = Dlg->IsEnableRedraw;
4960 if (Param1 == TRUE)
4961 Dlg->IsEnableRedraw++;
4962 else if (Param1 == FALSE)
4963 Dlg->IsEnableRedraw--;
4965 // Edit::DisableEditOut(!Dlg->IsEnableRedraw?FALSE:TRUE);
4967 if (!Dlg->IsEnableRedraw && Prev != Dlg->IsEnableRedraw)
4968 if (Dlg->DialogMode.Check(DMODE_INITOBJECTS)) {
4969 Dlg->ShowDialog();
4970 // Dlg->Show();
4971 ScrBuf.Flush();
4974 return Prev;
4977 case DM_ENABLEREDRAW:
4979 if(Param1)
4980 Dlg->IsEnableRedraw++;
4981 else
4982 Dlg->IsEnableRedraw--;
4984 if(!Dlg->IsEnableRedraw)
4985 if(Dlg->DialogMode.Check(DMODE_INITOBJECTS))
4987 Dlg->ShowDialog();
4988 ScrBuf.Flush();
4989 // Dlg->Show();
4991 return 0;
4994 /*****************************************************************/
4995 case DM_SHOWDIALOG: {
4996 // if(!Dlg->IsEnableRedraw)
4998 if (Param1) {
5000 $ 20.04.2002 KM
5001 Залочим прорисовку при прятании диалога, в противном
5002 случае ОТКУДА менеджер узнает, что отрисовывать
5003 объект нельзя!
5005 if (!Dlg->IsVisible()) {
5006 Dlg->Unlock();
5007 Dlg->Show();
5009 } else {
5010 if (Dlg->IsVisible()) {
5011 Dlg->Hide();
5012 Dlg->Lock();
5016 return 0;
5018 /*****************************************************************/
5019 case DM_SETDLGDATA: {
5020 LONG_PTR PrewDataDialog = Dlg->DataDialog;
5021 Dlg->DataDialog = Param2;
5022 return PrewDataDialog;
5024 /*****************************************************************/
5025 case DM_GETDLGDATA: {
5026 return Dlg->DataDialog;
5028 /*****************************************************************/
5029 case DM_KEY: {
5030 int *KeyArray = (int *)Param2;
5031 Dlg->DialogMode.Set(DMODE_KEY);
5033 for (unsigned int I = 0; I < (unsigned)Param1; ++I)
5034 Dlg->ProcessKey(KeyArray[I]);
5036 Dlg->DialogMode.Clear(DMODE_KEY);
5037 return 0;
5039 /*****************************************************************/
5040 case DM_CLOSE: {
5041 if (Param1 == -1)
5042 Dlg->ExitCode = Dlg->FocusPos;
5043 else
5044 Dlg->ExitCode = Param1;
5046 Dlg->CloseDialog();
5047 return TRUE; // согласен с закрытием
5049 /*****************************************************************/
5050 case DM_GETDLGRECT: {
5051 if (Param2) {
5052 int x1, y1, x2, y2;
5053 Dlg->GetPosition(x1, y1, x2, y2);
5054 ((SMALL_RECT *)Param2)->Left = x1;
5055 ((SMALL_RECT *)Param2)->Top = y1;
5056 ((SMALL_RECT *)Param2)->Right = x2;
5057 ((SMALL_RECT *)Param2)->Bottom = y2;
5058 return TRUE;
5061 return FALSE;
5063 /*****************************************************************/
5064 case DM_GETDROPDOWNOPENED: // Param1=0; Param2=0
5066 return Dlg->GetDropDownOpened();
5068 /*****************************************************************/
5069 case DM_KILLSAVESCREEN: {
5070 if (Dlg->SaveScr)
5071 Dlg->SaveScr->Discard();
5073 if (Dlg->ShadowSaveScr)
5074 Dlg->ShadowSaveScr->Discard();
5076 return TRUE;
5078 /*****************************************************************/
5080 Msg=DM_ALLKEYMODE
5081 Param1
5082 =-1 - получить состояние
5083 = 0 - выключить
5084 = 1 - включить
5085 Ret = состояние
5087 case DM_ALLKEYMODE: {
5088 if (Param1 == -1)
5089 return IsProcessAssignMacroKey;
5091 BOOL OldIsProcessAssignMacroKey = IsProcessAssignMacroKey;
5092 IsProcessAssignMacroKey = Param1;
5093 return OldIsProcessAssignMacroKey;
5095 /*****************************************************************/
5096 case DM_SETMOUSEEVENTNOTIFY: // Param1 = 1 on, 0 off, -1 - get
5098 int State = Dlg->DialogMode.Check(DMODE_MOUSEEVENT) ? TRUE : FALSE;
5100 if (Param1 != -1) {
5101 if (!Param1)
5102 Dlg->DialogMode.Clear(DMODE_MOUSEEVENT);
5103 else
5104 Dlg->DialogMode.Set(DMODE_MOUSEEVENT);
5107 return State;
5109 /*****************************************************************/
5110 case DN_RESIZECONSOLE: {
5111 return Dlg->CallDlgProc(Msg, Param1, Param2);
5113 case DM_GETDIALOGINFO: {
5114 return DefDlgProc(hDlg, DM_GETDIALOGINFO, Param1, Param2);
5118 /*****************************************************************/
5119 if (Msg >= DM_USER) {
5120 return Dlg->CallDlgProc(Msg, Param1, Param2);
5123 /*****************************************************************/
5124 DialogItemEx *CurItem = nullptr;
5125 int Type = 0;
5126 size_t Len = 0;
5129 предварительно проверим...
5130 $ 09.12.2001 DJ
5131 для DM_USER проверять _не_надо_!
5133 if ((unsigned)Param1 >= Dlg->ItemCount || !Dlg->Item)
5134 return 0;
5136 // CurItem=&Dlg->Item[Param1];
5137 CurItem = Dlg->Item[Param1];
5138 Type = CurItem->Type;
5139 const wchar_t *Ptr = CurItem->strData;
5141 if (FarIsEdit(Type) && CurItem->ObjPtr)
5142 Ptr = const_cast<const wchar_t *>(((DlgEdit *)(CurItem->ObjPtr))->GetStringAddr());
5144 switch (Msg) {
5145 /*****************************************************************/
5146 case DM_LISTSORT: // Param1=ID Param=Direct {0|1}
5147 case DM_LISTADD: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
5148 case DM_LISTADDSTR: // Param1=ID Param2=String
5149 case DM_LISTDELETE: // Param1=ID Param2=FarListDelete: StartIndex=BeginIndex, Count=количество (<=0 - все!)
5150 case DM_LISTGETITEM: // Param1=ID Param2=FarListGetItem: ItemsNumber=Index, Items=Dest
5151 case DM_LISTSET: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
5152 case DM_LISTGETCURPOS: // Param1=ID Param2=FarListPos
5153 case DM_LISTSETCURPOS: // Param1=ID Param2=FarListPos Ret: RealPos
5154 case DM_LISTUPDATE: // Param1=ID Param2=FarList: ItemsNumber=Index, Items=Src
5155 case DM_LISTINFO: // Param1=ID Param2=FarListInfo
5156 case DM_LISTFINDSTRING: // Param1=ID Param2=FarListFind
5157 case DM_LISTINSERT: // Param1=ID Param2=FarListInsert
5158 case DM_LISTGETDATA: // Param1=ID Param2=Index
5159 case DM_LISTSETDATA: // Param1=ID Param2=FarListItemData
5160 case DM_LISTSETTITLES: // Param1=ID Param2=FarListTitles: TitleLen=strlen(Title), BottomLen=strlen(Bottom)
5161 case DM_LISTGETTITLES: // Param1=ID Param2=FarListTitles: TitleLen=strlen(Title), BottomLen=strlen(Bottom)
5162 case DM_LISTGETDATASIZE: // Param1=ID Param2=Index
5163 case DM_LISTSETMOUSEREACTION: // Param1=ID Param2=FARLISTMOUSEREACTIONTYPE Ret=OldSets
5164 case DM_SETCOMBOBOXEVENT: // Param1=ID Param2=FARCOMBOBOXEVENTTYPE Ret=OldSets
5165 case DM_GETCOMBOBOXEVENT: // Param1=ID Param2=0 Ret=Sets
5167 if (Type == DI_LISTBOX || Type == DI_COMBOBOX) {
5168 VMenu *ListBox = CurItem->ListPtr;
5170 if (ListBox) {
5171 int Ret = TRUE;
5173 switch (Msg) {
5174 case DM_LISTINFO: // Param1=ID Param2=FarListInfo
5176 return ListBox->GetVMenuInfo((FarListInfo *)Param2);
5178 case DM_LISTSORT: // Param1=ID Param=Direct {0|1}
5180 ListBox->SortItems((int)Param2);
5181 break;
5183 case DM_LISTFINDSTRING: // Param1=ID Param2=FarListFind
5185 FarListFind *lf = reinterpret_cast<FarListFind *>(Param2);
5186 return ListBox->FindItem(lf->StartIndex, lf->Pattern, lf->Flags);
5188 case DM_LISTADDSTR: // Param1=ID Param2=String
5190 Ret = ListBox->AddItem((wchar_t *)Param2);
5191 break;
5193 case DM_LISTADD: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
5195 FarList *ListItems = (FarList *)Param2;
5197 if (!ListItems)
5198 return FALSE;
5200 Ret = ListBox->AddItem(ListItems);
5201 break;
5203 case DM_LISTDELETE: // Param1=ID Param2=FarListDelete: StartIndex=BeginIndex, Count=количество (<=0 - все!)
5205 int Count;
5206 FarListDelete *ListItems = (FarListDelete *)Param2;
5208 if (!ListItems || (Count = ListItems->Count) <= 0)
5209 ListBox->DeleteItems();
5210 else
5211 ListBox->DeleteItem(ListItems->StartIndex, Count);
5213 break;
5215 case DM_LISTINSERT: // Param1=ID Param2=FarListInsert
5217 if ((Ret = ListBox->InsertItem((FarListInsert *)Param2)) == -1)
5218 return -1;
5220 break;
5222 case DM_LISTUPDATE: // Param1=ID Param2=FarListUpdate: Index=Index, Items=Src
5224 if (Param2 && ListBox->UpdateItem((FarListUpdate *)Param2))
5225 break;
5227 return FALSE;
5229 case DM_LISTGETITEM: // Param1=ID Param2=FarListGetItem: ItemsNumber=Index, Items=Dest
5231 FarListGetItem *ListItems = (FarListGetItem *)Param2;
5233 if (!ListItems)
5234 return FALSE;
5236 MenuItemEx *ListMenuItem;
5238 if ((ListMenuItem = ListBox->GetItemPtr(ListItems->ItemIndex))) {
5239 // ListItems->ItemIndex=1;
5240 FarListItem *Item = &ListItems->Item;
5241 memset(Item, 0, sizeof(FarListItem));
5242 Item->Flags = ListMenuItem->Flags;
5243 Item->Text = ListMenuItem->strName;
5245 if(ListMenuItem->UserDataSize <= sizeof(DWORD)) //???
5246 Item->UserData=ListMenuItem->UserData;
5248 return TRUE;
5251 return FALSE;
5253 case DM_LISTGETDATA: // Param1=ID Param2=Index
5255 if (Param2 < ListBox->GetItemCount())
5256 return (LONG_PTR)ListBox->GetUserData(nullptr, 0, (int)Param2);
5258 return 0;
5260 case DM_LISTGETDATASIZE: // Param1=ID Param2=Index
5262 if (Param2 < ListBox->GetItemCount())
5263 return ListBox->GetUserDataSize((int)Param2);
5265 return 0;
5267 case DM_LISTSETDATA: // Param1=ID Param2=FarListItemData
5269 FarListItemData *ListItems = (FarListItemData *)Param2;
5271 if (ListItems && ListItems->Index < ListBox->GetItemCount()) {
5272 Ret = ListBox->SetUserData(ListItems->Data, ListItems->DataSize,
5273 ListItems->Index);
5275 if (!Ret && ListBox->GetUserData(nullptr, 0, ListItems->Index))
5276 Ret = sizeof(DWORD);
5278 return Ret;
5281 return 0;
5284 $ 02.12.2001 KM
5285 + Сообщение для добавления в список строк, с удалением
5286 уже существующих, т.с. "чистая" установка
5288 case DM_LISTSET: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
5290 FarList *ListItems = (FarList *)Param2;
5292 if (!ListItems)
5293 return FALSE;
5295 ListBox->DeleteItems();
5296 Ret = ListBox->AddItem(ListItems);
5297 break;
5299 // case DM_LISTINS: // Param1=ID Param2=FarList: ItemsNumber=Index, Items=Dest
5300 case DM_LISTSETTITLES: // Param1=ID Param2=FarListTitles
5302 FarListTitles *ListTitle = (FarListTitles *)Param2;
5303 ListBox->SetTitle(ListTitle->Title);
5304 ListBox->SetBottomTitle(ListTitle->Bottom);
5305 break; // return TRUE;
5307 case DM_LISTGETTITLES: // Param1=ID Param2=FarListTitles
5309 if (Param2) {
5310 FarListTitles *ListTitle = (FarListTitles *)Param2;
5311 FARString strTitle, strBottomTitle;
5312 ListBox->GetTitle(strTitle);
5313 ListBox->GetBottomTitle(strBottomTitle);
5315 if (!strTitle.IsEmpty() || !strBottomTitle.IsEmpty()) {
5316 if (ListTitle->Title && ListTitle->TitleLen)
5317 far_wcsncpy((wchar_t *)ListTitle->Title, strTitle,
5318 ListTitle->TitleLen);
5319 else
5320 ListTitle->TitleLen = (int)strTitle.GetLength() + 1;
5322 if (ListTitle->Bottom && ListTitle->BottomLen)
5323 far_wcsncpy((wchar_t *)ListTitle->Bottom, strBottomTitle,
5324 ListTitle->BottomLen);
5325 else
5326 ListTitle->BottomLen = (int)strBottomTitle.GetLength() + 1;
5328 return TRUE;
5332 return FALSE;
5334 case DM_LISTGETCURPOS: // Param1=ID Param2=FarListPos
5336 return Param2 ? ListBox->GetSelectPos((FarListPos *)Param2)
5337 : ListBox->GetSelectPos();
5339 case DM_LISTSETCURPOS: // Param1=ID Param2=FarListPos Ret: RealPos
5341 /* 26.06.2001 KM Подадим перед изменением позиции об этом сообщение */
5342 int CurListPos = ListBox->GetSelectPos();
5343 Ret = ListBox->SetSelectPos((FarListPos *)Param2);
5345 if (Ret != CurListPos)
5346 if (!Dlg->CallDlgProc(DN_LISTCHANGE, Param1, Ret))
5347 Ret = ListBox->SetSelectPos(CurListPos, 1);
5349 break; // т.к. нужно перерисовать!
5351 case DM_LISTSETMOUSEREACTION: // Param1=ID Param2=FARLISTMOUSEREACTIONTYPE Ret=OldSets
5353 int OldSets = CurItem->IFlags.Flags;
5355 if (Param2 == LMRT_ONLYFOCUS) {
5356 CurItem->IFlags.Clear(DLGIIF_LISTREACTIONNOFOCUS);
5357 CurItem->IFlags.Set(DLGIIF_LISTREACTIONFOCUS);
5358 } else if (Param2 == LMRT_NEVER) {
5359 CurItem->IFlags.Clear(DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS);
5360 // ListBox->ClearFlags(VMENU_MOUSEREACTION);
5361 } else {
5362 CurItem->IFlags.Set(DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS);
5363 // ListBox->SetFlags(VMENU_MOUSEREACTION);
5366 if ((OldSets & (DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS))
5367 == (DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS))
5368 OldSets = LMRT_ALWAYS;
5369 else if (!(OldSets & (DLGIIF_LISTREACTIONNOFOCUS | DLGIIF_LISTREACTIONFOCUS)))
5370 OldSets = LMRT_NEVER;
5371 else
5372 OldSets = LMRT_ONLYFOCUS;
5374 return OldSets;
5376 case DM_GETCOMBOBOXEVENT: // Param1=ID Param2=0 Ret=Sets
5378 return (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTKEY) ? CBET_KEY : 0)
5379 | (CurItem->IFlags.Check(DLGIIF_COMBOBOXEVENTMOUSE) ? CBET_MOUSE : 0);
5381 case DM_SETCOMBOBOXEVENT: // Param1=ID Param2=FARCOMBOBOXEVENTTYPE Ret=OldSets
5383 int OldSets = CurItem->IFlags.Flags;
5384 CurItem->IFlags.Clear(DLGIIF_COMBOBOXEVENTKEY | DLGIIF_COMBOBOXEVENTMOUSE);
5386 if (Param2 & CBET_KEY)
5387 CurItem->IFlags.Set(DLGIIF_COMBOBOXEVENTKEY);
5389 if (Param2 & CBET_MOUSE)
5390 CurItem->IFlags.Set(DLGIIF_COMBOBOXEVENTMOUSE);
5392 return OldSets;
5396 // уточнение для DI_COMBOBOX - здесь еще и DlgEdit нужно корректно заполнить
5397 if (!CurItem->IFlags.Check(DLGIIF_COMBOBOXNOREDRAWEDIT) && Type == DI_COMBOBOX
5398 && CurItem->ObjPtr) {
5399 MenuItemEx *ListMenuItem;
5401 if ((ListMenuItem = ListBox->GetItemPtr(ListBox->GetSelectPos()))) {
5402 if (CurItem->Flags & (DIF_DROPDOWNLIST | DIF_LISTNOAMPERSAND))
5403 ((DlgEdit *)(CurItem->ObjPtr))->SetHiString(ListMenuItem->strName);
5404 else
5405 ((DlgEdit *)(CurItem->ObjPtr))->SetString(ListMenuItem->strName);
5407 ((DlgEdit *)(CurItem->ObjPtr))->Select(-1, -1); // снимаем выделение
5411 if (Dlg->DialogMode.Check(DMODE_SHOW) && ListBox->UpdateRequired()) {
5412 Dlg->ShowDialog(Param1);
5413 ScrBuf.Flush();
5416 return Ret;
5420 return FALSE;
5422 /*****************************************************************/
5423 case DM_SETHISTORY: // Param1 = ID, Param2 = LPSTR HistoryName
5425 if (Type == DI_EDIT || Type == DI_FIXEDIT) {
5426 if (Param2 && *(const wchar_t *)Param2) {
5427 CurItem->Flags|= DIF_HISTORY;
5428 CurItem->strHistory = (const wchar_t *)Param2;
5430 if (Type == DI_EDIT && (CurItem->Flags & DIF_USELASTHISTORY)) {
5431 Dlg->ProcessLastHistory(CurItem, Param1);
5433 } else {
5434 CurItem->Flags&= ~DIF_HISTORY;
5435 CurItem->strHistory.Clear();
5438 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5439 Dlg->ShowDialog(Param1);
5440 ScrBuf.Flush();
5443 return TRUE;
5446 return FALSE;
5448 /*****************************************************************/
5449 case DM_ADDHISTORY: {
5450 if (Param2 && (Type == DI_EDIT || Type == DI_FIXEDIT) && (CurItem->Flags & DIF_HISTORY)) {
5451 return Dlg->AddToEditHistory((const wchar_t *)Param2, CurItem->strHistory);
5454 return FALSE;
5456 /*****************************************************************/
5457 case DM_GETCURSORPOS: {
5458 if (!Param2)
5459 return FALSE;
5461 if (FarIsEdit(Type) && CurItem->ObjPtr) {
5462 ((COORD *)Param2)->X = ((DlgEdit *)(CurItem->ObjPtr))->GetCurPos();
5463 ((COORD *)Param2)->Y = 0;
5464 return TRUE;
5465 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5466 ((COORD *)Param2)->X = CurItem->UCData->CursorPos.X;
5467 ((COORD *)Param2)->Y = CurItem->UCData->CursorPos.Y;
5468 return TRUE;
5471 return FALSE;
5473 /*****************************************************************/
5474 case DM_SETCURSORPOS: {
5475 if (FarIsEdit(Type) && CurItem->ObjPtr && ((COORD *)Param2)->X >= 0) {
5476 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
5477 EditPtr->SetCurPos(((COORD *)Param2)->X);
5478 // EditPtr->Show();
5479 Dlg->ShowDialog(Param1);
5480 return TRUE;
5481 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5483 учтем, что координаты для этого элемента всегда относительные!
5484 и начинаются с 0,0
5486 COORD Coord = *(COORD *)Param2;
5487 Coord.X+= CurItem->X1;
5489 if (Coord.X > CurItem->X2)
5490 Coord.X = CurItem->X2;
5492 Coord.Y+= CurItem->Y1;
5494 if (Coord.Y > CurItem->Y2)
5495 Coord.Y = CurItem->Y2;
5497 // Запомним
5498 CurItem->UCData->CursorPos.X = Coord.X - CurItem->X1;
5499 CurItem->UCData->CursorPos.Y = Coord.Y - CurItem->Y1;
5501 // переместим если надо
5502 if (Dlg->DialogMode.Check(DMODE_SHOW) && Dlg->FocusPos == (unsigned)Param1) {
5503 // что-то одно надо убрать :-)
5504 MoveCursor(Coord.X + Dlg->X1, Coord.Y + Dlg->Y1); // ???
5505 Dlg->ShowDialog(Param1); // ???
5508 return TRUE;
5511 return FALSE;
5513 /*****************************************************************/
5514 case DM_GETEDITPOSITION: {
5515 if (Param2 && FarIsEdit(Type)) {
5516 if (Type == DI_MEMOEDIT) {
5517 // EditorControl(ECTL_GETINFO,(EditorSetPosition *)Param2);
5518 return TRUE;
5519 } else {
5520 EditorSetPosition *esp = (EditorSetPosition *)Param2;
5521 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
5522 esp->CurLine = 0;
5523 esp->CurPos = EditPtr->GetCurPos();
5524 esp->CurTabPos = EditPtr->GetCellCurPos();
5525 esp->TopScreenLine = 0;
5526 esp->LeftPos = EditPtr->GetLeftPos();
5527 esp->Overtype = EditPtr->GetOvertypeMode();
5528 return TRUE;
5532 return FALSE;
5534 /*****************************************************************/
5535 case DM_SETEDITPOSITION: {
5536 if (Param2 && FarIsEdit(Type)) {
5537 if (Type == DI_MEMOEDIT) {
5538 // EditorControl(ECTL_SETPOSITION,(EditorSetPosition *)Param2);
5539 return TRUE;
5540 } else {
5541 EditorSetPosition *esp = (EditorSetPosition *)Param2;
5542 DlgEdit *EditPtr = (DlgEdit *)(CurItem->ObjPtr);
5543 EditPtr->SetCurPos(esp->CurPos);
5544 EditPtr->SetCellCurPos(esp->CurTabPos);
5545 EditPtr->SetLeftPos(esp->LeftPos);
5546 EditPtr->SetOvertypeMode(esp->Overtype);
5547 Dlg->ShowDialog(Param1);
5548 ScrBuf.Flush();
5549 return TRUE;
5553 return FALSE;
5555 /*****************************************************************/
5556 // Param2=0
5557 // Return MAKELONG(Visible,Size)
5558 case DM_GETCURSORSIZE: {
5559 if (FarIsEdit(Type) && CurItem->ObjPtr) {
5560 bool Visible;
5561 DWORD Size;
5562 ((DlgEdit *)(CurItem->ObjPtr))->GetCursorType(Visible, Size);
5563 return MAKELONG(Visible, Size);
5564 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5565 return MAKELONG(CurItem->UCData->CursorVisible, CurItem->UCData->CursorSize);
5568 return FALSE;
5570 /*****************************************************************/
5571 // Param2=MAKELONG(Visible,Size)
5572 // Return MAKELONG(OldVisible,OldSize)
5573 case DM_SETCURSORSIZE: {
5574 bool Visible = false;
5575 DWORD Size = 0;
5577 if (FarIsEdit(Type) && CurItem->ObjPtr) {
5578 ((DlgEdit *)(CurItem->ObjPtr))->GetCursorType(Visible, Size);
5579 ((DlgEdit *)(CurItem->ObjPtr))->SetCursorType(LOWORD(Param2) != 0, HIWORD(Param2));
5580 } else if (Type == DI_USERCONTROL && CurItem->UCData) {
5581 Visible = CurItem->UCData->CursorVisible;
5582 Size = CurItem->UCData->CursorSize;
5583 CurItem->UCData->CursorVisible = LOWORD(Param2) != 0;
5584 CurItem->UCData->CursorSize = HIWORD(Param2);
5585 int CCX = CurItem->UCData->CursorPos.X;
5586 int CCY = CurItem->UCData->CursorPos.Y;
5588 if (Dlg->DialogMode.Check(DMODE_SHOW) && Dlg->FocusPos == (unsigned)Param1 && CCX != -1
5589 && CCY != -1)
5590 SetCursorType(CurItem->UCData->CursorVisible, CurItem->UCData->CursorSize);
5593 return MAKELONG(Visible, Size);
5595 /*****************************************************************/
5596 case DN_LISTCHANGE: {
5597 return Dlg->CallDlgProc(Msg, Param1, Param2);
5599 /*****************************************************************/
5600 case DN_EDITCHANGE: {
5601 FarDialogItem Item;
5603 if (!ConvertItemEx(CVTITEM_TOPLUGIN, &Item, CurItem, 1))
5604 return FALSE; // no memory TODO: may be needed diagnostic
5606 INT_PTR I = 0;
5607 if (CurItem->Type == DI_EDIT || CurItem->Type == DI_COMBOBOX || CurItem->Type == DI_FIXEDIT
5608 || CurItem->Type == DI_PSWEDIT) {
5609 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(false);
5610 const wchar_t *original_PtrData = Item.PtrData;
5611 I = Dlg->CallDlgProc(DN_EDITCHANGE, Param1, (LONG_PTR)&Item);
5612 if (I) {
5613 if (Type == DI_COMBOBOX && CurItem->ListPtr)
5614 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
5616 if (original_PtrData)
5617 free((void *)original_PtrData);
5618 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(true);
5621 return I;
5623 /*****************************************************************/
5624 case DN_BTNCLICK: {
5625 LONG_PTR Ret = Dlg->CallDlgProc(Msg, Param1, Param2);
5627 if (Ret && (CurItem->Flags & DIF_AUTOMATION) && CurItem->AutoCount && CurItem->AutoPtr) {
5628 DialogItemAutomation *Auto = CurItem->AutoPtr;
5629 Param2%= 3;
5631 for (UINT I = 0; I < CurItem->AutoCount; ++I, ++Auto) {
5632 DWORD NewFlags = Dlg->Item[Auto->ID]->Flags;
5633 Dlg->Item[Auto->ID]->Flags =
5634 (NewFlags & (~Auto->Flags[Param2][1])) | Auto->Flags[Param2][0];
5635 // здесь намеренно в обработчик не посылаются эвенты об изменении
5636 // состояния...
5640 return Ret;
5642 /*****************************************************************/
5643 case DM_GETCHECK: {
5644 if (Type == DI_CHECKBOX || Type == DI_RADIOBUTTON)
5645 return CurItem->Selected;
5647 return 0;
5649 /*****************************************************************/
5650 case DM_SET3STATE: {
5651 if (Type == DI_CHECKBOX) {
5652 int OldState = CurItem->Flags & DIF_3STATE ? TRUE : FALSE;
5654 if (Param2)
5655 CurItem->Flags|= DIF_3STATE;
5656 else
5657 CurItem->Flags&= ~DIF_3STATE;
5659 return OldState;
5662 return 0;
5664 /*****************************************************************/
5665 case DM_SETCHECK: {
5666 if (Type == DI_CHECKBOX) {
5667 int Selected = CurItem->Selected;
5669 if (Param2 == BSTATE_TOGGLE)
5670 Param2 = ++Selected;
5672 if (CurItem->Flags & DIF_3STATE)
5673 Param2%= 3;
5674 else
5675 Param2&= 1;
5677 CurItem->Selected = (int)Param2;
5679 if (Selected != (int)Param2 && Dlg->DialogMode.Check(DMODE_SHOW)) {
5680 // автоматизация
5681 if ((CurItem->Flags & DIF_AUTOMATION) && CurItem->AutoCount && CurItem->AutoPtr) {
5682 DialogItemAutomation *Auto = CurItem->AutoPtr;
5683 Param2%= 3;
5685 for (UINT I = 0; I < CurItem->AutoCount; ++I, ++Auto) {
5686 DWORD NewFlags = Dlg->Item[Auto->ID]->Flags;
5687 Dlg->Item[Auto->ID]->Flags =
5688 (NewFlags & (~Auto->Flags[Param2][1])) | Auto->Flags[Param2][0];
5689 // здесь намеренно в обработчик не посылаются эвенты об изменении
5690 // состояния...
5693 Param1 = -1;
5696 Dlg->ShowDialog(Param1);
5697 ScrBuf.Flush();
5700 return Selected;
5701 } else if (Type == DI_RADIOBUTTON) {
5702 Param1 = Dlg->ProcessRadioButton(Param1);
5704 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5705 Dlg->ShowDialog();
5706 ScrBuf.Flush();
5709 return Param1;
5712 return 0;
5714 /*****************************************************************/
5715 case DN_DRAWDLGITEM: {
5716 FarDialogItem Item;
5718 if (!ConvertItemEx(CVTITEM_TOPLUGIN, &Item, CurItem, 1))
5719 return FALSE; // no memory TODO: may be needed diagnostic
5721 INT_PTR I = Dlg->CallDlgProc(Msg, Param1, (LONG_PTR)&Item);
5723 if ((Type == DI_LISTBOX || Type == DI_COMBOBOX) && CurItem->ListPtr)
5724 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
5726 if (Item.PtrData)
5727 free((wchar_t *)Item.PtrData);
5729 return I;
5731 /*****************************************************************/
5732 case DM_SETFOCUS: {
5733 if (!IsItemFocusable(CurItem))
5734 return FALSE;
5736 if (Dlg->FocusPos == (unsigned)Param1) // уже и так установлено все!
5737 return TRUE;
5739 Dlg->ChangeFocus2(Param1);
5741 if (Dlg->FocusPos == (unsigned)Param1) {
5742 Dlg->ShowDialog();
5743 return TRUE;
5746 return FALSE;
5748 /*****************************************************************/
5749 case DM_GETFOCUS: // Получить ID фокуса
5751 return Dlg->FocusPos;
5753 /*****************************************************************/
5754 case DM_GETCONSTTEXTPTR: {
5755 return (LONG_PTR)Ptr;
5757 /*****************************************************************/
5758 case DM_GETTEXTPTR:
5760 if (Param2) {
5761 FarDialogItemData IData = {0, (wchar_t *)Param2};
5762 return SendDlgMessage(hDlg, DM_GETTEXT, Param1, (LONG_PTR)&IData);
5765 /*****************************************************************/
5766 case DM_GETTEXT:
5768 if (Param2) // если здесь nullptr, то это еще один способ получить размер
5770 FarDialogItemData *did = (FarDialogItemData *)Param2;
5771 Len = 0;
5773 switch (Type) {
5774 case DI_MEMOEDIT:
5775 break;
5776 case DI_COMBOBOX:
5777 case DI_EDIT:
5778 case DI_PSWEDIT:
5779 case DI_FIXEDIT:
5781 if (!CurItem->ObjPtr)
5782 break;
5784 Ptr = const_cast<const wchar_t *>(((DlgEdit *)(CurItem->ObjPtr))->GetStringAddr());
5785 case DI_TEXT:
5786 case DI_VTEXT:
5787 case DI_SINGLEBOX:
5788 case DI_DOUBLEBOX:
5789 case DI_CHECKBOX:
5790 case DI_RADIOBUTTON:
5791 case DI_BUTTON:
5792 Len = StrLength(Ptr) + 1;
5794 if (Type == DI_BUTTON) {
5795 if (!(CurItem->Flags & DIF_NOBRACKETS)) {
5796 Ptr+= 2;
5797 Len-= 4;
5799 if (CurItem->Flags & DIF_SETSHIELD) {
5800 Ptr+= 2;
5804 if (!did->PtrLength)
5805 did->PtrLength = Len;
5806 else if (Len > did->PtrLength)
5807 Len = did->PtrLength + 1; // Прибавим 1, чтобы учесть нулевой байт.
5809 if (Len > 0 && did->PtrData) {
5810 wmemmove(did->PtrData, Ptr, Len);
5811 did->PtrData[Len - 1] = 0;
5814 break;
5815 case DI_USERCONTROL:
5816 /*did->PtrLength=CurItem->Ptr.PtrLength; BUGBUG
5817 did->PtrData=(char*)CurItem->Ptr.PtrData;*/
5818 break;
5819 case DI_LISTBOX: {
5820 // if(!CurItem->ListPtr)
5821 // break;
5822 // did->PtrLength=CurItem->ListPtr->GetUserData(did->PtrData,did->PtrLength,-1);
5823 break;
5825 default: // подразумеваем, что остались
5826 did->PtrLength = 0;
5827 break;
5830 return Len - (!Len ? 0 : 1);
5833 // здесь умышленно не ставим return, т.к. хотим получить размер
5834 // следовательно сразу должен идти "case DM_GETTEXTLENGTH"!!!
5835 /*****************************************************************/
5836 case DM_GETTEXTLENGTH: {
5837 switch (Type) {
5838 case DI_BUTTON:
5839 Len = StrLength(Ptr) + 1;
5841 if (!(CurItem->Flags & DIF_NOBRACKETS))
5842 Len-= 4;
5844 break;
5845 case DI_USERCONTROL:
5846 // Len=CurItem->Ptr.PtrLength; BUGBUG
5847 break;
5848 case DI_TEXT:
5849 case DI_VTEXT:
5850 case DI_SINGLEBOX:
5851 case DI_DOUBLEBOX:
5852 case DI_CHECKBOX:
5853 case DI_RADIOBUTTON:
5854 Len = StrLength(Ptr) + 1;
5855 break;
5856 case DI_COMBOBOX:
5857 case DI_EDIT:
5858 case DI_PSWEDIT:
5859 case DI_FIXEDIT:
5860 case DI_MEMOEDIT:
5862 if (CurItem->ObjPtr) {
5863 Len = ((DlgEdit *)(CurItem->ObjPtr))->GetLength() + 1;
5864 break;
5867 case DI_LISTBOX: {
5868 Len = 0;
5869 MenuItemEx *ListMenuItem;
5871 if ((ListMenuItem = CurItem->ListPtr->GetItemPtr(-1))) {
5872 Len = (int)ListMenuItem->strName.GetLength() + 1;
5875 break;
5877 default:
5878 Len = 0;
5879 break;
5882 return Len - (!Len ? 0 : 1);
5884 /*****************************************************************/
5885 case DM_SETTEXTPTR: {
5886 if (!Param2)
5887 return 0;
5889 FarDialogItemData IData = {(size_t)StrLength((wchar_t *)Param2), (wchar_t *)Param2};
5890 return SendDlgMessage(hDlg, DM_SETTEXT, Param1, (LONG_PTR)&IData);
5893 case DM_SETTEXTPTRSILENT: {
5894 if (!Param2)
5895 return 0;
5897 if (CurItem->Type != DI_FIXEDIT && CurItem->Type != DI_EDIT)
5898 return 0;
5900 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(false);
5901 FarDialogItemData IData = {(size_t)StrLength((wchar_t *)Param2), (wchar_t *)Param2};
5902 intptr_t rv = SendDlgMessage(hDlg, DM_SETTEXT, Param1, (LONG_PTR)&IData);
5903 reinterpret_cast<DlgEdit *>(CurItem->ObjPtr)->SetCallbackState(true);
5905 return rv;
5908 /*****************************************************************/
5909 case DM_SETTEXT: {
5910 if (Param2) {
5911 int NeedInit = TRUE;
5912 FarDialogItemData *did = (FarDialogItemData *)Param2;
5914 switch (Type) {
5915 case DI_MEMOEDIT:
5916 break;
5917 case DI_COMBOBOX:
5918 case DI_EDIT:
5919 case DI_TEXT:
5920 case DI_VTEXT:
5921 case DI_SINGLEBOX:
5922 case DI_DOUBLEBOX:
5923 case DI_BUTTON:
5924 case DI_CHECKBOX:
5925 case DI_RADIOBUTTON:
5926 case DI_PSWEDIT:
5927 case DI_FIXEDIT:
5928 case DI_LISTBOX: // меняет только текущий итем
5929 CurItem->strData = did->PtrData;
5930 Len = (int)CurItem->strData.GetLength();
5931 break;
5932 default:
5933 Len = 0;
5934 break;
5937 switch (Type) {
5938 case DI_USERCONTROL:
5939 /*CurItem->Ptr.PtrLength=did->PtrLength;
5940 CurItem->Ptr.PtrData=did->PtrData;
5941 return CurItem->Ptr.PtrLength;*/
5942 return 0; // BUGBUG
5943 case DI_TEXT:
5944 case DI_VTEXT:
5945 case DI_SINGLEBOX:
5946 case DI_DOUBLEBOX:
5948 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
5949 if (!Dlg->DialogMode.Check(DMODE_KEEPCONSOLETITLE))
5950 ConsoleTitle::SetFarTitle(Dlg->GetDialogTitle());
5951 Dlg->ShowDialog(Param1);
5952 ScrBuf.Flush();
5955 return Len - (!Len ? 0 : 1);
5956 case DI_BUTTON:
5957 case DI_CHECKBOX:
5958 case DI_RADIOBUTTON:
5959 break;
5960 case DI_MEMOEDIT:
5961 break;
5962 case DI_COMBOBOX:
5963 case DI_EDIT:
5964 case DI_PSWEDIT:
5965 case DI_FIXEDIT:
5966 NeedInit = FALSE;
5968 if (CurItem->ObjPtr) {
5969 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
5970 int ReadOnly = EditLine->GetReadOnly();
5971 EditLine->SetReadOnly(0);
5972 EditLine->DisableAC();
5973 EditLine->SetString(CurItem->strData);
5974 EditLine->RevertAC();
5975 EditLine->SetReadOnly(ReadOnly);
5977 if (Dlg->DialogMode.Check(DMODE_INITOBJECTS)) // не меняем клеар-флаг, пока не проиницализировались
5978 EditLine->SetClearFlag(0);
5980 EditLine->Select(-1, 0); // снимаем выделение
5981 // ...оно уже снимается в DlgEdit::SetString()
5984 break;
5985 case DI_LISTBOX: // меняет только текущий итем
5987 VMenu *ListBox = CurItem->ListPtr;
5989 if (ListBox) {
5990 FarListUpdate LUpdate;
5991 LUpdate.Index = ListBox->GetSelectPos();
5992 MenuItemEx *ListMenuItem = ListBox->GetItemPtr(LUpdate.Index);
5994 if (ListMenuItem) {
5995 LUpdate.Item.Flags = ListMenuItem->Flags;
5996 LUpdate.Item.Text = Ptr;
5997 SendDlgMessage(hDlg, DM_LISTUPDATE, Param1, (LONG_PTR)&LUpdate);
6000 break;
6001 } else
6002 return 0;
6004 default: // подразумеваем, что остались
6005 return 0;
6008 if (NeedInit)
6009 Dlg->InitDialogObjects(Param1); // переинициализируем элементы диалога
6011 if (Dlg->DialogMode.Check(DMODE_SHOW)) // достаточно ли этого????!!!!
6013 Dlg->ShowDialog(Param1);
6014 ScrBuf.Flush();
6017 // CurItem->strData = did->PtrData;
6018 return CurItem->strData.GetLength(); //???
6021 return 0;
6023 /*****************************************************************/
6024 case DM_SETMAXTEXTLENGTH: {
6025 if ((Type == DI_EDIT || Type == DI_PSWEDIT
6026 || (Type == DI_COMBOBOX && !(CurItem->Flags & DIF_DROPDOWNLIST)))
6027 && CurItem->ObjPtr) {
6028 int MaxLen = ((DlgEdit *)(CurItem->ObjPtr))->GetMaxLength();
6029 // BugZ#628 - Неправильная длина редактируемого текста.
6030 ((DlgEdit *)(CurItem->ObjPtr))->SetMaxLength((int)Param2);
6031 // if (DialogMode.Check(DMODE_INITOBJECTS)) //???
6032 Dlg->InitDialogObjects(Param1); // переинициализируем элементы диалога
6033 if (!Dlg->DialogMode.Check(DMODE_KEEPCONSOLETITLE))
6034 ConsoleTitle::SetFarTitle(Dlg->GetDialogTitle());
6035 return MaxLen;
6038 return 0;
6040 /*****************************************************************/
6041 case DM_GETDLGITEM: {
6042 FarDialogItem *Item = (FarDialogItem *)Param2;
6043 return (LONG_PTR)ConvertItemEx2(Item, CurItem);
6045 /*****************************************************************/
6046 case DM_GETDLGITEMSHORT: {
6047 if (Param2 && ConvertItemEx(CVTITEM_TOPLUGINSHORT, (FarDialogItem *)Param2, CurItem, 1))
6048 return TRUE;
6049 return FALSE;
6051 /*****************************************************************/
6052 case DM_SETDLGITEM:
6053 case DM_SETDLGITEMSHORT: {
6054 if (!Param2)
6055 return FALSE;
6057 if (Type != ((FarDialogItem *)Param2)->Type) // пока нефига менять тип
6058 return FALSE;
6060 // не менять
6061 if (!ConvertItemEx((Msg == DM_SETDLGITEM) ? CVTITEM_FROMPLUGIN : CVTITEM_FROMPLUGINSHORT,
6062 (FarDialogItem *)Param2, CurItem, 1))
6063 return FALSE; // invalid parameters
6065 CurItem->Type = Type;
6067 if ((Type == DI_LISTBOX || Type == DI_COMBOBOX) && CurItem->ListPtr)
6068 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
6070 // еще разок, т.к. данные могли быть изменены
6071 Dlg->InitDialogObjects(Param1);
6072 if (!Dlg->DialogMode.Check(DMODE_KEEPCONSOLETITLE))
6073 ConsoleTitle::SetFarTitle(Dlg->GetDialogTitle());
6075 if (Dlg->DialogMode.Check(DMODE_SHOW)) {
6076 Dlg->ShowDialog(Param1);
6077 ScrBuf.Flush();
6080 return TRUE;
6082 /*****************************************************************/
6084 $ 03.01.2001 SVS
6085 + показать/скрыть элемент
6086 Param2:
6087 -1 - получить состояние
6088 0 - погасить
6089 1 - показать
6090 Return: предыдущее состояние
6092 case DM_SHOWITEM: {
6093 DWORD PrevFlags = CurItem->Flags;
6095 if (Param2 != -1) {
6096 if (Param2)
6097 CurItem->Flags&= ~DIF_HIDDEN;
6098 else
6099 CurItem->Flags|= DIF_HIDDEN;
6101 if (Dlg->DialogMode.Check(DMODE_SHOW)) // && (PrevFlags&DIF_HIDDEN) != (CurItem->Flags&DIF_HIDDEN))//!(CurItem->Flags&DIF_HIDDEN))
6103 if ((CurItem->Flags & DIF_HIDDEN) && Dlg->FocusPos == (unsigned)Param1) {
6104 Param2 = Dlg->ChangeFocus(Param1, 1, TRUE);
6105 Dlg->ChangeFocus2((int)Param2);
6108 // Либо все, либо... только 1
6109 Dlg->ShowDialog(Dlg->GetDropDownOpened() || (CurItem->Flags & DIF_HIDDEN) ? -1 : Param1);
6110 ScrBuf.Flush();
6114 return (PrevFlags & DIF_HIDDEN) ? FALSE : TRUE;
6116 /*****************************************************************/
6117 case DM_SETDROPDOWNOPENED: // Param1=ID; Param2={TRUE|FALSE}
6119 if (!Param2) // Закрываем любой открытый комбобокс или историю
6121 if (Dlg->GetDropDownOpened()) {
6122 Dlg->SetDropDownOpened(FALSE);
6123 WINPORT(Sleep)(10);
6126 return TRUE;
6129 $ 09.12.2001 DJ
6130 у DI_PSWEDIT не бывает хистори!
6132 else if (Param2
6133 && (Type == DI_COMBOBOX
6134 || ((Type == DI_EDIT || Type == DI_FIXEDIT) && (CurItem->Flags & DIF_HISTORY)))) /* DJ $ */
6136 // Открываем заданный в Param1 комбобокс или историю
6137 if (Dlg->GetDropDownOpened()) {
6138 Dlg->SetDropDownOpened(FALSE);
6139 WINPORT(Sleep)(10);
6142 if (SendDlgMessage(hDlg, DM_SETFOCUS, Param1, 0)) {
6143 Dlg->ProcessOpenComboBox(Type, CurItem, Param1); //?? Param1 ??
6144 // Dlg->ProcessKey(KEY_CTRLDOWN);
6145 return TRUE;
6146 } else
6147 return FALSE;
6150 return FALSE;
6152 /* KM $ */
6153 /*****************************************************************/
6154 case DM_SETITEMPOSITION: // Param1 = ID; Param2 = SMALL_RECT
6156 return Dlg->SetItemRect((int)Param1, (SMALL_RECT *)Param2);
6158 /*****************************************************************/
6160 $ 31.08.2000 SVS
6161 + переключение/получение состояния Enable/Disable элемента
6163 case DM_ENABLE: {
6164 DWORD PrevFlags = CurItem->Flags;
6166 if (Param2 != -1) {
6167 if (Param2)
6168 CurItem->Flags&= ~DIF_DISABLE;
6169 else
6170 CurItem->Flags|= DIF_DISABLE;
6172 if ((Type == DI_LISTBOX || Type == DI_COMBOBOX) && CurItem->ListPtr)
6173 CurItem->ListPtr->ChangeFlags(VMENU_DISABLED, CurItem->Flags & DIF_DISABLE);
6176 if (Dlg->DialogMode.Check(DMODE_SHOW)) //???
6178 Dlg->ShowDialog(Param1);
6179 ScrBuf.Flush();
6182 return (PrevFlags & DIF_DISABLE) ? FALSE : TRUE;
6185 //* `DM_SETREADONLY` - changes readonly-ness of selected dialog edit control item
6186 //* `DM_GETCOLOR` - retrieves current color attributes of selected dialog item
6187 //* `DM_SETCOLOR` - changes current color attributes of selected dialog item
6188 //* `DM_SETTRUECOLOR` - sets 24-bit RGB colors to selected dialog item, can be used within DN_CTLCOLORDLGITEM handler to provide extra coloring.
6189 //* `DM_GETTRUECOLOR` - retrieves 24-bit RGB colors of selected dialog item, if they were set before by DM_SETTRUECOLOR.
6190 //* `ECTL_ADDTRUECOLOR` - applies coloring to editor like ECTL_ADDCOLOR does but allows to specify 24 RGB color using EditorTrueColor structure.
6191 //* `ECTL_GETTRUECOLOR` - retrieves coloring of editor like ECTL_GETCOLOR does but gets 24 RGB color using EditorTrueColor structure.
6194 // case DM_GETCOLOR: {
6195 // *(DWORD *)Param2 = (DWORD)Dlg->CtlColorDlgItem(Param1, CurItem);
6196 // *(DWORD *)Param2|= (CurItem->Flags & DIF_SETCOLOR);
6197 // return TRUE;
6198 // }
6200 // case DM_SETCOLOR: {
6201 // CurItem->Flags&= ~(DIF_SETCOLOR | DIF_COLORMASK);
6202 // CurItem->Flags|= Param2 & (DIF_SETCOLOR | DIF_COLORMASK);
6203 // if (Dlg->DialogMode.Check(DMODE_SHOW)) { //???
6204 // Dlg->ShowDialog(Param1);
6205 // ScrBuf.Flush();
6206 // }
6207 // return TRUE;
6208 // }
6210 case DM_GETDEFAULTCOLOR: {
6211 if (Param2)
6212 Dlg->CtlColorDlgItem(Param1, CurItem, (uint64_t *)Param2);
6214 return TRUE;
6217 ///case DM_GETCOLOR:///
6218 case DM_GETTRUECOLOR: {
6219 if (Param2)
6220 memcpy((uint64_t *)Param2, CurItem->customItemColor, sizeof(uint64_t) * 4);
6221 // if (!CurItem->TrueColors) {
6222 // memset((uint64_t *)Param2, 0, sizeof(DialogItemTrueColors));
6223 // } else {
6224 // *(DialogItemTrueColors *)Param2 = *CurItem->TrueColors;
6225 // }
6226 // Param2 = CurItem->customItemColor
6228 return TRUE;
6231 ///case DM_SETCOLOR:///
6232 case DM_SETTRUECOLOR: {
6233 if (Param2)
6234 memcpy(CurItem->customItemColor, (uint64_t *)Param2, sizeof(uint64_t) * 4);
6236 // if (!CurItem->TrueColors) {
6237 // CurItem->TrueColors.reset(new DialogItemTrueColors);
6238 // }
6239 // *CurItem->TrueColors = *(const DialogItemTrueColors *)Param2;
6241 if (Dlg->InCtlColorDlgItem == 0 && Dlg->DialogMode.Check(DMODE_SHOW)) { //???
6242 Dlg->ShowDialog(Param1);
6243 ScrBuf.Flush();
6245 return TRUE;
6248 case DM_SETREADONLY: {
6249 if (Param2) {
6250 CurItem->Flags|= DIF_READONLY;
6251 } else {
6252 CurItem->Flags&= ~DIF_READONLY;
6254 if (FarIsEdit(Type)) {
6255 DlgEdit *CurItemEdit = (DlgEdit *)CurItem->ObjPtr;
6256 if (CurItemEdit) {
6257 CurItemEdit->SetReadOnly(Param2 ? 1 : 0);
6259 } else {
6260 fprintf(stderr,
6261 "%s: DM_SETREADONLY invoked for non-edit item %u\n",
6262 __FUNCTION__, Param1);
6264 if (Dlg->DialogMode.Check(DMODE_SHOW)) { //???
6265 Dlg->ShowDialog(Param1);
6266 ScrBuf.Flush();
6268 return TRUE;
6271 /*****************************************************************/
6272 // получить позицию и размеры контрола
6273 case DM_GETITEMPOSITION: // Param1=ID, Param2=*SMALL_RECT
6275 if (Param2) {
6276 SMALL_RECT Rect;
6277 if (Dlg->GetItemRect(Param1, Rect)) {
6278 *reinterpret_cast<PSMALL_RECT>(Param2) = Rect;
6279 return TRUE;
6283 return FALSE;
6284 /*****************************************************************/
6285 case DM_SETITEMDATA: {
6286 LONG_PTR PrewDataDialog = CurItem->UserData;
6287 CurItem->UserData = Param2;
6288 return PrewDataDialog;
6290 /*****************************************************************/
6291 case DM_GETITEMDATA: {
6292 return CurItem->UserData;
6294 /*****************************************************************/
6295 case DM_EDITUNCHANGEDFLAG: // -1 Get, 0 - Skip, 1 - Set; Выделение блока снимается.
6297 if (FarIsEdit(Type)) {
6298 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
6299 int ClearFlag = EditLine->GetClearFlag();
6301 if (Param2 >= 0) {
6302 EditLine->SetClearFlag((int)Param2);
6303 EditLine->Select(-1, 0); // снимаем выделение
6305 if (Dlg->DialogMode.Check(DMODE_SHOW)) //???
6307 Dlg->ShowDialog(Param1);
6308 ScrBuf.Flush();
6312 return ClearFlag;
6315 break;
6317 /*****************************************************************/
6318 case DM_GETSELECTION: // Msg=DM_GETSELECTION, Param1=ID, Param2=*EditorSelect
6319 case DM_SETSELECTION: // Msg=DM_SETSELECTION, Param1=ID, Param2=*EditorSelect
6321 if (FarIsEdit(Type) && Param2) {
6322 if (Msg == DM_GETSELECTION) {
6323 EditorSelect *EdSel = (EditorSelect *)Param2;
6324 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
6325 EdSel->BlockStartLine = 0;
6326 EdSel->BlockHeight = 1;
6327 EditLine->GetSelection(EdSel->BlockStartPos, EdSel->BlockWidth);
6329 if (EdSel->BlockStartPos == -1 && !EdSel->BlockWidth)
6330 EdSel->BlockType = BTYPE_NONE;
6331 else {
6332 EdSel->BlockType = BTYPE_STREAM;
6333 EdSel->BlockWidth-= EdSel->BlockStartPos;
6336 return TRUE;
6337 } else {
6338 if (Param2) {
6339 EditorSelect *EdSel = (EditorSelect *)Param2;
6340 DlgEdit *EditLine = (DlgEdit *)(CurItem->ObjPtr);
6342 // EdSel->BlockType=BTYPE_STREAM;
6343 // EdSel->BlockStartLine=0;
6344 // EdSel->BlockHeight=1;
6345 if (EdSel->BlockType == BTYPE_NONE)
6346 EditLine->Select(-1, 0);
6347 else
6348 EditLine->Select(EdSel->BlockStartPos, EdSel->BlockStartPos + EdSel->BlockWidth);
6350 if (Dlg->DialogMode.Check(DMODE_SHOW)) //???
6352 Dlg->ShowDialog(Param1);
6353 ScrBuf.Flush();
6356 return TRUE;
6361 break;
6365 // Все, что сами не отрабатываем - посылаем на обработку обработчику.
6366 return Dlg->CallDlgProc(Msg, Param1, Param2);
6370 $ 28.07.2000 SVS
6371 Посылка сообщения диалогу
6372 Некоторые сообщения эта функция обрабатывает сама, не передавая управление
6373 обработчику диалога.
6375 LONG_PTR WINAPI SendDlgMessage(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2)
6377 if (!hDlg)
6378 return 0;
6380 return InterThreadCall<LONG_PTR, 0>(std::bind(SendDlgMessageSynched, hDlg, Msg, Param1, Param2));
6383 void Dialog::SetPosition(int X1, int Y1, int X2, int Y2)
6385 CriticalSectionLock Lock(CS);
6387 if (X1 >= 0)
6388 RealWidth = X2 - X1 + 1;
6389 else
6390 RealWidth = X2;
6392 if (Y1 >= 0)
6393 RealHeight = Y2 - Y1 + 1;
6394 else
6395 RealHeight = Y2;
6397 ScreenObject::SetPosition(X1, Y1, X2, Y2);
6399 //////////////////////////////////////////////////////////////////////////
6400 BOOL Dialog::IsInited()
6402 CriticalSectionLock Lock(CS);
6403 return DialogMode.Check(DMODE_INITOBJECTS);
6406 void Dialog::SetComboBoxPos(DialogItemEx *CurItem)
6408 if (GetDropDownOpened()) {
6409 if (!CurItem) {
6410 CurItem = Item[FocusPos];
6412 int EditX1, EditY1, EditX2, EditY2;
6413 ((DlgEdit *)CurItem->ObjPtr)->GetPosition(EditX1, EditY1, EditX2, EditY2);
6415 if (EditX2 - EditX1 < 20)
6416 EditX2 = EditX1 + 20;
6418 if (ScrY - EditY1 < Min(Opt.Dialogs.CBoxMaxHeight, CurItem->ListPtr->GetItemCount()) + 2
6419 && EditY1 > ScrY / 2)
6420 CurItem->ListPtr->SetPosition(EditX1,
6421 Max(0, EditY1 - 1 - Min(Opt.Dialogs.CBoxMaxHeight, CurItem->ListPtr->GetItemCount()) - 1),
6422 EditX2, EditY1 - 1);
6423 else
6424 CurItem->ListPtr->SetPosition(EditX1, EditY1 + 1, EditX2, 0);
6428 bool Dialog::ProcessEvents()
6430 return !DialogMode.Check(DMODE_ENDLOOP);
6433 void Dialog::SetId(const GUID &Id)
6435 this->Id = Id;
6436 IdExist = true;