7 Copyright (c) 1996 Eugene Roshal
8 Copyright (c) 2000 Far Group
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
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"
38 #include "keyboard.hpp"
39 #include "macroopcode.hpp"
41 #include "ctrlobj.hpp"
42 #include "chgprior.hpp"
44 #include "dlgedit.hpp"
47 #include "manager.hpp"
48 #include "savescr.hpp"
49 #include "constitle.hpp"
50 #include "lockscrn.hpp"
51 #include "TPreRedrawFunc.hpp"
54 #include "palette.hpp"
55 #include "message.hpp"
57 #include "history.hpp"
58 #include "InterThreadCall.hpp"
59 #include <VT256ColorTable.h>
63 #define VTEXT_ADN_SEPARATORS 1
65 // Флаги для функции ConvertItem
69 CVTITEM_FROMPLUGIN
= 1,
70 CVTITEM_TOPLUGINSHORT
= 2,
71 CVTITEM_FROMPLUGINSHORT
= 3
76 DLGEDITLINE_CLEARSELONKILLFOCUS
= 0x00000001, // управляет выделением блока при потере фокуса ввода
77 DLGEDITLINE_SELALLGOTFOCUS
= 0x00000002, // управляет выделением блока при получении фокуса ввода
78 DLGEDITLINE_NOTSELONGOTFOCUS
= 0x00000004, // не восстанавливать выделение строки редактирования при получении фокуса ввода
79 DLGEDITLINE_NEWSELONGOTFOCUS
= 0x00000008, // управляет процессом выделения блока при получении фокуса
80 DLGEDITLINE_GOTOEOLGOTFOCUS
= 0x00000010, // при получении фокуса ввода переместить курсор в конец строки
83 enum DLGITEMINTERNALFLAGS
85 DLGIIF_LISTREACTIONFOCUS
= 0x00000001, // MouseReaction для фокусного элемента
86 DLGIIF_LISTREACTIONNOFOCUS
= 0x00000002, // MouseReaction для не фокусного элемента
88 DLGIIF_COMBOBOXNOREDRAWEDIT
= 0x00000008, // не прорисовывать строку редактирования при изменениях в комбо
89 DLGIIF_COMBOBOXEVENTKEY
= 0x00000010, // посылать события клавиатуры в диалоговую проц. для открытого комбобокса
90 DLGIIF_COMBOBOXEVENTMOUSE
= 0x00000020, // посылать события мыши в диалоговую проц. для открытого комбобокса
93 const wchar_t *fmtSavedDialogHistory
= L
"SavedDialogHistory/";
95 //////////////////////////////////////////////////////////////////////////
97 Функция, определяющая - "Может ли элемент диалога иметь фокус ввода"
99 static inline bool CanGetFocus(int Type
)
118 bool IsKeyHighlighted(const wchar_t *Str
, FarKey Key
, int Translate
, int AmpPos
)
121 if (!(Str
= wcschr(Str
, L
'&')))
126 if (AmpPos
>= StrLength(Str
))
132 if (Str
[AmpPos
] == L
'&')
136 wchar_t UpperStrKey
= Upper(Str
[AmpPos
]);
138 if (WCHAR_IS_VALID(Key
)) {
139 return UpperStrKey
== Upper(Key
) || (Translate
&& KeyToKeyLayoutCompare(Upper(Key
), UpperStrKey
));
143 uint32_t AltKey
= Key
& (~KEY_ALT
);
145 if (WCHAR_IS_VALID(AltKey
)) {
146 if (iswdigit(AltKey
) != 0)
147 return (AltKey
== (uint32_t)UpperStrKey
);
150 // (AltKey=='-' || AltKey=='/' || AltKey==',' || AltKey=='.' ||
151 // AltKey=='\\' || AltKey=='=' || AltKey=='[' || AltKey==']' ||
152 // AltKey==':' || AltKey=='"' || AltKey=='~'))
154 return (UpperStrKey
== Upper(AltKey
)
155 || (Translate
&& KeyToKeyLayoutCompare(AltKey
, UpperStrKey
)));
163 void DialogItemExToDialogItemEx(DialogItemEx
*pSrc
, DialogItemEx
*pDest
)
165 pDest
->Type
= pSrc
->Type
;
166 pDest
->X1
= pSrc
->X1
;
167 pDest
->Y1
= pSrc
->Y1
;
168 pDest
->X2
= pSrc
->X2
;
169 pDest
->Y2
= pSrc
->Y2
;
170 pDest
->Focus
= pSrc
->Focus
;
171 pDest
->Reserved
= pSrc
->Reserved
;
172 pDest
->strHistory
= pSrc
->strHistory
;
173 pDest
->strMask
= pSrc
->strMask
;
174 pDest
->Flags
= pSrc
->Flags
;
175 pDest
->DefaultButton
= pSrc
->DefaultButton
;
176 pDest
->nMaxLength
= 0;
177 pDest
->strData
= pSrc
->strData
;
178 pDest
->ID
= pSrc
->ID
;
179 pDest
->IFlags
= pSrc
->IFlags
;
180 pDest
->AutoCount
= pSrc
->AutoCount
;
181 pDest
->AutoPtr
= pSrc
->AutoPtr
;
182 pDest
->UserData
= pSrc
->UserData
;
183 pDest
->ObjPtr
= pSrc
->ObjPtr
;
184 pDest
->ListPtr
= pSrc
->ListPtr
;
185 pDest
->UCData
= pSrc
->UCData
;
186 pDest
->SelStart
= pSrc
->SelStart
;
187 pDest
->SelEnd
= pSrc
->SelEnd
;
190 void ConvertItemSmall(FarDialogItem
*Item
, DialogItemEx
*Data
)
192 Item
->Type
= Data
->Type
;
197 Item
->Focus
= Data
->Focus
;
198 Item
->Flags
= Data
->Flags
;
199 Item
->DefaultButton
= Data
->DefaultButton
;
200 Item
->MaxLen
= Data
->nMaxLength
;
201 Item
->PtrData
= nullptr;
203 Item
->Param
.History
= nullptr;
204 if (Data
->Type
== DI_LISTBOX
|| Data
->Type
== DI_COMBOBOX
) {
205 Item
->Param
.ListPos
= Data
->ListPtr
? Data
->ListPtr
->GetSelectPos() : 0;
207 if ((Data
->Type
== DI_EDIT
|| Data
->Type
== DI_FIXEDIT
) && Data
->Flags
& DIF_HISTORY
) {
208 Item
->Param
.History
= Data
->strHistory
;
209 } else if (Data
->Type
== DI_FIXEDIT
&& Data
->Flags
& DIF_MASKEDIT
) {
210 Item
->Param
.Mask
= Data
->strMask
;
212 Item
->Param
.Reserved
= Data
->Reserved
;
216 size_t ItemStringAndSize(DialogItemEx
*Data
, FARString
&ItemString
)
219 if (FarIsEdit(Data
->Type
) && (EditPtr
= (DlgEdit
*)(Data
->ObjPtr
)) != nullptr)
220 EditPtr
->GetString(ItemString
);
222 ItemString
= Data
->strData
;
224 size_t sz
= ItemString
.GetLength();
226 if (sz
> Data
->nMaxLength
&& Data
->nMaxLength
> 0)
227 sz
= Data
->nMaxLength
;
232 bool ConvertItemEx(CVTITEMFLAGS FromPlugin
, FarDialogItem
*Item
, DialogItemEx
*Data
, unsigned Count
)
239 switch (FromPlugin
) {
240 case CVTITEM_TOPLUGIN
:
241 case CVTITEM_TOPLUGINSHORT
:
243 for (I
= 0; I
< Count
; I
++, ++Item
, ++Data
) {
244 ConvertItemSmall(Item
, Data
);
246 if (FromPlugin
== CVTITEM_TOPLUGIN
) {
248 size_t sz
= ItemStringAndSize(Data
, str
);
250 wchar_t *p
= (wchar_t *)malloc((sz
+ 1) * sizeof(wchar_t));
253 if (!p
) // TODO: may be needed message?
256 wmemcpy(p
, str
.CPtr(), sz
);
263 case CVTITEM_FROMPLUGIN
:
264 case CVTITEM_FROMPLUGINSHORT
:
266 for (I
= 0; I
< Count
; I
++, ++Item
, ++Data
) {
271 Data
->Focus
= Item
->Focus
;
273 if ((Item
->Type
== DI_EDIT
|| Item
->Type
== DI_FIXEDIT
) && Item
->Flags
& DIF_HISTORY
) {
274 Data
->strHistory
= Item
->Param
.History
;
275 } else if (Item
->Type
== DI_FIXEDIT
&& Item
->Flags
& DIF_MASKEDIT
) {
276 Data
->strMask
= Item
->Param
.Mask
;
278 Data
->Reserved
= Item
->Param
.Reserved
;
280 Data
->Flags
= Item
->Flags
;
281 Data
->DefaultButton
= Item
->DefaultButton
;
282 Data
->Type
= Item
->Type
;
284 if (FromPlugin
== CVTITEM_FROMPLUGIN
) {
285 Data
->strData
= Item
->PtrData
;
286 Data
->nMaxLength
= Item
->MaxLen
;
288 if (Data
->nMaxLength
> 0)
289 Data
->strData
.Truncate(Data
->nMaxLength
);
292 Data
->ListItems
= Item
->Param
.ListItems
;
294 if (Data
->X2
< Data
->X1
)
297 if (Data
->Y2
< Data
->Y1
)
300 if ((Data
->Type
== DI_COMBOBOX
|| Data
->Type
== DI_LISTBOX
) && !IsPtr(Item
->Param
.ListItems
))
301 Data
->ListItems
= nullptr;
310 size_t ConvertItemEx2(FarDialogItem
*Item
, DialogItemEx
*Data
)
312 size_t size
= sizeof(*Item
);
314 size_t sz
= ItemStringAndSize(Data
, str
);
315 size
+= (sz
+ 1) * sizeof(wchar_t);
318 ConvertItemSmall(Item
, Data
);
320 wchar_t *p
= (wchar_t *)(Item
+ 1);
322 wmemcpy(p
, str
.CPtr(), sz
);
329 void DataToItemEx(const DialogDataEx
*Data
, DialogItemEx
*Item
, int Count
)
334 for (int i
= 0; i
< Count
; i
++) {
336 Item
[i
].ID
= static_cast<WORD
>(i
);
337 Item
[i
].Type
= Data
[i
].Type
;
338 Item
[i
].X1
= Data
[i
].X1
;
339 Item
[i
].Y1
= Data
[i
].Y1
;
340 Item
[i
].X2
= Data
[i
].X2
;
341 Item
[i
].Y2
= Data
[i
].Y2
;
343 if (Item
[i
].X2
< Item
[i
].X1
)
344 Item
[i
].X2
= Item
[i
].X1
;
346 if (Item
[i
].Y2
< Item
[i
].Y1
)
347 Item
[i
].Y2
= Item
[i
].Y1
;
350 Item
[i
].Type
!= DI_SINGLEBOX
&& Item
[i
].Type
!= DI_DOUBLEBOX
&& (Data
[i
].Flags
& DIF_FOCUS
);
351 if ((Data
[i
].Type
== DI_EDIT
|| Data
[i
].Type
== DI_FIXEDIT
) && Data
[i
].Flags
& DIF_HISTORY
) {
352 Item
[i
].strHistory
= Data
[i
].History
;
353 } else if (Data
[i
].Type
== DI_FIXEDIT
&& Data
[i
].Flags
& DIF_MASKEDIT
) {
354 Item
[i
].strMask
= Data
[i
].Mask
;
356 Item
[i
].Reserved
= Data
[i
].Reserved
;
358 Item
[i
].Flags
= Data
[i
].Flags
;
359 Item
[i
].DefaultButton
=
360 Item
[i
].Type
!= DI_TEXT
&& Item
[i
].Type
!= DI_VTEXT
&& (Data
[i
].Flags
& DIF_DEFAULT
);
361 Item
[i
].SelStart
= -1;
363 if (!IsPtr(Data
[i
].Data
)) // awful
364 Item
[i
].strData
= FarLangMsg
{(int)(DWORD_PTR
)Data
[i
].Data
};
366 Item
[i
].strData
= Data
[i
].Data
;
370 Dialog::Dialog(DialogItemEx
*SrcItem
, // Набор элементов диалога
371 unsigned SrcItemCount
, // Количество элементов
372 FARWINDOWPROC DlgProc
, // Диалоговая процедура
373 LONG_PTR InitParam
) // Ассоцированные с диалогом данные
377 Dialog::Item
= (DialogItemEx
**)malloc(sizeof(DialogItemEx
*) * SrcItemCount
);
379 for (unsigned i
= 0; i
< SrcItemCount
; i
++) {
380 Dialog::Item
[i
] = new DialogItemEx
;
381 Dialog::Item
[i
]->Clear();
382 DialogItemExToDialogItemEx(&SrcItem
[i
], Dialog::Item
[i
]);
385 Dialog::ItemCount
= SrcItemCount
;
386 Dialog::pSaveItemEx
= SrcItem
;
387 Init(DlgProc
, InitParam
);
390 Dialog::Dialog(FarDialogItem
*SrcItem
, // Набор элементов диалога
391 unsigned SrcItemCount
, // Количество элементов
392 FARWINDOWPROC DlgProc
, // Диалоговая процедура
393 LONG_PTR InitParam
) // Ассоцированные с диалогом данные
397 Dialog::Item
= (DialogItemEx
**)malloc(sizeof(DialogItemEx
*) * SrcItemCount
);
399 for (unsigned i
= 0; i
< SrcItemCount
; i
++) {
400 Dialog::Item
[i
] = new DialogItemEx
;
401 Dialog::Item
[i
]->Clear();
402 // BUGBUG add error check
403 ConvertItemEx(CVTITEM_FROMPLUGIN
, &SrcItem
[i
], Dialog::Item
[i
], 1);
406 Dialog::ItemCount
= SrcItemCount
;
407 Dialog::pSaveItemEx
= nullptr;
408 Init(DlgProc
, InitParam
);
411 void Dialog::Init(FARWINDOWPROC DlgProc
, // Диалоговая процедура
412 LONG_PTR InitParam
) // Ассоцированные с диалогом данные
414 SetDynamicallyBorn(FALSE
); // $OT: По умолчанию все диалоги создаются статически
415 CanLoseFocus
= FALSE
;
417 // Номер плагина, вызвавшего диалог (-1 = Main)
419 Dialog::DataDialog
= InitParam
;
420 DialogMode
.Set(DMODE_ISCANMOVE
);
421 SetDropDownOpened(FALSE
);
423 InCtlColorDlgItem
= 0;
424 FocusPos
= (unsigned)-1;
425 PrevFocusPos
= (unsigned)-1;
427 if (!DlgProc
) // функция должна быть всегда!!!
429 DlgProc
= DefDlgProc
;
430 // знать диалог в старом стиле - учтем этот факт!
431 DialogMode
.Set(DMODE_OLDSTYLE
);
434 Dialog::RealDlgProc
= DlgProc
;
436 //_SVS(SysLog(L"Dialog =%d",CtrlObject->Macro.GetMode()));
437 // запоминаем предыдущий заголовок консоли
438 OldTitle
= new ConsoleTitle
;
440 memset(&Id
, 0, sizeof(Id
));
443 //////////////////////////////////////////////////////////////////////////
446 Деструктор класса Dialog
450 _tran(SysLog(L
"[%p] Dialog::~Dialog()", this));
452 DeleteDialogObjects();
460 for (unsigned i
= 0; i
< ItemCount
; i
++)
466 if (!WinPortTesting()) {
468 PeekInputRecord(&rec
);
471 _DIALOG(CleverSysLog
CL(L
"Destroy Dialog"));
474 void Dialog::CheckDialogCoord()
476 CriticalSectionLock
Lock(CS
);
478 if (X1
== -1) // задано центрирование диалога по горизонтали?
479 { // X2 при этом = ширине диалога.
480 X1
= (ScrX
- X2
+ 1) / 2;
482 if (X1
< 0) // ширина диалога больше ширины экрана?
490 if (Y1
== -1) // задано центрирование диалога по вертикали?
491 { // Y2 при этом = высоте диалога.
492 Y1
= (ScrY
- Y2
+ 1) / 2;
494 if (!DialogMode
.Check(DMODE_SMALLDIALOG
)) //????
506 void Dialog::InitDialog()
508 CriticalSectionLock
Lock(CS
);
510 if (!DialogMode
.Check(DMODE_INITOBJECTS
)) // самодостаточный вариант, когда
511 { // элементы инициализируются при первом вызове.
513 unsigned InitFocus
= InitDialogObjects();
514 int Result
= (int)DlgProc((HANDLE
)this, DN_INITDIALOG
, InitFocus
, DataDialog
);
516 if (ExitCode
== -1) {
518 // еще разок, т.к. данные могли быть изменены
519 InitFocus
= InitDialogObjects(); // InitFocus=????
522 if (!DialogMode
.Check(DMODE_KEEPCONSOLETITLE
))
523 ConsoleTitle::SetFarTitle(GetDialogTitle());
526 // все объекты проинициализированы!
527 DialogMode
.Set(DMODE_INITOBJECTS
);
528 DialogInfo di
= {sizeof(di
)};
530 if (DlgProc(reinterpret_cast<HANDLE
>(this), DN_GETDIALOGINFO
, 0, reinterpret_cast<LONG_PTR
>(&di
))) {
535 DlgProc((HANDLE
)this, DN_GOTFOCUS
, InitFocus
, 0);
539 //////////////////////////////////////////////////////////////////////////
542 Расчет значений координат окна диалога и вызов функции
543 ScreenObject::Show() для вывода диалога на экран.
547 CriticalSectionLock
Lock(CS
);
548 _tran(SysLog(L
"[%p] Dialog::Show()", this));
550 if (!DialogMode
.Check(DMODE_INITOBJECTS
))
553 if (!Locked() && DialogMode
.Check(DMODE_RESIZED
)) {
554 PreRedrawItem preRedrawItem
= PreRedraw
.Peek();
556 if (preRedrawItem
.PreRedrawFunc
)
557 preRedrawItem
.PreRedrawFunc();
560 DialogMode
.Clear(DMODE_RESIZED
);
565 DialogMode
.Set(DMODE_SHOW
);
566 ScreenObject::Show();
569 // Цель перехвата данной функции - управление видимостью...
572 CriticalSectionLock
Lock(CS
);
573 _tran(SysLog(L
"[%p] Dialog::Hide()", this));
575 if (!DialogMode
.Check(DMODE_INITOBJECTS
))
578 DialogMode
.Clear(DMODE_SHOW
);
579 ScreenObject::Hide();
582 //////////////////////////////////////////////////////////////////////////
585 Инициализация объектов и вывод диалога на экран.
587 void Dialog::DisplayObject()
589 CriticalSectionLock
Lock(CS
);
591 if (DialogMode
.Check(DMODE_SHOW
)) {
592 ChangePriority
ChPriority(ChangePriority::NORMAL
);
593 ShowDialog(); // "нарисуем" диалог
597 // пересчитать координаты для элементов с DIF_CENTERGROUP
598 void Dialog::ProcessCenterGroup()
600 CriticalSectionLock
Lock(CS
);
602 for (unsigned I
= 0; I
< ItemCount
; I
++) {
604 Последовательно объявленные элементы с флагом DIF_CENTERGROUP
605 и одинаковой вертикальной позицией будут отцентрированы в диалоге.
606 Их координаты X не важны. Удобно использовать для центрирования
609 if ((Item
[I
]->Flags
& DIF_CENTERGROUP
)
610 && (I
== 0 || (Item
[I
- 1]->Flags
& DIF_CENTERGROUP
) == 0
611 || Item
[I
- 1]->Y1
!= Item
[I
]->Y1
)) {
615 J
< ItemCount
&& (Item
[J
]->Flags
& DIF_CENTERGROUP
) && Item
[J
]->Y1
== Item
[I
]->Y1
; J
++) {
616 Length
+= LenStrItem(J
);
618 if (!Item
[J
]->strData
.IsEmpty())
619 switch (Item
[J
]->Type
) {
630 if (!Item
[I
]->strData
.IsEmpty())
631 switch (Item
[I
]->Type
) {
639 } // Бля, це ж ботва какая-то
641 int StartX
= Max(0, (X2
- X1
+ 1 - Length
) / 2);
644 J
< ItemCount
&& (Item
[J
]->Flags
& DIF_CENTERGROUP
) && Item
[J
]->Y1
== Item
[I
]->Y1
; J
++) {
645 Item
[J
]->X1
= StartX
;
646 StartX
+= LenStrItem(J
);
648 if (!Item
[J
]->strData
.IsEmpty())
649 switch (Item
[J
]->Type
) {
659 if (StartX
== Item
[J
]->X1
)
660 Item
[J
]->X2
= StartX
;
662 Item
[J
]->X2
= StartX
- 1;
668 //////////////////////////////////////////////////////////////////////////
671 Инициализация элементов диалога.
673 InitDialogObjects возвращает ID элемента с фокусом ввода
674 Параметр - для выборочной реинициализации элементов. ID = -1 - касаемо всех объектов
677 TODO: Необходимо применить ProcessRadioButton для исправления
678 кривых рук некоторых плагинописателей (а надо?)
680 unsigned Dialog::InitDialogObjects(unsigned ID
)
682 CriticalSectionLock
Lock(CS
);
685 DialogItemEx
*CurItem
;
686 unsigned InitItemCount
;
688 _DIALOG(CleverSysLog
CL(L
"Init Dialog"));
690 if (ID
== (unsigned)-1) // инициализируем все?
693 InitItemCount
= ItemCount
;
694 } else if (ID
+ 1 > ItemCount
) {
697 InitItemCount
= ID
+ 1;
700 // если FocusPos в пределах и элемент задисаблен, то ищем сначала
701 if (FocusPos
!= (unsigned)-1 && FocusPos
< ItemCount
702 && (Item
[FocusPos
]->Flags
& (DIF_DISABLE
| DIF_NOFOCUS
| DIF_HIDDEN
)))
703 FocusPos
= (unsigned)-1; // будем искать сначала!
705 // предварительный цикл по поводу кнопок
706 for (I
= ID
; I
< InitItemCount
; I
++) {
708 ItemFlags
= CurItem
->Flags
;
709 Type
= CurItem
->Type
;
711 if (Type
== DI_BUTTON
&& ItemFlags
& DIF_SETSHIELD
) {
712 CurItem
->strData
= FARString(L
"\x2580\x2584 ") + CurItem
->strData
;
716 для кнопок не имеющи стиля "Показывает заголовок кнопки без скобок"
717 добавим энти самые скобки
719 if (Type
== DI_BUTTON
&& !(ItemFlags
& DIF_NOBRACKETS
)) {
720 LPCWSTR Brackets
[] = {L
"[ ", L
" ]", L
"{ ", L
" }"};
721 int Start
= (CurItem
->DefaultButton
? 2 : 0);
722 if (CurItem
->strData
.At(0) != *Brackets
[Start
]) {
723 CurItem
->strData
= Brackets
[Start
] + CurItem
->strData
+ Brackets
[Start
+ 1];
726 // предварительный поик фокуса
727 if (FocusPos
== (unsigned)-1 && CanGetFocus(Type
) && CurItem
->Focus
728 && !(ItemFlags
& (DIF_DISABLE
| DIF_NOFOCUS
| DIF_HIDDEN
)))
729 FocusPos
= I
; // запомним первый фокусный элемент
731 CurItem
->Focus
= 0; // сбросим для всех, чтобы не оказалось,
732 // что фокусов - как у дурочка фантиков
734 // сбросим флаг DIF_CENTERGROUP для редакторов
740 case DI_VTEXT
: // ????
744 if (ItemFlags
& DIF_CENTERGROUP
)
745 CurItem
->Flags
&= ~DIF_CENTERGROUP
;
750 Опять про фокус ввода - теперь, если "чудо" забыло выставить
751 хотя бы один, то ставим на первый подходящий
753 if (FocusPos
== (unsigned)-1) {
754 for (I
= 0; I
< ItemCount
; I
++) // по всем!!!!
758 if (CanGetFocus(CurItem
->Type
) && !(CurItem
->Flags
& (DIF_DISABLE
| DIF_NOFOCUS
| DIF_HIDDEN
))) {
765 if (FocusPos
== (unsigned)-1) // ну ни хрена себе - нет ни одного
766 { // элемента с возможностью фокуса
767 FocusPos
= 0; // убится, блин
770 // ну вот и добрались до!
771 Item
[FocusPos
]->Focus
= 1;
772 // а теперь все сначала и по полной программе...
773 ProcessCenterGroup(); // сначала отцентрируем
775 for (I
= ID
; I
< InitItemCount
; I
++) {
777 Type
= CurItem
->Type
;
778 ItemFlags
= CurItem
->Flags
;
780 if (Type
== DI_LISTBOX
) {
781 if (!DialogMode
.Check(DMODE_CREATEOBJECTS
)) {
782 CurItem
->ListPtr
= new VMenu(nullptr, nullptr, 0, CurItem
->Y2
- CurItem
->Y1
+ 1,
783 VMENU_ALWAYSSCROLLBAR
| VMENU_LISTBOX
, nullptr, this);
786 if (CurItem
->ListPtr
) {
787 VMenu
*ListPtr
= CurItem
->ListPtr
;
788 ListPtr
->SetVDialogItemID(I
);
791 + Флаг DIF_LISTNOAMPERSAND. По умолчанию для DI_LISTBOX &
792 DI_COMBOBOX выставляется флаг MENU_SHOWAMPERSAND. Этот флаг
793 подавляет такое поведение
795 CurItem
->IFlags
.Set(DLGIIF_LISTREACTIONFOCUS
| DLGIIF_LISTREACTIONNOFOCUS
); // всегда!
796 ListPtr
->ChangeFlags(VMENU_DISABLED
, ItemFlags
& DIF_DISABLE
);
797 ListPtr
->ChangeFlags(VMENU_SHOWAMPERSAND
, !(ItemFlags
& DIF_LISTNOAMPERSAND
));
798 ListPtr
->ChangeFlags(VMENU_SHOWNOBOX
, ItemFlags
& DIF_LISTNOBOX
);
799 ListPtr
->ChangeFlags(VMENU_WRAPMODE
, ItemFlags
& DIF_LISTWRAPMODE
);
800 ListPtr
->ChangeFlags(VMENU_AUTOHIGHLIGHT
, ItemFlags
& DIF_LISTAUTOHIGHLIGHT
);
802 if (ItemFlags
& DIF_LISTAUTOHIGHLIGHT
)
803 ListPtr
->AssignHighlights(FALSE
);
805 ListPtr
->SetDialogStyle(DialogMode
.Check(DMODE_WARNINGSTYLE
));
806 ListPtr
->SetPosition(X1
+ CurItem
->X1
, Y1
+ CurItem
->Y1
, X1
+ CurItem
->X2
, Y1
+ CurItem
->Y2
);
807 ListPtr
->SetBoxType(SHORT_SINGLE_BOX
);
809 // поле FarDialogItem.Data для DI_LISTBOX используется как верхний заголовок листа
810 if (!(ItemFlags
& DIF_LISTNOBOX
) && !DialogMode
.Check(DMODE_CREATEOBJECTS
)) {
811 ListPtr
->SetTitle(CurItem
->strData
);
815 // ListBox->DeleteItems(); //???? А НАДО ЛИ ????
816 if (CurItem
->ListItems
&& !DialogMode
.Check(DMODE_CREATEOBJECTS
)) {
817 ListPtr
->AddItem(CurItem
->ListItems
);
820 ListPtr
->ChangeFlags(VMENU_LISTHASFOCUS
, CurItem
->Focus
);
823 // "редакторы" - разговор особый...
824 else if (FarIsEdit(Type
)) {
826 сбросим флаг DIF_EDITOR для строки ввода, отличной от DI_EDIT,
827 DI_FIXEDIT и DI_PSWEDIT
829 if (Type
!= DI_COMBOBOX
)
830 if ((ItemFlags
& DIF_EDITOR
) && Type
!= DI_EDIT
&& Type
!= DI_FIXEDIT
&& Type
!= DI_PSWEDIT
)
831 ItemFlags
&= ~DIF_EDITOR
;
833 if (!DialogMode
.Check(DMODE_CREATEOBJECTS
)) {
835 new DlgEdit(this, I
, Type
== DI_MEMOEDIT
? DLGEDIT_MULTILINE
: DLGEDIT_SINGLELINE
);
837 if (Type
== DI_COMBOBOX
) {
838 CurItem
->ListPtr
= new VMenu(L
"", nullptr, 0, Opt
.Dialogs
.CBoxMaxHeight
,
839 VMENU_ALWAYSSCROLLBAR
| VMENU_NOTCHANGE
, nullptr, this);
840 CurItem
->ListPtr
->SetVDialogItemID(I
);
843 CurItem
->SelStart
= -1;
846 DlgEdit
*DialogEdit
= (DlgEdit
*)CurItem
->ObjPtr
;
847 // Mantis#58 - символ-маска с кодом 0х0А - пропадает
848 // DialogEdit->SetDialogParent((Type != DI_COMBOBOX && (ItemFlags & DIF_EDITOR) || (CurItem->Type==DI_PSWEDIT || CurItem->Type==DI_FIXEDIT))?
849 // FEDITLINE_PARENT_SINGLELINE:FEDITLINE_PARENT_MULTILINE);
850 DialogEdit
->SetDialogParent(
851 Type
== DI_MEMOEDIT
? FEDITLINE_PARENT_MULTILINE
: FEDITLINE_PARENT_SINGLELINE
);
852 DialogEdit
->SetReadOnly(0);
854 if (Type
== DI_COMBOBOX
) {
855 if (CurItem
->ListPtr
) {
856 VMenu
*ListPtr
= CurItem
->ListPtr
;
857 ListPtr
->SetBoxType(SHORT_SINGLE_BOX
);
858 DialogEdit
->SetDropDownBox(ItemFlags
& DIF_DROPDOWNLIST
);
859 ListPtr
->ChangeFlags(VMENU_WRAPMODE
, ItemFlags
& DIF_LISTWRAPMODE
);
860 ListPtr
->ChangeFlags(VMENU_DISABLED
, ItemFlags
& DIF_DISABLE
);
861 ListPtr
->ChangeFlags(VMENU_SHOWAMPERSAND
, !(ItemFlags
& DIF_LISTNOAMPERSAND
));
862 ListPtr
->ChangeFlags(VMENU_AUTOHIGHLIGHT
, ItemFlags
& DIF_LISTAUTOHIGHLIGHT
);
864 if (ItemFlags
& DIF_LISTAUTOHIGHLIGHT
)
865 ListPtr
->AssignHighlights(FALSE
);
867 if (CurItem
->ListItems
&& !DialogMode
.Check(DMODE_CREATEOBJECTS
))
868 ListPtr
->AddItem(CurItem
->ListItems
);
870 ListPtr
->SetFlags(VMENU_COMBOBOX
);
871 ListPtr
->SetDialogStyle(DialogMode
.Check(DMODE_WARNINGSTYLE
));
877 строка редакторирование должна иметь максимум в 511 символов
878 выставляем максимальный размер в том случае, если он еще не выставлен
882 if (DialogEdit
->GetMaxLength() == -1)
883 DialogEdit
->SetMaxLength(CurItem
->nMaxLength
? (int)CurItem
->nMaxLength
: -1);
885 DialogEdit
->SetPosition(X1
+ CurItem
->X1
, Y1
+ CurItem
->Y1
, X1
+ CurItem
->X2
, Y1
+ CurItem
->Y2
);
888 DialogEdit->SetObjectColor(
889 FarColorToReal(DialogMode.Check(DMODE_WARNINGSTYLE) ?
890 ((ItemFlags&DIF_DISABLE)?COL_WARNDIALOGEDITDISABLED:COL_WARNDIALOGEDIT):
891 ((ItemFlags&DIF_DISABLE)?COL_DIALOGEDITDISABLED:COL_DIALOGEDIT)),
892 FarColorToReal((ItemFlags&DIF_DISABLE)?COL_DIALOGEDITDISABLED:COL_DIALOGEDITSELECTED)
895 if (CurItem
->Type
== DI_PSWEDIT
) {
896 DialogEdit
->SetPasswordMode(TRUE
);
897 // ...Что бы небыло повадно... и для повыщения защиты, т.с.
898 ItemFlags
&= ~DIF_HISTORY
;
901 if (Type
== DI_FIXEDIT
) {
902 // DIF_HISTORY имеет более высокий приоритет, чем DIF_MASKEDIT
903 if (ItemFlags
& DIF_HISTORY
)
904 ItemFlags
&= ~DIF_MASKEDIT
;
907 если DI_FIXEDIT, то курсор сразу ставится на замену...
908 ай-ай - было недокументированно :-)
910 DialogEdit
->SetMaxLength(CurItem
->X2
- CurItem
->X1
+ 1
911 + (CurItem
->X2
== CurItem
->X1
|| !(ItemFlags
& DIF_HISTORY
) ? 0 : 1));
912 DialogEdit
->SetOvertypeMode(TRUE
);
915 Если тип строки ввода DI_FIXEDIT и установлен флаг DIF_MASKEDIT
916 и непустой параметр CurItem->Mask, то вызываем новую функцию
917 для установки маски в объект DlgEdit.
920 // Маска не должна быть пустой (строка из пробелов не учитывается)!
921 if ((ItemFlags
& DIF_MASKEDIT
) && !CurItem
->strMask
.IsEmpty()) {
922 RemoveExternalSpaces(CurItem
->strMask
);
923 if (!CurItem
->strMask
.IsEmpty()) {
924 DialogEdit
->SetInputMask(CurItem
->strMask
);
926 ItemFlags
&= ~DIF_MASKEDIT
;
933 Последовательно определенные поля ввода (edit controls),
934 имеющие этот флаг группируются в редактор с возможностью
935 вставки и удаления строк
937 if (!(ItemFlags
& DIF_EDITOR
) && CurItem
->Type
!= DI_COMBOBOX
) {
938 DialogEdit
->SetEditBeyondEnd(FALSE
);
940 if (!DialogMode
.Check(DMODE_INITOBJECTS
))
941 DialogEdit
->SetClearFlag(1);
944 if (CurItem
->Type
== DI_COMBOBOX
)
945 DialogEdit
->SetClearFlag(1);
949 Еже ли стоит флаг DIF_USELASTHISTORY и непустая строка ввода,
950 то подстанавливаем первое значение из History
952 if (CurItem
->Type
== DI_EDIT
953 && (ItemFlags
& (DIF_HISTORY
| DIF_USELASTHISTORY
))
954 == (DIF_HISTORY
| DIF_USELASTHISTORY
)) {
955 ProcessLastHistory(CurItem
, -1);
958 if ((ItemFlags
& DIF_MANUALADDHISTORY
) && !(ItemFlags
& DIF_HISTORY
))
959 ItemFlags
&= ~DIF_MANUALADDHISTORY
; // сбросим нафиг.
963 Если это ComBoBox и данные не установлены, то берем из списка
964 при условии, что хоть один из пунктов имеет Selected
967 if (Type
== DI_COMBOBOX
&& CurItem
->strData
.IsEmpty() && CurItem
->ListItems
) {
968 FarListItem
*ListItems
= CurItem
->ListItems
->Items
;
969 unsigned Length
= CurItem
->ListItems
->ItemsNumber
;
970 // CurItem->ListPtr->AddItem(CurItem->ListItems);
972 for (J
= 0; J
< Length
; J
++) {
973 if (ListItems
[J
].Flags
& LIF_SELECTED
) {
974 if (ItemFlags
& (DIF_DROPDOWNLIST
| DIF_LISTNOAMPERSAND
))
975 HiText2Str(CurItem
->strData
, ListItems
[J
].Text
);
977 CurItem
->strData
= ListItems
[J
].Text
;
984 DialogEdit
->SetCallbackState(false);
985 DialogEdit
->SetString(CurItem
->strData
);
986 DialogEdit
->SetCallbackState(true);
988 if (Type
== DI_FIXEDIT
)
989 DialogEdit
->SetCurPos(0);
991 // Для обычных строк отрубим постоянные блоки
992 if (!(ItemFlags
& DIF_EDITOR
))
993 DialogEdit
->SetPersistentBlocks(Opt
.Dialogs
.EditBlock
);
995 DialogEdit
->SetDelRemovesBlocks(Opt
.Dialogs
.DelRemovesBlocks
);
997 if (ItemFlags
& DIF_READONLY
)
998 DialogEdit
->SetReadOnly(1);
999 } else if (Type
== DI_USERCONTROL
) {
1000 if (!DialogMode
.Check(DMODE_CREATEOBJECTS
))
1001 CurItem
->UCData
= new DlgUserControl
;
1004 CurItem
->Flags
= ItemFlags
;
1007 // если будет редактор, то обязательно будет выделен.
1008 SelectOnEntry(FocusPos
, TRUE
);
1009 // все объекты созданы!
1010 DialogMode
.Set(DMODE_CREATEOBJECTS
);
1014 const wchar_t *Dialog::GetDialogTitle()
1016 CriticalSectionLock
Lock(CS
);
1017 DialogItemEx
*CurItem
, *CurItemList
= nullptr;
1019 for (unsigned I
= 0; I
< ItemCount
; I
++) {
1022 // по первому попавшемуся "тексту" установим заголовок консоли!
1023 if ((CurItem
->Type
== DI_TEXT
|| CurItem
->Type
== DI_DOUBLEBOX
|| CurItem
->Type
== DI_SINGLEBOX
)) {
1024 const wchar_t *Ptr
= CurItem
->strData
;
1027 if (IsAlpha(*Ptr
) || iswdigit(*Ptr
))
1029 } else if (CurItem
->Type
== DI_LISTBOX
&& !I
)
1030 CurItemList
= CurItem
;
1034 return CurItemList
->ListPtr
->GetPtrTitle();
1037 return nullptr; //""
1040 void Dialog::ProcessLastHistory(DialogItemEx
*CurItem
, int MsgIndex
)
1042 CriticalSectionLock
Lock(CS
);
1043 FARString
&strData
= CurItem
->strData
;
1045 if (strData
.IsEmpty()) {
1046 FARString strRegKey
= fmtSavedDialogHistory
;
1047 strRegKey
+= CurItem
->strHistory
;
1048 History::ReadLastItem(strRegKey
.GetMB().c_str(), strData
);
1050 if (MsgIndex
!= -1) {
1051 // обработка DM_SETHISTORY => надо пропустить изменение текста через
1052 // диалоговую функцию
1053 FarDialogItemData IData
;
1054 IData
.PtrData
= const_cast<wchar_t *>(strData
.CPtr());
1055 IData
.PtrLength
= (int)strData
.GetLength();
1056 SendDlgMessage(this, DM_SETTEXT
, MsgIndex
, (LONG_PTR
)&IData
);
1062 static int ToRange(int Val
, int Min
, int Max
)
1064 return std::min(std::max(Val
, Min
), Max
);
1067 // Изменение координат и/или размеров итема диалога.
1068 BOOL
Dialog::SetItemRect(unsigned ID
, SMALL_RECT
*aRect
)
1070 CriticalSectionLock
Lock(CS
);
1072 if (ID
>= ItemCount
)
1077 Rect
.Left
= ToRange(Rect
.Left
, 0, X2
-X1
);
1078 Rect
.Top
= ToRange(Rect
.Top
, 0, Y2
-Y1
);
1079 Rect
.Right
= ToRange(Rect
.Right
, Rect
.Left
, X2
-X1
);
1080 Rect
.Bottom
= ToRange(Rect
.Bottom
, Rect
.Top
, Y2
-Y1
);
1082 DialogItemEx
*CurItem
= Item
[ID
];
1083 int Type
= CurItem
->Type
;
1084 CurItem
->X1
= Rect
.Left
;
1085 CurItem
->Y1
= (Rect
.Top
< 0) ? 0 : Rect
.Top
;
1087 if (FarIsEdit(Type
)) {
1088 DlgEdit
*DialogEdit
= (DlgEdit
*)CurItem
->ObjPtr
;
1089 CurItem
->X2
= Rect
.Right
;
1090 CurItem
->Y2
= (Type
== DI_MEMOEDIT
? Rect
.Bottom
: 0);
1091 DialogEdit
->SetPosition(X1
+ Rect
.Left
, Y1
+ Rect
.Top
, X1
+ Rect
.Right
, Y1
+ Rect
.Top
);
1092 } else if (Type
== DI_LISTBOX
) {
1093 CurItem
->X2
= Rect
.Right
;
1094 CurItem
->Y2
= Rect
.Bottom
;
1095 CurItem
->ListPtr
->SetPosition(X1
+ Rect
.Left
, Y1
+ Rect
.Top
, X1
+ Rect
.Right
, Y1
+ Rect
.Bottom
);
1096 CurItem
->ListPtr
->SetMaxHeight(CurItem
->Y2
- CurItem
->Y1
+ 1);
1101 CurItem
->X2
= Rect
.Right
;
1102 CurItem
->Y2
= 0; // ???
1105 CurItem
->X2
= 0; // ???
1106 CurItem
->Y2
= Rect
.Bottom
;
1109 case DI_USERCONTROL
:
1110 CurItem
->X2
= Rect
.Right
;
1111 CurItem
->Y2
= Rect
.Bottom
;
1115 if (DialogMode
.Check(DMODE_SHOW
)) {
1116 ShowDialog((unsigned)-1);
1123 BOOL
Dialog::GetItemRect(unsigned I
, SMALL_RECT
&Rect
)
1125 CriticalSectionLock
Lock(CS
);
1130 DialogItemEx
*CurItem
= Item
[I
];
1131 DWORD ItemFlags
= CurItem
->Flags
;
1132 int Type
= CurItem
->Type
;
1134 Rect
.Left
= CurItem
->X1
;
1135 Rect
.Top
= CurItem
->Y1
;
1136 Rect
.Right
= CurItem
->X2
;
1137 Rect
.Bottom
= CurItem
->Y2
;
1148 Len
= ((ItemFlags
& DIF_SHOWAMPERSAND
)
1149 ? (int)CurItem
->strData
.CellsCount()
1150 : HiStrCellsCount(CurItem
->strData
));
1157 if (CurItem
->X1
== -1)
1158 Rect
.Left
= (X2
- X1
+ 1 - Len
) / 2;
1163 if (CurItem
->Y1
== -1)
1164 Rect
.Top
= (Y2
- Y1
+ 1) / 2;
1169 Rect
.Bottom
= Rect
.Top
;
1171 if (!Rect
.Right
|| Rect
.Right
== Rect
.Left
)
1172 Rect
.Right
= Rect
.Left
+ Len
- (Len
? 1 : 0);
1174 if (ItemFlags
& (DIF_SEPARATOR
| DIF_SEPARATOR2
)) {
1175 Rect
.Bottom
= Rect
.Top
;
1176 Rect
.Left
= (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 3 : 0); //???
1177 Rect
.Right
= X2
- X1
- (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 5 : 0); //???
1183 if (CurItem
->X1
== -1)
1184 Rect
.Left
= (X2
- X1
+ 1) / 2;
1189 if (CurItem
->Y1
== -1)
1190 Rect
.Top
= (Y2
- Y1
+ 1 - Len
) / 2;
1195 Rect
.Right
= Rect
.Left
;
1197 // Rect.bottom=Rect.top+Len;
1198 if (!Rect
.Bottom
|| Rect
.Bottom
== Rect
.Top
)
1199 Rect
.Bottom
= Rect
.Top
+ Len
- (Len
? 1 : 0);
1201 #if defined(VTEXT_ADN_SEPARATORS)
1203 if (ItemFlags
& (DIF_SEPARATOR
| DIF_SEPARATOR2
)) {
1204 Rect
.Right
= Rect
.Left
;
1205 Rect
.Top
= (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 1 : 0); //???
1206 Rect
.Bottom
= Y2
- Y1
- (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 3 : 0); //???
1213 Rect
.Bottom
= Rect
.Top
;
1214 Rect
.Right
= Rect
.Left
+ Len
;
1217 case DI_RADIOBUTTON
:
1218 Rect
.Bottom
= Rect
.Top
;
1219 Rect
.Right
= Rect
.Left
+ Len
+ ((Type
== DI_CHECKBOX
) ? 4 : (ItemFlags
& DIF_MOVESELECT
? 3 : 4));
1225 Rect
.Bottom
= Rect
.Top
;
1232 bool Dialog::ItemHasDropDownArrow(const DialogItemEx
*Item
)
1234 return ((!Item
->strHistory
.IsEmpty() && (Item
->Flags
& DIF_HISTORY
) && Opt
.Dialogs
.EditHistory
)
1235 || (Item
->Type
== DI_COMBOBOX
&& Item
->ListPtr
&& Item
->ListPtr
->GetItemCount() > 0));
1238 //////////////////////////////////////////////////////////////////////////
1241 Получение данных и удаление "редакторов"
1243 void Dialog::DeleteDialogObjects()
1245 CriticalSectionLock
Lock(CS
);
1246 DialogItemEx
*CurItem
;
1248 for (unsigned I
= 0; I
< ItemCount
; I
++) {
1251 switch (CurItem
->Type
) {
1258 if (CurItem
->ObjPtr
)
1259 delete (DlgEdit
*)(CurItem
->ObjPtr
);
1263 if ((CurItem
->Type
== DI_COMBOBOX
|| CurItem
->Type
== DI_LISTBOX
) && CurItem
->ListPtr
)
1264 delete CurItem
->ListPtr
;
1267 case DI_USERCONTROL
:
1269 if (CurItem
->UCData
)
1270 delete CurItem
->UCData
;
1275 if (CurItem
->Flags
& DIF_AUTOMATION
)
1276 if (CurItem
->AutoPtr
)
1277 free(CurItem
->AutoPtr
);
1281 //////////////////////////////////////////////////////////////////////////
1284 Сохраняет значение из полей редактирования.
1285 При установленном флаге DIF_HISTORY, сохраняет данные в реестре.
1287 void Dialog::GetDialogObjectsData()
1289 CriticalSectionLock
Lock(CS
);
1291 DialogItemEx
*CurItem
;
1293 for (unsigned I
= 0; I
< ItemCount
; I
++) {
1295 DWORD IFlags
= CurItem
->Flags
;
1297 switch (Type
= CurItem
->Type
) {
1304 if (CurItem
->ObjPtr
) {
1306 DlgEdit
*EditPtr
= (DlgEdit
*)(CurItem
->ObjPtr
);
1312 EditPtr
->GetString(strData
);
1314 if (ExitCode
>= 0 && (IFlags
& DIF_HISTORY
) && !(IFlags
& DIF_MANUALADDHISTORY
) && // при мануале не добавляем
1315 !CurItem
->strHistory
.IsEmpty() && Opt
.Dialogs
.EditHistory
) {
1316 AddToEditHistory(strData
, CurItem
->strHistory
);
1321 ! В History должно заносится значение (для DIF_EXPAND...) перед
1327 Проверка - этот элемент предполагает расширение переменных среды?
1328 т.к. функция GetDialogObjectsData() может вызываться самостоятельно
1334 ! Для DI_PSWEDIT и DI_FIXEDIT обработка DIF_EDITEXPAND не нужна
1335 (DI_FIXEDIT допускается для случая если нету маски)
1338 if ((IFlags
& DIF_EDITEXPAND
) && Type
!= DI_PSWEDIT
&& Type
!= DI_FIXEDIT
) {
1339 apiExpandEnvironmentStrings(strData
, strData
);
1340 // как бы грязный хак, нам нужно обновить строку чтоб отдавалась правильная строка
1341 // для различных DM_* после закрытия диалога, но ни в коем случае нельзя чтоб
1342 // высылался DN_EDITCHANGE для этого изменения, ибо диалог уже закрыт.
1343 EditPtr
->SetCallbackState(false);
1344 EditPtr
->SetString(strData
);
1345 EditPtr
->SetCallbackState(true);
1348 CurItem
->strData
= strData
;
1355 if(CurItem->ListPtr)
1357 CurItem->ListPos=CurItem->ListPtr->GetSelectPos();
1366 if ((Type
== DI_COMBOBOX
|| Type
== DI_LISTBOX
) && CurItem
->ListPtr
&& CurItem
->ListItems
&& DlgProc
== DefDlgProc
)
1368 int ListPos
=CurItem
->ListPtr
->GetSelectPos();
1370 if (ListPos
< CurItem
->ListItems
->ItemsNumber
)
1372 for (int J
=0; J
< CurItem
->ListItems
->ItemsNumber
; ++J
)
1373 CurItem
->ListItems
->Items
[J
].Flags
&=~LIF_SELECTED
;
1375 CurItem
->ListItems
->Items
[ListPos
].Flags
|=LIF_SELECTED
;
1381 if ((Type
== DI_COMBOBOX
|| Type
== DI_LISTBOX
)) {
1382 CurItem
->ListPos
= CurItem
->ListPtr
? CurItem
->ListPtr
->GetSelectPos() : 0;
1389 // Функция формирования и запроса цветов.
1390 DWORD
Dialog::CtlColorDlgItem(int ItemPos
, const DialogItemEx
*CurItem
)
1392 CriticalSectionLock
Lock(CS
);
1393 const int Type
= CurItem
->Type
;
1394 const int Focus
= CurItem
->Focus
;
1395 const int Default
= CurItem
->DefaultButton
;
1396 const DWORD Flags
= CurItem
->Flags
;
1398 const bool DisabledItem
= (Flags
& DIF_DISABLE
) != 0;
1403 case DI_DOUBLEBOX
: {
1404 if (Flags
& DIF_SETCOLOR
)
1405 Attr
= Flags
& DIF_COLORMASK
;
1407 Attr
= DialogMode
.Check(DMODE_WARNINGSTYLE
)
1408 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGBOX
)
1409 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGBOX
);
1412 Attr
= MAKELONG(MAKEWORD(FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1413 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGBOXTITLE
)
1414 : (DisabledItem
? COL_DIALOGDISABLED
1415 : COL_DIALOGBOXTITLE
)), // Title LOBYTE
1416 FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1417 ? (DisabledItem
? COL_WARNDIALOGDISABLED
1418 : COL_WARNDIALOGHIGHLIGHTBOXTITLE
)
1419 : (DisabledItem
? COL_DIALOGDISABLED
1420 : COL_DIALOGHIGHLIGHTBOXTITLE
))), // HiText HIBYTE
1421 MAKEWORD(FarColorToReal(Attr
), // Box LOBYTE
1426 #if defined(VTEXT_ADN_SEPARATORS)
1430 if (Flags
& DIF_SETCOLOR
)
1431 Attr
= Flags
& DIF_COLORMASK
;
1433 if (Flags
& DIF_BOXCOLOR
)
1434 Attr
= DialogMode
.Check(DMODE_WARNINGSTYLE
)
1435 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGBOX
)
1436 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGBOX
);
1438 Attr
= DialogMode
.Check(DMODE_WARNINGSTYLE
)
1439 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGTEXT
)
1440 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGTEXT
);
1443 Attr
= MAKELONG(MAKEWORD(FarColorToReal(Attr
),
1444 FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1445 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGHIGHLIGHTTEXT
)
1446 : (DisabledItem
? COL_DIALOGDISABLED
1447 : COL_DIALOGHIGHLIGHTTEXT
) // HIBYTE HiText
1449 ((Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
)) ? (
1450 MAKEWORD(FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1451 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGBOX
)
1452 : (DisabledItem
? COL_DIALOGDISABLED
1453 : COL_DIALOGBOX
) // Box LOBYTE
1459 #if !defined(VTEXT_ADN_SEPARATORS)
1461 if (Flags
& DIF_BOXCOLOR
)
1462 Attr
= DialogMode
.Check(DMODE_WARNINGSTYLE
)
1463 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGBOX
)
1464 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGBOX
);
1465 else if (Flags
& DIF_SETCOLOR
)
1466 Attr
= (Flags
& DIF_COLORMASK
);
1468 Attr
= (DialogMode
.Check(DMODE_WARNINGSTYLE
)
1469 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGTEXT
)
1470 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGTEXT
));
1472 Attr
= MAKEWORD(MAKEWORD(FarColorToReal(Attr
), 0), MAKEWORD(0, 0));
1477 case DI_RADIOBUTTON
: {
1478 if (Flags
& DIF_SETCOLOR
)
1479 Attr
= (Flags
& DIF_COLORMASK
);
1481 Attr
= (DialogMode
.Check(DMODE_WARNINGSTYLE
)
1482 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGTEXT
)
1483 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGTEXT
));
1485 Attr
= MAKEWORD(FarColorToReal(Attr
),
1486 FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1487 ? (DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGHIGHLIGHTTEXT
)
1488 : (DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGHIGHLIGHTTEXT
))); // HiText
1493 SetCursorType(0, 10);
1494 Attr
= MAKEWORD((Flags
& DIF_SETCOLOR
)
1495 ? (Flags
& DIF_COLORMASK
)
1496 : FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1497 ? (DisabledItem
? COL_WARNDIALOGDISABLED
1498 : (Default
? COL_WARNDIALOGSELECTEDDEFAULTBUTTON
1499 : COL_WARNDIALOGSELECTEDBUTTON
))
1500 : (DisabledItem
? COL_DIALOGDISABLED
1501 : (Default
? COL_DIALOGSELECTEDDEFAULTBUTTON
1502 : COL_DIALOGSELECTEDBUTTON
))), // TEXT
1503 FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1504 ? (DisabledItem
? COL_WARNDIALOGDISABLED
1505 : (Default
? COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON
1506 : COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON
))
1507 : (DisabledItem
? COL_DIALOGDISABLED
1508 : (Default
? COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON
1509 : COL_DIALOGHIGHLIGHTSELECTEDBUTTON
)))); // HiText
1511 Attr
= MAKEWORD((Flags
& DIF_SETCOLOR
)
1512 ? (Flags
& DIF_COLORMASK
)
1513 : FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1514 ? (DisabledItem
? COL_WARNDIALOGDISABLED
1515 : (Default
? COL_WARNDIALOGDEFAULTBUTTON
1516 : COL_WARNDIALOGBUTTON
))
1517 : (DisabledItem
? COL_DIALOGDISABLED
1518 : (Default
? COL_DIALOGDEFAULTBUTTON
1519 : COL_DIALOGBUTTON
))), // TEXT
1520 FarColorToReal(DialogMode
.Check(DMODE_WARNINGSTYLE
)
1521 ? (DisabledItem
? COL_WARNDIALOGDISABLED
1522 : (Default
? COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON
1523 : COL_WARNDIALOGHIGHLIGHTBUTTON
))
1524 : (DisabledItem
? COL_DIALOGDISABLED
1525 : (Default
? COL_DIALOGHIGHLIGHTDEFAULTBUTTON
1526 : COL_DIALOGHIGHLIGHTBUTTON
)))); // HiText
1536 if (Type
== DI_COMBOBOX
&& (Flags
& DIF_DROPDOWNLIST
)) {
1537 if (DialogMode
.Check(DMODE_WARNINGSTYLE
))
1538 Attr
= MAKELONG(MAKEWORD( // LOWORD
1540 FarColorToReal(DisabledItem
? COL_WARNDIALOGEDITDISABLED
1541 : COL_WARNDIALOGEDIT
),
1543 FarColorToReal(DisabledItem
? COL_DIALOGEDITDISABLED
1544 : COL_DIALOGEDITSELECTED
)),
1547 FarColorToReal(DisabledItem
? COL_WARNDIALOGEDITDISABLED
1548 : COL_DIALOGEDITUNCHANGED
), //???
1551 DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGTEXT
)));
1553 Attr
= MAKELONG(MAKEWORD( // LOWORD
1555 FarColorToReal(DisabledItem
1556 ? COL_DIALOGEDITDISABLED
1557 : (!Focus
? COL_DIALOGEDIT
1558 : COL_DIALOGEDITSELECTED
)),
1560 FarColorToReal(DisabledItem
1561 ? COL_DIALOGEDITDISABLED
1562 : (!Focus
? COL_DIALOGEDIT
1563 : COL_DIALOGEDITSELECTED
))),
1566 FarColorToReal(DisabledItem
? COL_DIALOGEDITDISABLED
1567 : COL_DIALOGEDITUNCHANGED
), //???
1569 FarColorToReal(DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGTEXT
)));
1571 if (DialogMode
.Check(DMODE_WARNINGSTYLE
))
1572 Attr
= MAKELONG(MAKEWORD( // LOWORD
1574 FarColorToReal(DisabledItem
1575 ? COL_WARNDIALOGEDITDISABLED
1576 : (Flags
& DIF_NOFOCUS
? COL_DIALOGEDITUNCHANGED
1577 : COL_WARNDIALOGEDIT
)),
1579 FarColorToReal(DisabledItem
? COL_DIALOGEDITDISABLED
1580 : COL_DIALOGEDITSELECTED
)),
1583 FarColorToReal(DisabledItem
? COL_WARNDIALOGEDITDISABLED
1584 : COL_DIALOGEDITUNCHANGED
), //???
1587 DisabledItem
? COL_WARNDIALOGDISABLED
: COL_WARNDIALOGTEXT
)));
1589 Attr
= MAKELONG(MAKEWORD( // LOWORD
1591 FarColorToReal(DisabledItem
1592 ? COL_DIALOGEDITDISABLED
1593 : (Flags
& DIF_NOFOCUS
? COL_DIALOGEDITUNCHANGED
1596 FarColorToReal(DisabledItem
? COL_DIALOGEDITDISABLED
1597 : COL_DIALOGEDITSELECTED
)),
1600 FarColorToReal(DisabledItem
? COL_DIALOGEDITDISABLED
1601 : COL_DIALOGEDITUNCHANGED
), //???
1603 FarColorToReal(DisabledItem
? COL_DIALOGDISABLED
: COL_DIALOGTEXT
)));
1609 Item
[ItemPos
]->ListPtr
->SetColors(nullptr);
1617 ++InCtlColorDlgItem
;
1618 DWORD out
= DlgProc((HANDLE
)this, DN_CTLCOLORDLGITEM
, ItemPos
, Attr
);
1619 --InCtlColorDlgItem
;
1623 static void SetColorNormal(DWORD Attr
, const std::unique_ptr
<DialogItemTrueColors
> &TrueColors
)
1625 ComposeAndSetColor(Attr
& 0xff, TrueColors
? &TrueColors
->Normal
: nullptr);
1628 static void SetColorFrame(DWORD Attr
, const std::unique_ptr
<DialogItemTrueColors
> &TrueColors
)
1630 ComposeAndSetColor(LOBYTE(HIWORD(Attr
)), TrueColors
? &TrueColors
->Frame
: nullptr);
1634 //////////////////////////////////////////////////////////////////////////
1637 Отрисовка элементов диалога на экране.
1639 void Dialog::ShowDialog(unsigned ID
)
1641 CriticalSectionLock
Lock(CS
);
1647 DialogItemEx
*CurItem
;
1649 unsigned I
, DrawItemCount
;
1652 // Если не разрешена отрисовка, то вываливаем.
1653 if (IsEnableRedraw
|| // разрешена прорисовка ?
1654 (ID
+ 1 > ItemCount
) || // а номер в рамках дозволенного?
1655 DialogMode
.Check(DMODE_DRAWING
) || // диалог рисуется?
1656 !DialogMode
.Check(DMODE_SHOW
) || // если не видим, то и не отрисовываем.
1657 !DialogMode
.Check(DMODE_INITOBJECTS
))
1660 DialogMode
.Set(DMODE_DRAWING
); // диалог рисуется!!!
1661 ChangePriority
ChPriority(ChangePriority::NORMAL
);
1663 if (ID
== (unsigned)-1) // рисуем все?
1665 // Перед прорисовкой диалога посылаем сообщение в обработчик
1666 if (!DlgProc((HANDLE
)this, DN_DRAWDIALOG
, 0, 0)) {
1667 DialogMode
.Clear(DMODE_DRAWING
); // конец отрисовки диалога!!!
1671 // перед прорисовкой подложки окна диалога
1672 if (!DialogMode
.Check(DMODE_NODRAWSHADOW
))
1673 Shadow(DialogMode
.Check(DMODE_FULLSHADOW
) != FALSE
); // "наводим" тень
1675 if (!DialogMode
.Check(DMODE_NODRAWPANEL
)) {
1676 Attr
= (DWORD
)DlgProc((HANDLE
)this, DN_CTLCOLORDIALOG
, 0,
1677 DialogMode
.Check(DMODE_WARNINGSTYLE
) ? COL_WARNDIALOGTEXT
: COL_DIALOGTEXT
);
1678 SetScreen(X1
, Y1
, X2
, Y2
, L
' ', Attr
);
1682 DrawItemCount
= ItemCount
;
1684 DrawItemCount
= ID
+ 1;
1688 IFlags.Set(DIMODE_REDRAW)
1690 если рисуется контрол и по Z-order`у он пересекается с
1691 другим контролом (по координатам), то для "позднего"
1692 контрола тоже нужна прорисовка.
1695 bool CursorVisible
= false;
1696 DWORD CursorSize
= 0;
1698 if (ID
!= (unsigned)-1 && FocusPos
!= ID
) {
1699 if (Item
[FocusPos
]->Type
== DI_USERCONTROL
&& Item
[FocusPos
]->UCData
->CursorPos
.X
!= -1
1700 && Item
[FocusPos
]->UCData
->CursorPos
.Y
!= -1) {
1701 CursorVisible
= Item
[FocusPos
]->UCData
->CursorVisible
;
1702 CursorSize
= Item
[FocusPos
]->UCData
->CursorSize
;
1706 SetCursorType(CursorVisible
, CursorSize
);
1709 for (I
= ID
; I
< DrawItemCount
; I
++) {
1712 if (CurItem
->Flags
& DIF_HIDDEN
)
1717 Перед прорисовкой каждого элемента посылаем сообщение
1718 посредством функции SendDlgMessage - в ней делается все!
1720 if (!SendDlgMessage((HANDLE
)this, DN_DRAWDLGITEM
, I
, 0))
1724 short CX1
= CurItem
->X1
;
1725 short CY1
= CurItem
->Y1
;
1726 short CX2
= CurItem
->X2
;
1727 short CY2
= CurItem
->Y2
;
1735 short CW
= CX2
- CX1
+ 1;
1736 short CH
= CY2
- CY1
+ 1;
1737 Attr
= CtlColorDlgItem(I
, CurItem
);
1740 // TODO: прежде чем эту строку применять... нужно проверить _ВСЕ_ диалоги на предмет X2, Y2. !!!
1741 if (((CX1
> -1) && (CX2
> 0) && (CX2
> CX1
)) &&
1742 ((CY1
> -1) && (CY2
> 0) && (CY2
> CY1
)))
1743 SetScreen(X1
+CX1
,Y1
+CY1
,X1
+CX2
,Y1
+CY2
,' ',Attr
&0xFF);
1747 switch (CurItem
->Type
) {
1748 /* ***************************************************************** */
1750 case DI_DOUBLEBOX
: {
1751 BOOL IsDrawTitle
= TRUE
;
1752 GotoXY(X1
+ CX1
, Y1
+ CY1
);
1753 SetColorFrame(Attr
, CurItem
->TrueColors
);
1756 DrawLine(CX2
- CX1
+ 1, CurItem
->Type
== DI_SINGLEBOX
? 8 : 9); //???
1757 } else if (CX1
== CX2
) {
1758 DrawLine(CY2
- CY1
+ 1, CurItem
->Type
== DI_SINGLEBOX
? 10 : 11);
1759 IsDrawTitle
= FALSE
;
1761 Box(X1
+ CX1
, Y1
+ CY1
, X1
+ CX2
, Y1
+ CY2
, LOBYTE(HIWORD(Attr
)),
1762 (CurItem
->Type
== DI_SINGLEBOX
) ? SINGLE_BOX
: DOUBLE_BOX
);
1765 if (!CurItem
->strData
.IsEmpty() && IsDrawTitle
) {
1766 // ! Пусть диалог сам заботится о ширине собственного заголовка.
1767 strStr
= CurItem
->strData
;
1768 TruncStrFromEnd(strStr
, CW
- 2); // 5 ???
1769 LenText
= LenStrItem(I
, strStr
);
1771 if (LenText
< CW
- 2 && !strStr
.Begins(L
' ') ) {
1772 strStr
.Insert(0, L
' ');
1773 LenText
= LenStrItem(I
, strStr
);
1776 if (LenText
< CW
- 2 && !strStr
.Ends(L
' ') ) { // пробел после текста заголовка и рамкой
1777 strStr
.Append(L
' ');
1778 LenText
= LenStrItem(I
, strStr
);
1781 X
= X1
+ CX1
+ (CW
- LenText
) / 2;
1783 if ((CurItem
->Flags
& DIF_LEFTTEXT
) && X1
+ CX1
+ 1 < X
)
1786 SetColorNormal(Attr
, CurItem
->TrueColors
);
1787 GotoXY(X
, Y1
+ CY1
);
1789 if (CurItem
->Flags
& DIF_SHOWAMPERSAND
)
1791 else if (CurItem
->TrueColors
)
1792 HiText(strStr
, ComposeColor(HIBYTE(LOWORD(Attr
)), &CurItem
->TrueColors
->Hilighted
));
1794 HiText(strStr
, HIBYTE(LOWORD(Attr
)));
1799 /* ***************************************************************** */
1801 strStr
= CurItem
->strData
;
1802 LenText
= LenStrItem(I
, strStr
);
1804 if (!(CurItem
->Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
))
1805 && (CurItem
->Flags
& DIF_CENTERTEXT
) && CX1
!= -1)
1806 LenText
= LenStrItem(I
, CenterStr(strStr
, strStr
, CX2
- CX1
+ 1));
1808 X
= (CX1
== -1 || (CurItem
->Flags
& (DIF_SEPARATOR
| DIF_SEPARATOR2
)))
1809 ? (X2
- X1
+ 1 - LenText
) / 2
1811 Y
= (CY1
== -1) ? (Y2
- Y1
+ 1) / 2 : CY1
;
1816 if ((CX2
<= 0) || (CX2
< CX1
))
1819 if (X1
+ X
+ LenText
> X2
) {
1820 int tmpCW
= ObjWidth
;
1825 strStr
.TruncateByCells(tmpCW
- 1);
1829 // SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1831 if (CX1
> -1 && CX2
> CX1
1832 && !(CurItem
->Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
))) { // половинчатое решение
1834 int CntChr
= CX2
- CX1
+ 1;
1835 SetColorNormal(Attr
, CurItem
->TrueColors
);
1836 GotoXY(X1
+ X
, Y1
+ Y
);
1838 if (X1
+ X
+ CntChr
- 1 > X2
)
1839 CntChr
= X2
- (X1
+ X
) + 1;
1841 FS
<< fmt::Cells() << fmt::Expand(CntChr
) << L
"";
1843 if (CntChr
< LenText
)
1844 strStr
.TruncateByCells(CntChr
);
1847 if (CurItem
->Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
)) {
1848 SetColorFrame(Attr
, CurItem
->TrueColors
);
1850 + ((CurItem
->Flags
& DIF_SEPARATORUSER
)
1852 : (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 3 : 0)),
1854 ShowUserSeparator((CurItem
->Flags
& DIF_SEPARATORUSER
)
1856 : RealWidth
- (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 6 : 0 /* -1 */),
1857 (CurItem
->Flags
& DIF_SEPARATORUSER
)
1859 : (CurItem
->Flags
& DIF_SEPARATOR2
? 3 : 1),
1863 SetColorNormal(Attr
, CurItem
->TrueColors
);
1864 GotoXY(X1
+ X
, Y1
+ Y
);
1866 if (CurItem
->Flags
& DIF_SHOWAMPERSAND
) {
1867 // MessageBox(0, strStr, strStr, MB_OK);
1870 // MessageBox(0, strStr, strStr, MB_OK);
1871 HiText(strStr
, HIBYTE(LOWORD(Attr
)));
1876 /* ***************************************************************** */
1878 strStr
= CurItem
->strData
;
1879 LenText
= LenStrItem(I
, strStr
);
1881 if (!(CurItem
->Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
))
1882 && (CurItem
->Flags
& DIF_CENTERTEXT
) && CY1
!= -1)
1883 LenText
= StrLength(CenterStr(strStr
, strStr
, CY2
- CY1
+ 1));
1885 X
= (CX1
== -1) ? (X2
- X1
+ 1) / 2 : CX1
;
1886 Y
= (CY1
== -1 || (CurItem
->Flags
& (DIF_SEPARATOR
| DIF_SEPARATOR2
)))
1887 ? (Y2
- Y1
+ 1 - LenText
) / 2
1893 if ((CY2
<= 0) || (CY2
< CY1
))
1894 CH
= LenStrItem(I
, strStr
);
1896 if (Y1
+ Y
+ LenText
> Y2
) {
1897 int tmpCH
= ObjHeight
;
1902 strStr
.TruncateByCells(tmpCH
- 1);
1906 // SetScreen(X1+CX1,Y1+CY1,X1+CX2,Y1+CY2,' ',Attr&0xFF);
1908 if (CY1
> -1 && CY2
> 0 && CY2
> CY1
1909 && !(CurItem
->Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
))) { // половинчатое решение
1911 int CntChr
= CY2
- CY1
+ 1;
1912 SetColorNormal(Attr
, CurItem
->TrueColors
);
1913 GotoXY(X1
+ X
, Y1
+ Y
);
1915 if (Y1
+ Y
+ CntChr
- 1 > Y2
)
1916 CntChr
= Y2
- (Y1
+ Y
) + 1;
1918 vmprintf(L
"%*ls", CntChr
, L
"");
1921 #if defined(VTEXT_ADN_SEPARATORS)
1923 if (CurItem
->Flags
& (DIF_SEPARATORUSER
| DIF_SEPARATOR
| DIF_SEPARATOR2
)) {
1924 SetColorFrame(Attr
, CurItem
->TrueColors
);
1927 + ((CurItem
->Flags
& DIF_SEPARATORUSER
)
1929 : (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 1 : 0))); //????
1930 ShowUserSeparator((CurItem
->Flags
& DIF_SEPARATORUSER
)
1932 : RealHeight
- (!DialogMode
.Check(DMODE_SMALLDIALOG
) ? 2 : 0),
1933 (CurItem
->Flags
& DIF_SEPARATORUSER
)
1935 : (CurItem
->Flags
& DIF_SEPARATOR2
? 7 : 5),
1940 SetColorNormal(Attr
, CurItem
->TrueColors
);
1941 GotoXY(X1
+ X
, Y1
+ Y
);
1943 if (CurItem
->Flags
& DIF_SHOWAMPERSAND
)
1946 HiText(strStr
, HIBYTE(LOWORD(Attr
)), TRUE
);
1950 /* ***************************************************************** */
1952 case DI_RADIOBUTTON
: {
1953 SetColorNormal(Attr
, CurItem
->TrueColors
);
1954 GotoXY(X1
+ CX1
, Y1
+ CY1
);
1956 if (CurItem
->Type
== DI_CHECKBOX
) {
1957 const wchar_t Check
[] = {L
'[',
1958 (CurItem
->Selected
? (((CurItem
->Flags
& DIF_3STATE
) && CurItem
->Selected
== 2)
1959 ? *Msg::CheckBox2State
1965 if (CurItem
->strData
.GetLength())
1968 wchar_t Dot
[] = {L
' ', CurItem
->Selected
? L
'\x2022' : L
' ', L
' ', L
'\0'};
1970 if (CurItem
->Flags
& DIF_MOVESELECT
) {
1977 if (CurItem
->strData
.GetLength())
1982 strStr
+= CurItem
->strData
;
1983 LenText
= LenStrItem(I
, strStr
);
1985 if (X1
+ CX1
+ LenText
> X2
)
1986 strStr
.TruncateByCells(ObjWidth
- 1);
1988 if (CurItem
->Flags
& DIF_SHOWAMPERSAND
)
1991 HiText(strStr
, HIBYTE(LOWORD(Attr
)));
1993 if (CurItem
->Focus
) {
1994 // Отключение мигающего курсора при перемещении диалога
1995 if (!DialogMode
.Check(DMODE_DRAGGED
))
1996 SetCursorType(1, -1);
1998 MoveCursor(X1
+ CX1
+ 1, Y1
+ CY1
);
2003 /* ***************************************************************** */
2005 strStr
= CurItem
->strData
;
2006 SetColorNormal(Attr
, CurItem
->TrueColors
);
2007 GotoXY(X1
+ CX1
, Y1
+ CY1
);
2009 if (CurItem
->Flags
& DIF_SHOWAMPERSAND
)
2012 HiText(strStr
, HIBYTE(LOWORD(Attr
)));
2014 if (CurItem
->Flags
& DIF_SETSHIELD
) {
2015 int startx
= X1
+ CX1
+ (CurItem
->Flags
& DIF_NOBRACKETS
? 0 : 2);
2016 ScrBuf
.ApplyColor(startx
, Y1
+ CY1
, startx
+ 1, Y1
+ CY1
, 0xE9);
2020 /* ***************************************************************** */
2026 DlgEdit
*EditPtr
= (DlgEdit
*)(CurItem
->ObjPtr
);
2031 EditPtr
->SetObjectColor(Attr
& 0xFF, HIBYTE(LOWORD(Attr
)), LOBYTE(HIWORD(Attr
)));
2033 if (CurItem
->Focus
) {
2034 // Отключение мигающего курсора при перемещении диалога
2035 if (!DialogMode
.Check(DMODE_DRAGGED
))
2036 SetCursorType(1, -1);
2040 EditPtr
->FastShow();
2041 EditPtr
->SetLeftPos(0);
2044 // Отключение мигающего курсора при перемещении диалога
2045 if (DialogMode
.Check(DMODE_DRAGGED
))
2046 SetCursorType(0, 0);
2048 if (ItemHasDropDownArrow(CurItem
)) {
2049 int EditX1
, EditY1
, EditX2
, EditY2
;
2050 EditPtr
->GetPosition(EditX1
, EditY1
, EditX2
, EditY2
);
2051 // Text((CurItem->Type == DI_COMBOBOX?"\x1F":"\x19"));
2052 Text(EditX2
+ 1, EditY1
, HIBYTE(HIWORD(Attr
)), L
"\x2193");
2055 if (CurItem
->Type
== DI_COMBOBOX
&& GetDropDownOpened() && CurItem
->ListPtr
->IsVisible()) // need redraw VMenu?
2057 CurItem
->ListPtr
->Hide();
2058 CurItem
->ListPtr
->Show();
2063 /* ***************************************************************** */
2065 if (CurItem
->ListPtr
) {
2066 // Перед отрисовкой спросим об изменении цветовых атрибутов
2067 BYTE RealColors
[VMENU_COLOR_COUNT
];
2068 FarListColors ListColors
= {0};
2069 ListColors
.ColorCount
= VMENU_COLOR_COUNT
;
2070 ListColors
.Colors
= RealColors
;
2071 CurItem
->ListPtr
->GetColors(&ListColors
);
2073 if (DlgProc((HANDLE
)this, DN_CTLCOLORDLGLIST
, I
, (LONG_PTR
)&ListColors
))
2074 CurItem
->ListPtr
->SetColors(&ListColors
);
2076 // Курсор запоминаем...
2077 bool CursorVisible
= false;
2078 DWORD CursorSize
= 0;
2079 GetCursorType(CursorVisible
, CursorSize
);
2080 CurItem
->ListPtr
->Show();
2082 // .. а теперь восстановим!
2084 SetCursorType(CursorVisible
, CursorSize
);
2089 /* 01.08.2000 SVS $ */
2090 /* ***************************************************************** */
2091 case DI_USERCONTROL
:
2093 if (CurItem
->VBuf
) {
2094 PutText(X1
+ CX1
, Y1
+ CY1
, X1
+ CX2
, Y1
+ CY2
, CurItem
->VBuf
);
2096 // не забудем переместить курсор, если он позиционирован.
2097 if (FocusPos
== I
) {
2098 if (CurItem
->UCData
->CursorPos
.X
!= -1 && CurItem
->UCData
->CursorPos
.Y
!= -1) {
2099 MoveCursor(CurItem
->UCData
->CursorPos
.X
+ CX1
+ X1
,
2100 CurItem
->UCData
->CursorPos
.Y
+ CY1
+ Y1
);
2101 SetCursorType(CurItem
->UCData
->CursorVisible
, CurItem
->UCData
->CursorSize
);
2103 SetCursorType(0, -1);
2107 break; // уже наприсовали :-)))
2108 /* ***************************************************************** */
2115 for (I
= 0; I
< ItemCount
; I
++) {
2118 if (CurItem
->ListPtr
&& GetDropDownOpened() && CurItem
->ListPtr
->IsVisible()) {
2119 if ((CurItem
->Type
== DI_COMBOBOX
)
2120 || ((CurItem
->Type
== DI_EDIT
|| CurItem
->Type
== DI_FIXEDIT
)
2121 && !(CurItem
->Flags
& DIF_HIDDEN
) && (CurItem
->Flags
& DIF_HISTORY
))) {
2122 CurItem
->ListPtr
->Show();
2127 // Включим индикатор перемещения...
2128 if (!DialogMode
.Check(DMODE_DRAGGED
)) // если диалог таскается
2132 + При каждой перерисовке диалога, кроме режима перемещения, устанавливаем
2133 заголовок консоли, в противном случае он не всегда восстанавливался.
2135 if (!DialogMode
.Check(DMODE_KEEPCONSOLETITLE
))
2136 ConsoleTitle::SetFarTitle(GetDialogTitle());
2139 DialogMode
.Clear(DMODE_DRAWING
); // конец отрисовки диалога!!!
2140 DialogMode
.Set(DMODE_SHOW
); // диалог на экране!
2142 if (DialogMode
.Check(DMODE_DRAGGED
)) {
2144 - BugZ#813 - DM_RESIZEDIALOG в DN_DRAWDIALOG -> проблема: Ctrl-F5 - отрисовка только полозьев.
2145 Убираем вызов плагиновго обработчика.
2147 // DlgProc((HANDLE)this,DN_DRAWDIALOGDONE,1,0);
2148 DefDlgProc((HANDLE
)this, DN_DRAWDIALOGDONE
, 1, 0);
2150 DlgProc((HANDLE
)this, DN_DRAWDIALOGDONE
, 0, 0);
2153 int Dialog::LenStrItem(int ID
, const wchar_t *lpwszStr
)
2155 CriticalSectionLock
Lock(CS
);
2158 lpwszStr
= Item
[ID
]->strData
;
2160 return (Item
[ID
]->Flags
& DIF_SHOWAMPERSAND
) ? StrZCellsCount(lpwszStr
) : HiStrCellsCount(lpwszStr
);
2163 int Dialog::ProcessMoveDialog(DWORD Key
)
2165 CriticalSectionLock
Lock(CS
);
2167 if (DialogMode
.Check(DMODE_DRAGGED
)) // если диалог таскается
2170 TODO: Здесь проверить "уже здесь" и не делать лишних движений
2171 Т.е., если нажали End, то при следующем End ненужно ничего делать! - сравнить координаты !!!
2175 // При перемещении диалога повторяем поведение "бормандовых" сред.
2178 case KEY_CTRLNUMPAD4
:
2180 case KEY_CTRLNUMPAD7
:
2183 rr
= Key
== KEY_CTRLLEFT
|| Key
== KEY_CTRLNUMPAD4
? 10 : X1
;
2188 for (int i
= 0; i
< rr
; i
++)
2192 AdjustEditPos(-1, 0);
2195 if (!DialogMode
.Check(DMODE_ALTDRAGGED
))
2200 case KEY_CTRLNUMPAD6
:
2202 case KEY_CTRLNUMPAD1
:
2205 rr
= Key
== KEY_CTRLRIGHT
|| Key
== KEY_CTRLNUMPAD6
? 10 : Max(0, ScrX
- X2
);
2210 for (int i
= 0; i
< rr
; i
++)
2214 AdjustEditPos(1, 0);
2217 if (!DialogMode
.Check(DMODE_ALTDRAGGED
))
2224 case KEY_CTRLNUMPAD9
:
2226 case KEY_CTRLNUMPAD8
:
2227 rr
= Key
== KEY_CTRLUP
|| Key
== KEY_CTRLNUMPAD8
? 5 : Y1
;
2232 for (int i
= 0; i
< rr
; i
++)
2236 AdjustEditPos(0, -1);
2239 if (!DialogMode
.Check(DMODE_ALTDRAGGED
))
2244 case KEY_CTRLNUMPAD2
:
2246 case KEY_CTRLNUMPAD3
:
2249 rr
= Key
== KEY_CTRLDOWN
|| Key
== KEY_CTRLNUMPAD2
? 5 : Max(0, ScrY
- Y2
);
2254 for (int i
= 0; i
< rr
; i
++)
2258 AdjustEditPos(0, 1);
2261 if (!DialogMode
.Check(DMODE_ALTDRAGGED
))
2268 DialogMode
.Clear(DMODE_DRAGGED
); // закончим движение!
2270 if (!DialogMode
.Check(DMODE_ALTDRAGGED
)) {
2271 DlgProc((HANDLE
)this, DN_DRAGGED
, 1, 0);
2278 AdjustEditPos(OldX1
- X1
, OldY1
- Y1
);
2283 DialogMode
.Clear(DMODE_DRAGGED
);
2285 if (!DialogMode
.Check(DMODE_ALTDRAGGED
)) {
2286 DlgProc((HANDLE
)this, DN_DRAGGED
, 1, TRUE
);
2293 if (DialogMode
.Check(DMODE_ALTDRAGGED
)) {
2294 DialogMode
.Clear(DMODE_DRAGGED
| DMODE_ALTDRAGGED
);
2295 DlgProc((HANDLE
)this, DN_DRAGGED
, 1, 0);
2302 if (Key
== KEY_CTRLF5
&& DialogMode
.Check(DMODE_ISCANMOVE
)) {
2303 if (DlgProc((HANDLE
)this, DN_DRAGGED
, 0, 0)) // если разрешили перемещать!
2305 // включаем флаг и запоминаем координаты
2306 DialogMode
.Set(DMODE_DRAGGED
);
2311 // # GetText(0,0,3,0,LV);
2321 int64_t Dialog::VMProcess(MacroOpcode OpCode
, void *vParam
, int64_t iParam
)
2324 case MCODE_F_MENU_CHECKHOTKEY
:
2325 case MCODE_F_MENU_GETHOTKEY
:
2326 case MCODE_F_MENU_SELECT
:
2327 case MCODE_F_MENU_GETVALUE
:
2328 case MCODE_F_MENU_ITEMSTATUS
:
2329 case MCODE_V_MENU_VALUE
: {
2330 const wchar_t *str
= (const wchar_t *)vParam
;
2332 if (GetDropDownOpened() || Item
[FocusPos
]->Type
== DI_LISTBOX
) {
2333 if (Item
[FocusPos
]->ListPtr
)
2334 return Item
[FocusPos
]->ListPtr
->VMProcess(OpCode
, vParam
, iParam
);
2335 } else if (OpCode
== MCODE_F_MENU_CHECKHOTKEY
)
2336 return (int64_t)(CheckHighlights(*str
, (int)iParam
) + 1);
2345 case MCODE_C_SELECTED
:
2346 case MCODE_C_EMPTY
: {
2347 if (FarIsEdit(Item
[FocusPos
]->Type
)) {
2348 if (Item
[FocusPos
]->Type
== DI_COMBOBOX
&& GetDropDownOpened())
2349 return Item
[FocusPos
]->ListPtr
->VMProcess(OpCode
, vParam
, iParam
);
2351 return ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->VMProcess(OpCode
, vParam
, iParam
);
2352 } else if (Item
[FocusPos
]->Type
== DI_LISTBOX
&& OpCode
!= MCODE_C_SELECTED
)
2353 return Item
[FocusPos
]->ListPtr
->VMProcess(OpCode
, vParam
, iParam
);
2357 case MCODE_V_DLGITEMTYPE
: {
2358 switch (Item
[FocusPos
]->Type
) {
2360 return 7; // Кнопка (Push Button).
2362 return 8; // Контрольный переключатель (Check Box).
2364 return (DropDownOpened
? 0x800A : 10); // Комбинированный список.
2366 return 3; // Двойная рамка.
2368 return DropDownOpened
? 0x8004 : 4; // Поле ввода.
2370 return 6; // Поле ввода фиксированного размера.
2372 return 11; // Окно списка.
2374 return 5; // Поле ввода пароля.
2375 case DI_RADIOBUTTON
:
2376 return 9; // Селекторная кнопка (Radio Button).
2378 return 2; // Одиночная рамка.
2380 return 0; // Текстовая строка.
2381 case DI_USERCONTROL
:
2382 return 255; // Элемент управления, определяемый программистом.
2384 return 1; // Вертикальная текстовая строка.
2389 case MCODE_V_DLGITEMCOUNT
: // Dlg.ItemCount
2393 case MCODE_V_DLGCURPOS
: // Dlg.CurPos
2395 return FocusPos
+ 1;
2397 case MCODE_V_DLGINFOID
: // Dlg.Info.Id
2399 static FARString strId
;
2400 strId
.Format(L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", Id
.Data1
, Id
.Data2
, Id
.Data3
,
2401 Id
.Data4
[0], Id
.Data4
[1], Id
.Data4
[2], Id
.Data4
[3], Id
.Data4
[4], Id
.Data4
[5], Id
.Data4
[6],
2403 return reinterpret_cast<INT64
>(strId
.CPtr());
2405 case MCODE_V_ITEMCOUNT
:
2406 case MCODE_V_CURPOS
: {
2407 switch (Item
[FocusPos
]->Type
) {
2410 if (DropDownOpened
|| (Item
[FocusPos
]->Flags
& DIF_DROPDOWNLIST
))
2411 return Item
[FocusPos
]->ListPtr
->VMProcess(OpCode
, vParam
, iParam
);
2416 return ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->VMProcess(OpCode
, vParam
, iParam
);
2418 return Item
[FocusPos
]->ListPtr
->VMProcess(OpCode
, vParam
, iParam
);
2419 case DI_USERCONTROL
:
2421 if (OpCode
== MCODE_V_CURPOS
)
2422 return Item
[FocusPos
]->UCData
->CursorPos
.X
;
2426 case DI_RADIOBUTTON
:
2432 case MCODE_F_EDITOR_SEL
: {
2433 if (FarIsEdit(Item
[FocusPos
]->Type
)
2434 || (Item
[FocusPos
]->Type
== DI_COMBOBOX
2435 && !(DropDownOpened
|| (Item
[FocusPos
]->Flags
& DIF_DROPDOWNLIST
)))) {
2436 return ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->VMProcess(OpCode
, vParam
, iParam
);
2446 //////////////////////////////////////////////////////////////////////////
2449 Обработка данных от клавиатуры.
2450 Перекрывает BaseInput::ProcessKey.
2452 int Dialog::ProcessKey(FarKey Key
)
2454 CriticalSectionLock
Lock(CS
);
2455 _DIALOG(CleverSysLog
CL(L
"Dialog::ProcessKey"));
2456 _DIALOG(SysLog(L
"Param: Key=%ls", _FARKEY_ToName(Key
)));
2460 if (Key
== KEY_NONE
|| Key
== KEY_IDLE
) {
2461 DlgProc((HANDLE
)this, DN_ENTERIDLE
, 0, 0); // $ 28.07.2000 SVS Передадим этот факт в обработчик :-)
2465 if (Key
== KEY_KILLFOCUS
|| Key
== KEY_GOTFOCUS
) {
2466 DlgProc((HANDLE
)this, DN_ACTIVATEAPP
, Key
== KEY_KILLFOCUS
? FALSE
: TRUE
, 0);
2470 if (ProcessMoveDialog(Key
))
2473 // BugZ#488 - Shift=enter
2474 if (ShiftPressed
&& (Key
== KEY_ENTER
|| Key
== KEY_NUMENTER
) && !CtrlObject
->Macro
.IsExecuting()
2475 && Item
[FocusPos
]->Type
!= DI_BUTTON
) {
2476 Key
= Key
== KEY_ENTER
? KEY_SHIFTENTER
: KEY_SHIFTNUMENTER
;
2480 /*(Key>=KEY_MACRO_BASE && Key <=KEY_MACRO_ENDBASE) ||*/
2481 ((unsigned int)Key
>= KEY_OP_BASE
&& (unsigned int)Key
<= KEY_OP_ENDBASE
))
2482 && !DialogMode
.Check(DMODE_KEY
))
2483 if (DlgProc((HANDLE
)this, DN_KEY
, FocusPos
, Key
))
2486 if (!DialogMode
.Check(DMODE_SHOW
))
2489 // А ХЗ, может в этот момент изменилось состояние элемента!
2490 if (Item
[FocusPos
]->Flags
& DIF_HIDDEN
)
2493 // небольшая оптимизация
2494 if (Item
[FocusPos
]->Type
== DI_CHECKBOX
) {
2495 if (!(Item
[FocusPos
]->Flags
& DIF_3STATE
)) {
2496 if (Key
== KEY_MULTIPLY
) // в CheckBox 2-state Gray* не работает!
2499 if ((Key
== KEY_ADD
&& !Item
[FocusPos
]->Selected
)
2500 || (Key
== KEY_SUBTRACT
&& Item
[FocusPos
]->Selected
))
2504 // блок else не нужен, т.к. ниже клавиши будут обработаны...
2505 } else if (Key
== KEY_ADD
)
2507 else if (Key
== KEY_SUBTRACT
)
2509 else if (Key
== KEY_MULTIPLY
)
2512 if (Item
[FocusPos
]->Type
== DI_BUTTON
&& Key
== KEY_SPACE
)
2515 if (Item
[FocusPos
]->Type
== DI_LISTBOX
) {
2533 case KEY_MSWHEEL_UP
:
2534 case KEY_MSWHEEL_DOWN
:
2535 case KEY_MSWHEEL_LEFT
:
2536 case KEY_MSWHEEL_RIGHT
:
2539 VMenu
*List
= Item
[FocusPos
]->ListPtr
;
2540 int CurListPos
= List
->GetSelectPos();
2541 auto CheckedListItem
= List
->GetCheck(-1);
2542 List
->ProcessKey(Key
);
2543 int NewListPos
= List
->GetSelectPos();
2545 if (NewListPos
!= CurListPos
&& !DlgProc((HANDLE
)this, DN_LISTCHANGE
, FocusPos
, NewListPos
)) {
2546 if (!DialogMode
.Check(DMODE_SHOW
))
2549 List
->SetCheck(CheckedListItem
, CurListPos
);
2551 if (DialogMode
.Check(DMODE_SHOW
) && !(Item
[FocusPos
]->Flags
& DIF_HIDDEN
))
2552 ShowDialog(FocusPos
); // FocusPos
2555 if (!(Key
== KEY_ENTER
|| Key
== KEY_NUMENTER
) || (Item
[FocusPos
]->Flags
& DIF_LISTNOCLOSE
))
2564 Перед выводом диалога посылаем сообщение в обработчик
2565 и если вернули что надо, то выводим подсказку
2567 if (!Help::MkTopic(PluginNumber
,
2568 (const wchar_t *)DlgProc((HANDLE
)this, DN_HELP
, FocusPos
,
2569 (HelpTopic
? (LONG_PTR
)HelpTopic
: 0)),
2572 Help::Present(strStr
);
2579 ExitCode
= (Key
== KEY_BREAK
) ? -2 : -1;
2585 if (Item
[FocusPos
]->Type
== DI_USERCONTROL
) // для user-типа вываливаем
2588 return Do_ProcessFirstCtrl();
2591 return Do_ProcessTab(Key
== KEY_TAB
);
2593 return Do_ProcessSpace();
2594 case KEY_CTRLNUMENTER
:
2595 case KEY_CTRLENTER
: {
2596 for (I
= 0; I
< ItemCount
; I
++)
2597 if (Item
[I
]->DefaultButton
) {
2598 if (Item
[I
]->Flags
& DIF_DISABLE
) {
2599 // ProcessKey(KEY_DOWN); // на твой вкус :-)
2603 if (!FarIsEdit(Item
[I
]->Type
))
2604 Item
[I
]->Selected
= 1;
2607 /* $ 18.05.2001 DJ */
2613 if (!DialogMode
.Check(DMODE_OLDSTYLE
)) {
2614 DialogMode
.Clear(DMODE_ENDLOOP
); // только если есть
2615 return TRUE
; // делать больше не чего
2620 if (Item
[FocusPos
]->Type
!= DI_COMBOBOX
&& FarIsEdit(Item
[FocusPos
]->Type
)
2621 && (Item
[FocusPos
]->Flags
& DIF_EDITOR
) && !(Item
[FocusPos
]->Flags
& DIF_READONLY
)) {
2622 unsigned EditorLastPos
;
2624 for (EditorLastPos
= I
= FocusPos
; I
< ItemCount
; I
++)
2625 if (FarIsEdit(Item
[I
]->Type
) && (Item
[I
]->Flags
& DIF_EDITOR
))
2630 if (((DlgEdit
*)(Item
[EditorLastPos
]->ObjPtr
))->GetLength())
2633 for (I
= EditorLastPos
; I
> FocusPos
; I
--) {
2636 if (I
== FocusPos
+ 1)
2637 CurPos
= ((DlgEdit
*)(Item
[I
- 1]->ObjPtr
))->GetCurPos();
2641 ((DlgEdit
*)(Item
[I
- 1]->ObjPtr
))->GetString(strStr
);
2642 int Length
= (int)strStr
.GetLength();
2643 ((DlgEdit
*)(Item
[I
]->ObjPtr
))
2644 ->SetString(CurPos
>= Length
? L
"" : strStr
.CPtr() + CurPos
);
2646 if (CurPos
< Length
)
2647 strStr
.Truncate(CurPos
);
2649 ((DlgEdit
*)(Item
[I
]->ObjPtr
))->SetCurPos(0);
2650 ((DlgEdit
*)(Item
[I
- 1]->ObjPtr
))->SetString(strStr
);
2653 if (EditorLastPos
> FocusPos
) {
2654 ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->SetCurPos(0);
2655 Do_ProcessNextCtrl(FALSE
, FALSE
);
2660 } else if (Item
[FocusPos
]->Type
== DI_BUTTON
) {
2661 Item
[FocusPos
]->Selected
= 1;
2663 // сообщение - "Кнокна кликнута"
2664 if (SendDlgMessage((HANDLE
)this, DN_BTNCLICK
, FocusPos
, 0))
2667 if (Item
[FocusPos
]->Flags
& DIF_BTNNOCLOSE
)
2670 ExitCode
= FocusPos
;
2676 for (I
= 0; I
< ItemCount
; I
++) {
2677 if (Item
[I
]->DefaultButton
&& !(Item
[I
]->Flags
& DIF_BTNNOCLOSE
)) {
2678 if (Item
[I
]->Flags
& DIF_DISABLE
) {
2679 // ProcessKey(KEY_DOWN); // на твой вкус :-)
2683 // if (!(FarIsEdit(Item[I].Type) || Item[I].Type == DI_CHECKBOX || Item[I].Type == DI_RADIOBUTTON))
2684 // Item[I].Selected=1;
2692 ExitCode
= FocusPos
;
2698 3-х уровневое состояние
2699 Для чекбокса сюда попадем только в случае, если контрол
2700 имеет флаг DIF_3STATE
2706 if (Item
[FocusPos
]->Type
== DI_CHECKBOX
) {
2707 unsigned int CHKState
= (Key
== KEY_ADD
2709 : (Key
== KEY_SUBTRACT
2711 : ((Key
== KEY_MULTIPLY
) ? 2 : Item
[FocusPos
]->Selected
)));
2713 if (Item
[FocusPos
]->Selected
!= (int)CHKState
)
2714 if (SendDlgMessage((HANDLE
)this, DN_BTNCLICK
, FocusPos
, CHKState
)) {
2715 Item
[FocusPos
]->Selected
= CHKState
;
2723 case KEY_SHIFTNUMPAD4
:
2724 case KEY_MSWHEEL_LEFT
:
2727 case KEY_SHIFTNUMPAD6
:
2728 case KEY_MSWHEEL_RIGHT
: {
2729 if (Item
[FocusPos
]->Type
== DI_USERCONTROL
) // для user-типа вываливаем
2732 if (FarIsEdit(Item
[FocusPos
]->Type
)) {
2733 ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->ProcessKey(Key
);
2736 int MinDist
= 1000, MinPos
= 0;
2738 for (I
= 0; I
< ItemCount
; I
++) {
2739 if (I
!= FocusPos
&& (!(Item
[I
]->Flags
& (DIF_NOFOCUS
| DIF_DISABLE
| DIF_HIDDEN
)))
2740 && (FarIsEdit(Item
[I
]->Type
) || Item
[I
]->Type
== DI_CHECKBOX
2741 || Item
[I
]->Type
== DI_RADIOBUTTON
)
2742 && Item
[I
]->Y1
== Item
[FocusPos
]->Y1
) {
2743 int Dist
= Item
[I
]->X1
- Item
[FocusPos
]->X1
;
2745 if (((Key
== KEY_LEFT
|| Key
== KEY_SHIFTNUMPAD4
) && Dist
< 0)
2746 || ((Key
== KEY_RIGHT
|| Key
== KEY_SHIFTNUMPAD6
) && Dist
> 0))
2747 if (abs(Dist
) < MinDist
) {
2748 MinDist
= abs(Dist
);
2754 if (MinDist
< 1000) {
2755 ChangeFocus2(MinPos
);
2757 if (Item
[MinPos
]->Flags
& DIF_MOVESELECT
) {
2772 if (Item
[FocusPos
]->Type
== DI_USERCONTROL
) // для user-типа вываливаем
2775 return Do_ProcessNextCtrl(
2776 Key
== KEY_LEFT
|| Key
== KEY_UP
|| Key
== KEY_NUMPAD4
|| Key
== KEY_NUMPAD8
);
2777 // $ 27.04.2001 VVM - Обработка колеса мышки
2778 case KEY_MSWHEEL_UP
:
2779 case KEY_MSWHEEL_DOWN
:
2781 case KEY_CTRLNUMPAD8
:
2783 case KEY_CTRLNUMPAD2
:
2784 return ProcessOpenComboBox(Item
[FocusPos
]->Type
, Item
[FocusPos
], FocusPos
);
2785 // ЭТО перед default предпоследний!!!
2789 if (Item
[FocusPos
]->Type
== DI_USERCONTROL
) // для user-типа вываливаем
2792 if (FarIsEdit(Item
[FocusPos
]->Type
)) {
2793 ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->ProcessKey(Key
);
2798 // ЭТО перед default последний!!!
2802 if (Item
[FocusPos
]->Type
== DI_USERCONTROL
) // для user-типа вываливаем
2805 if (!(Item
[FocusPos
]->Flags
& DIF_EDITOR
)) {
2806 for (I
= 0; I
< ItemCount
; I
++)
2807 if (Item
[I
]->DefaultButton
) {
2818 if (!CheckDialogMode(DMODE_NOPLUGINS
)) {
2819 return FrameManager
->ProcessKey(Key
);
2823 // для DIF_EDITOR будет обработано ниже
2825 // if(Item[FocusPos].Type == DI_USERCONTROL) // для user-типа вываливаем
2827 if (Item
[FocusPos
]->Type
== DI_LISTBOX
) {
2828 VMenu
*List
= Item
[FocusPos
]->ListPtr
;
2829 int CurListPos
= List
->GetSelectPos();
2830 auto CheckedListItem
= List
->GetCheck(-1);
2831 List
->ProcessKey(Key
);
2832 int NewListPos
= List
->GetSelectPos();
2834 if (NewListPos
!= CurListPos
&& !DlgProc((HANDLE
)this, DN_LISTCHANGE
, FocusPos
, NewListPos
)) {
2835 if (!DialogMode
.Check(DMODE_SHOW
))
2838 List
->SetCheck(CheckedListItem
, CurListPos
);
2840 if (DialogMode
.Check(DMODE_SHOW
) && !(Item
[FocusPos
]->Flags
& DIF_HIDDEN
))
2841 ShowDialog(FocusPos
); // FocusPos
2847 if (FarIsEdit(Item
[FocusPos
]->Type
)) {
2848 DlgEdit
*edt
= (DlgEdit
*)Item
[FocusPos
]->ObjPtr
;
2850 if (Key
== KEY_CTRLL
) // исключим смену режима RO для поля ввода с клавиатуры
2853 } else if (Key
== KEY_CTRLU
) {
2854 edt
->SetClearFlag(0);
2858 } else if ((Item
[FocusPos
]->Flags
& DIF_EDITOR
) && !(Item
[FocusPos
]->Flags
& DIF_READONLY
)) {
2861 int CurPos
= edt
->GetCurPos();
2863 // В начале строки????
2864 if (!edt
->GetCurPos()) {
2865 // а "выше" тоже DIF_EDITOR?
2866 if (FocusPos
> 0 && (Item
[FocusPos
- 1]->Flags
& DIF_EDITOR
)) {
2867 // добавляем к предыдущему и...
2868 DlgEdit
*edt_1
= (DlgEdit
*)Item
[FocusPos
- 1]->ObjPtr
;
2869 edt_1
->GetString(strStr
);
2870 CurPos
= static_cast<int>(strStr
.GetLength());
2872 edt
->GetString(strAdd
);
2874 edt_1
->SetString(strStr
);
2876 for (I
= FocusPos
+ 1; I
< ItemCount
; I
++) {
2877 if (Item
[I
]->Flags
& DIF_EDITOR
) {
2879 ((DlgEdit
*)(Item
[I
]->ObjPtr
))->GetString(strStr
);
2880 ((DlgEdit
*)(Item
[I
- 1]->ObjPtr
))->SetString(strStr
);
2883 ((DlgEdit
*)(Item
[I
]->ObjPtr
))->SetString(L
"");
2884 } else // ага, значит FocusPos это есть последний из DIF_EDITOR
2886 ((DlgEdit
*)(Item
[I
- 1]->ObjPtr
))->SetString(L
"");
2891 Do_ProcessNextCtrl(TRUE
);
2892 edt_1
->SetCurPos(CurPos
);
2895 edt
->ProcessKey(Key
);
2902 for (I
= FocusPos
; I
< ItemCount
; I
++)
2903 if (Item
[I
]->Flags
& DIF_EDITOR
) {
2905 ((DlgEdit
*)(Item
[I
]->ObjPtr
))->GetString(strStr
);
2906 ((DlgEdit
*)(Item
[I
- 1]->ObjPtr
))->SetString(strStr
);
2909 ((DlgEdit
*)(Item
[I
]->ObjPtr
))->SetString(L
"");
2920 ! "...В редакторе команд меню нажмите home shift+end del
2921 блок не удаляется..."
2922 DEL у итемов, имеющих DIF_EDITOR, работал без учета
2925 if (FocusPos
< ItemCount
+ 1 && (Item
[FocusPos
+ 1]->Flags
& DIF_EDITOR
)) {
2926 int CurPos
= edt
->GetCurPos();
2927 int Length
= edt
->GetLength();
2928 int SelStart
, SelEnd
;
2929 edt
->GetSelection(SelStart
, SelEnd
);
2930 edt
->GetString(strStr
);
2932 if (SelStart
> -1) {
2933 FARString strEnd
= strStr
.CPtr() + SelEnd
;
2934 strStr
.Truncate(SelStart
);
2936 edt
->SetString(strStr
);
2937 edt
->SetCurPos(SelStart
);
2940 } else if (CurPos
>= Length
) {
2941 DlgEdit
*edt_1
= (DlgEdit
*)Item
[FocusPos
+ 1]->ObjPtr
;
2945 Решаем проблему, если Del нажали в позиции
2946 большей, чем длина строки
2948 if (CurPos
> Length
) {
2949 strStr
.Append(L
' ', CurPos
- Length
);
2953 edt_1
->GetString(strAdd
);
2954 edt_1
->SetString(strStr
+ strAdd
);
2955 ProcessKey(KEY_CTRLY
);
2956 edt
->SetCurPos(CurPos
);
2970 while (Item
[I
]->Flags
& DIF_EDITOR
)
2971 I
= ChangeFocus(I
, (Key
== KEY_PGUP
|| Key
== KEY_NUMPAD9
) ? -1 : 1, FALSE
);
2973 if (!(Item
[I
]->Flags
& DIF_EDITOR
))
2974 I
= ChangeFocus(I
, (Key
== KEY_PGUP
|| Key
== KEY_NUMPAD9
) ? 1 : -1, FALSE
);
2984 if (Key
== KEY_OP_XLAT
&& !(Item
[FocusPos
]->Flags
& DIF_READONLY
)) {
2985 edt
->SetClearFlag(0);
2988 // иначе неправильно работает ctrl-end
2989 edt
->strLastStr
= edt
->GetStringAddr();
2990 edt
->LastPartLength
= static_cast<int>(edt
->strLastStr
.GetLength());
2992 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
2996 if (!(Item
[FocusPos
]->Flags
& DIF_READONLY
) || IsNavKey(Key
)) {
2997 // "только что ломанулись и начинать выделение с нуля"?
2998 if ((Opt
.Dialogs
.EditLine
& DLGEDITLINE_NEWSELONGOTFOCUS
) && Item
[FocusPos
]->SelStart
!= -1
2999 && PrevFocusPos
!= FocusPos
) { // && Item[FocusPos].SelEnd)
3001 edt
->Flags().Clear(FEDITLINE_MARKINGBLOCK
);
3002 PrevFocusPos
= FocusPos
;
3005 if (edt
->ProcessKey(Key
)) {
3006 if (Item
[FocusPos
]->Flags
& DIF_READONLY
)
3009 if ((Key
== KEY_CTRLEND
|| Key
== KEY_CTRLNUMPAD1
)
3010 && edt
->GetCurPos() == edt
->GetLength()) {
3011 if (edt
->LastPartLength
== -1)
3012 edt
->strLastStr
= edt
->GetStringAddr();
3014 strStr
= edt
->strLastStr
;
3015 int CurCmdPartLength
= static_cast<int>(strStr
.GetLength());
3016 edt
->HistoryGetSimilar(strStr
, edt
->LastPartLength
);
3018 if (edt
->LastPartLength
== -1) {
3019 edt
->strLastStr
= edt
->GetStringAddr();
3020 edt
->LastPartLength
= CurCmdPartLength
;
3023 edt
->SetString(strStr
);
3024 edt
->Select(edt
->LastPartLength
, static_cast<int>(strStr
.GetLength()));
3030 edt
->LastPartLength
= -1;
3032 if (Key
== KEY_CTRLSHIFTEND
|| Key
== KEY_CTRLSHIFTNUMPAD1
) {
3034 edt
->AutoComplete(true, false);
3038 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3041 } else if (!(Key
& (KEY_ALT
| KEY_RALT
)))
3045 if (ProcessHighlighting(Key
, FocusPos
, FALSE
))
3048 return (Opt
.XLat
.EnableForDialogs
&& ProcessHighlighting(Key
, FocusPos
, TRUE
));
3054 void Dialog::ProcessKey(FarKey Key
, unsigned ItemPos
)
3056 unsigned SavedFocusPos
= FocusPos
;
3059 if (FocusPos
== ItemPos
)
3060 FocusPos
= SavedFocusPos
;
3063 //////////////////////////////////////////////////////////////////////////
3066 Обработка данных от "мыши".
3067 Перекрывает BaseInput::ProcessMouse.
3073 int Dialog::ProcessMouse(MOUSE_EVENT_RECORD
*MouseEvent
)
3075 CriticalSectionLock
Lock(CS
);
3081 if (!DialogMode
.Check(DMODE_SHOW
))
3084 if (DialogMode
.Check(DMODE_MOUSEEVENT
)) {
3085 if (!DlgProc((HANDLE
)this, DN_MOUSEEVENT
, 0, (LONG_PTR
)MouseEvent
))
3089 if (!DialogMode
.Check(DMODE_SHOW
))
3092 MsX
= MouseEvent
->dwMousePosition
.X
;
3093 MsY
= MouseEvent
->dwMousePosition
.Y
;
3095 // for (I=0;I<ItemCount;I++)
3096 for (I
= ItemCount
- 1; I
!= (unsigned)-1; I
--) {
3097 if (Item
[I
]->Flags
& (DIF_DISABLE
| DIF_HIDDEN
))
3100 Type
= Item
[I
]->Type
;
3102 if (Type
== DI_LISTBOX
&& MsY
>= Y1
+ Item
[I
]->Y1
&& MsY
<= Y1
+ Item
[I
]->Y2
3103 && MsX
>= X1
+ Item
[I
]->X1
&& MsX
<= X1
+ Item
[I
]->X2
) {
3104 VMenu
*List
= Item
[I
]->ListPtr
;
3105 int Pos
= List
->GetSelectPos();
3106 auto CheckedListItem
= List
->GetCheck(-1);
3108 if ((MouseEvent
->dwButtonState
& FROM_LEFT_1ST_BUTTON_PRESSED
)) {
3109 if (FocusPos
!= I
) {
3114 if (MouseEvent
->dwEventFlags
!= DOUBLE_CLICK
3115 && !(Item
[I
]->IFlags
.Flags
3116 & (DLGIIF_LISTREACTIONFOCUS
| DLGIIF_LISTREACTIONNOFOCUS
))) {
3118 List
->ProcessMouse(MouseEvent
);
3119 int NewListPos
= List
->GetSelectPos();
3121 if (NewListPos
!= Pos
3122 && !SendDlgMessage((HANDLE
)this, DN_LISTCHANGE
, I
, (LONG_PTR
)NewListPos
)) {
3123 List
->SetCheck(CheckedListItem
, Pos
);
3125 if (DialogMode
.Check(DMODE_SHOW
) && !(Item
[I
]->Flags
& DIF_HIDDEN
))
3126 ShowDialog(I
); // FocusPos
3130 } else if (!SendDlgMessage((HANDLE
)this, DN_MOUSECLICK
, I
, (LONG_PTR
)MouseEvent
)) {
3132 List
->ProcessMouse(MouseEvent
);
3133 int NewListPos
= List
->GetSelectPos();
3135 (MsX
== X1
+ Item
[I
]->X2
&& MsY
>= Y1
+ Item
[I
]->Y1
&& MsY
<= Y1
+ Item
[I
]->Y2
)
3136 && (List
->CheckFlags(VMENU_LISTBOX
| VMENU_ALWAYSSCROLLBAR
)
3137 || Opt
.ShowMenuScrollbar
);
3139 if (!InScroolBar
&& // вне скроллбара и
3140 NewListPos
!= Pos
&& // позиция изменилась и
3141 !SendDlgMessage((HANDLE
)this, DN_LISTCHANGE
, I
, (LONG_PTR
)NewListPos
)) // и плагин сказал в морг
3143 List
->SetCheck(CheckedListItem
, Pos
);
3145 if (DialogMode
.Check(DMODE_SHOW
) && !(Item
[I
]->Flags
& DIF_HIDDEN
))
3146 ShowDialog(I
); // FocusPos
3150 if (!InScroolBar
&& !(Item
[I
]->Flags
& DIF_LISTNOCLOSE
)) {
3159 if (SendDlgMessage((HANDLE
)this, DN_LISTCHANGE
, I
, (LONG_PTR
)Pos
)) {
3160 if (MsX
== X1
+ Item
[I
]->X2
&& MsY
>= Y1
+ Item
[I
]->Y1
&& MsY
<= Y1
+ Item
[I
]->Y2
)
3161 List
->ProcessMouse(MouseEvent
); // забыл проверить на клик на скролбар (KM)
3163 ProcessKey(KEY_ENTER
, I
);
3171 if (!MouseEvent
->dwButtonState
3172 || SendDlgMessage((HANDLE
)this, DN_MOUSECLICK
, I
, (LONG_PTR
)MouseEvent
)) {
3173 if ((I
== FocusPos
&& (Item
[I
]->IFlags
.Flags
& DLGIIF_LISTREACTIONFOCUS
))
3174 || (I
!= FocusPos
&& (Item
[I
]->IFlags
.Flags
& DLGIIF_LISTREACTIONNOFOCUS
))) {
3175 List
->ProcessMouse(MouseEvent
);
3176 int NewListPos
= List
->GetSelectPos();
3178 if (NewListPos
!= Pos
3179 && !SendDlgMessage((HANDLE
)this, DN_LISTCHANGE
, I
, (LONG_PTR
)NewListPos
)) {
3180 List
->SetCheck(CheckedListItem
, Pos
);
3182 if (DialogMode
.Check(DMODE_SHOW
) && !(Item
[I
]->Flags
& DIF_HIDDEN
))
3183 ShowDialog(I
); // FocusPos
3194 if (MsX
< X1
|| MsY
< Y1
|| MsX
> X2
|| MsY
> Y2
) {
3195 if (DialogMode
.Check(DMODE_CLICKOUTSIDE
)
3196 && !DlgProc((HANDLE
)this, DN_MOUSECLICK
, -1, (LONG_PTR
)MouseEvent
)) {
3197 if (!DialogMode
.Check(DMODE_SHOW
))
3200 // if (!(MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) && PrevLButtonPressed && ScreenObject::CaptureMouseObject)
3201 if (!(MouseEvent
->dwButtonState
& FROM_LEFT_1ST_BUTTON_PRESSED
)
3202 && (PrevMouseButtonState
& FROM_LEFT_1ST_BUTTON_PRESSED
)
3203 && (Opt
.Dialogs
.MouseButton
& DMOUSEBUTTON_LEFT
))
3204 ProcessKey(KEY_ESC
);
3205 // else if (!(MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED) && PrevRButtonPressed && ScreenObject::CaptureMouseObject)
3206 else if (!(MouseEvent
->dwButtonState
& RIGHTMOST_BUTTON_PRESSED
)
3207 && (PrevMouseButtonState
& RIGHTMOST_BUTTON_PRESSED
)
3208 && (Opt
.Dialogs
.MouseButton
& DMOUSEBUTTON_RIGHT
))
3209 ProcessKey(KEY_ENTER
);
3212 if (MouseEvent
->dwButtonState
)
3213 DialogMode
.Set(DMODE_CLICKOUTSIDE
);
3215 // ScreenObject::SetCapture(this);
3219 if (!MouseEvent
->dwButtonState
) {
3220 DialogMode
.Clear(DMODE_CLICKOUTSIDE
);
3221 // ScreenObject::SetCapture(nullptr);
3225 if (!MouseEvent
->dwEventFlags
|| MouseEvent
->dwEventFlags
== DOUBLE_CLICK
) {
3226 // первый цикл - все за исключением рамок.
3227 // for (I=0; I < ItemCount;I++)
3228 for (I
= ItemCount
- 1; I
!= (unsigned)-1; I
--) {
3229 if (Item
[I
]->Flags
& (DIF_DISABLE
| DIF_HIDDEN
))
3232 GetItemRect(I
, Rect
);
3237 //_D(SysLog(L"? %2d) Rect (%2d,%2d) (%2d,%2d) '%ls'",I,Rect.left,Rect.top,Rect.right,Rect.bottom,Item[I].Data));
3239 if (MsX
>= Rect
.Left
&& MsY
>= Rect
.Top
&& MsX
<= Rect
.Right
&& MsY
<= Rect
.Bottom
) {
3240 // для прозрачных :-)
3241 if (Item
[I
]->Type
== DI_SINGLEBOX
|| Item
[I
]->Type
== DI_DOUBLEBOX
) {
3242 // если на рамке, то...
3243 if (((MsX
== Rect
.Left
|| MsX
== Rect
.Right
) && MsY
>= Rect
.Top
&& MsY
<= Rect
.Bottom
)
3245 ((MsY
== Rect
.Top
|| MsY
== Rect
.Bottom
) && MsX
>= Rect
.Left
3246 && MsX
<= Rect
.Right
)) // hor
3248 if (DlgProc((HANDLE
)this, DN_MOUSECLICK
, I
, (LONG_PTR
)MouseEvent
))
3251 if (!DialogMode
.Check(DMODE_SHOW
))
3257 if (Item
[I
]->Type
== DI_USERCONTROL
) {
3258 // для user-типа подготовим координаты мыши
3259 MouseEvent
->dwMousePosition
.X
-= Rect
.Left
;
3260 MouseEvent
->dwMousePosition
.Y
-= Rect
.Top
;
3263 //_SVS(SysLog(L"+ %2d) Rect (%2d,%2d) (%2d,%2d) '%ls' Dbl=%d",I,Rect.left,Rect.top,Rect.right,Rect.bottom,Item[I].Data,MouseEvent->dwEventFlags==DOUBLE_CLICK));
3264 if (DlgProc((HANDLE
)this, DN_MOUSECLICK
, I
, (LONG_PTR
)MouseEvent
))
3267 if (!DialogMode
.Check(DMODE_SHOW
))
3270 if (Item
[I
]->Type
== DI_USERCONTROL
) {
3280 if ((MouseEvent
->dwButtonState
& FROM_LEFT_1ST_BUTTON_PRESSED
)) {
3281 // for (I=0;I<ItemCount;I++)
3283 for (I
= ItemCount
- 1; I
!= (unsigned)-1; I
--) {
3284 // Исключаем из списка оповещаемых о мыши недоступные элементы
3285 if (Item
[I
]->Flags
& (DIF_DISABLE
| DIF_HIDDEN
))
3288 Type
= Item
[I
]->Type
;
3290 GetItemRect(I
, Rect
);
3295 if (ItemHasDropDownArrow(Item
[I
]))
3298 if (MsX
>= Rect
.Left
&& MsY
>= Rect
.Top
&& MsX
<= Rect
.Right
&& MsY
<= Rect
.Bottom
) {
3299 /* ********************************************************** */
3300 if (FarIsEdit(Type
)) {
3303 + Сделаем так, чтобы ткнув мышкой в DropDownList
3304 список раскрывался сам.
3305 Есть некоторая глюкавость - когда список раскрыт и мы
3306 мышой переваливаем на другой элемент, то список закрывается
3307 но перехода реального на указанный элемент диалога не происходит
3309 int EditX1
, EditY1
, EditX2
, EditY2
;
3310 DlgEdit
*EditLine
= (DlgEdit
*)(Item
[I
]->ObjPtr
);
3311 EditLine
->GetPosition(EditX1
, EditY1
, EditX2
, EditY2
);
3313 if (MsY
== EditY1
&& Type
== DI_COMBOBOX
&& (Item
[I
]->Flags
& DIF_DROPDOWNLIST
)
3314 && MsX
>= EditX1
&& MsX
<= EditX2
+ 1) {
3315 EditLine
->SetClearFlag(0);
3320 ProcessOpenComboBox(Item
[I
]->Type
, Item
[I
], I
);
3327 if (EditLine
->ProcessMouse(MouseEvent
)) {
3328 EditLine
->SetClearFlag(0); // а может это делать в самом edit?
3332 ! Оказалось нужно перерисовывать весь диалог иначе
3333 не снимался признак активности с комбобокса с которго уходим.
3335 ShowDialog(); // нужен ли только один контрол или весь диалог?
3338 // Проверка на DI_COMBOBOX здесь лишняя. Убрана (KM).
3339 if (MsX
== EditX2
+ 1 && MsY
== EditY1
&& ItemHasDropDownArrow(Item
[I
])) {
3340 EditLine
->SetClearFlag(0); // раз уж покусились на, то и...
3344 if (!(Item
[I
]->Flags
& DIF_HIDDEN
))
3347 ProcessOpenComboBox(Item
[I
]->Type
, Item
[I
], I
);
3354 /* ********************************************************** */
3355 if (Type
== DI_BUTTON
&& MsY
== Y1
+ Item
[I
]->Y1
3356 && MsX
< X1
+ Item
[I
]->X1
+ HiStrCellsCount(Item
[I
]->strData
)) {
3360 while (IsMouseButtonPressed())
3363 if (MouseX
< X1
|| MouseX
> X1
+ Item
[I
]->X1
+ HiStrCellsCount(Item
[I
]->strData
) + 4
3364 || MouseY
!= Y1
+ Item
[I
]->Y1
) {
3371 ProcessKey(KEY_ENTER
, I
);
3375 /* ********************************************************** */
3376 if ((Type
== DI_CHECKBOX
|| Type
== DI_RADIOBUTTON
) && MsY
== Y1
+ Item
[I
]->Y1
3377 && MsX
< (X1
+ Item
[I
]->X1
+ HiStrCellsCount(Item
[I
]->strData
) + 4
3378 - ((Item
[I
]->Flags
& DIF_MOVESELECT
) != 0))) {
3380 ProcessKey(KEY_SPACE
, I
);
3384 } // for (I=0;I<ItemCount;I++)
3386 // ДЛЯ MOUSE-Перемещалки:
3387 // Сюда попадаем в том случае, если мышь не попала на активные элементы
3390 if (DialogMode
.Check(DMODE_ISCANMOVE
)) {
3391 // DialogMode.Set(DMODE_DRAGGED);
3396 // запомним delta места хватания и Left-Top диалогового окна
3397 MsX
= abs(X1
- MouseX
);
3398 MsY
= abs(Y1
- MouseY
);
3399 int NeedSendMsg
= 0;
3402 DWORD Mb
= IsMouseButtonPressed();
3405 if (Mb
== FROM_LEFT_1ST_BUTTON_PRESSED
) // still dragging
3407 int AdjX
= 0, AdjY
= 0;
3415 if (MouseX
== PrevMouseX
)
3420 if (MouseY
== PrevMouseY
)
3425 NX2
= mx
+ (X2
- X1
);
3428 NY2
= my
+ (Y2
- Y1
);
3432 // "А был ли мальчик?" (про холостой ход)
3433 if (OX1
!= NX1
|| OY1
!= NY1
) {
3434 if (!NeedSendMsg
) // тыкс, а уже посылку делали в диалоговую процедуру?
3438 if (!DlgProc((HANDLE
)this, DN_DRAGGED
, 0, 0)) // а может нас обломали?
3439 break; // валим отсель...плагин сказал - в морг перемещения
3441 if (!DialogMode
.Check(DMODE_SHOW
))
3445 // Да, мальчик был. Зачнем...
3455 AdjustEditPos(AdjX
, AdjY
); //?
3460 } else if (Mb
== RIGHTMOST_BUTTON_PRESSED
) // abort
3464 AdjustEditPos(OldX1
- X1
, OldY1
- Y1
);
3469 DialogMode
.Clear(DMODE_DRAGGED
);
3470 DlgProc((HANDLE
)this, DN_DRAGGED
, 1, TRUE
);
3472 if (DialogMode
.Check(DMODE_SHOW
))
3476 } else // release key, drop dialog
3478 if (OldX1
!= X1
|| OldX2
!= X2
|| OldY1
!= Y1
|| OldY2
!= Y2
) {
3480 DialogMode
.Clear(DMODE_DRAGGED
);
3481 DlgProc((HANDLE
)this, DN_DRAGGED
, 1, 0);
3483 if (DialogMode
.Check(DMODE_SHOW
))
3497 int Dialog::ProcessOpenComboBox(int Type
, DialogItemEx
*CurItem
, unsigned CurFocusPos
)
3499 CriticalSectionLock
Lock(CS
);
3501 DlgEdit
*CurEditLine
;
3503 // для user-типа вываливаем
3504 if (Type
== DI_USERCONTROL
)
3507 CurEditLine
= ((DlgEdit
*)(CurItem
->ObjPtr
));
3509 if (FarIsEdit(Type
) && (CurItem
->Flags
& DIF_HISTORY
) && Opt
.Dialogs
.EditHistory
3510 && !CurItem
->strHistory
.IsEmpty() && !(CurItem
->Flags
& DIF_READONLY
)) {
3511 // Передаем то, что в строке ввода в функцию выбора из истории для выделения нужного пункта в истории.
3512 CurEditLine
->GetString(strStr
);
3513 SelectFromEditHistory(CurItem
, CurEditLine
, CurItem
->strHistory
, strStr
);
3515 // $ 18.07.2000 SVS: +обработка DI_COMBOBOX - выбор из списка!
3516 else if (Type
== DI_COMBOBOX
&& CurItem
->ListPtr
&& !(CurItem
->Flags
& DIF_READONLY
)
3517 && CurItem
->ListPtr
->GetItemCount() > 0) //??
3519 SelectFromComboBox(CurItem
, CurEditLine
, CurItem
->ListPtr
);
3525 unsigned Dialog::ProcessRadioButton(unsigned CurRB
)
3527 CriticalSectionLock
Lock(CS
);
3528 unsigned PrevRB
= CurRB
, J
;
3531 for (I
= CurRB
;; I
--) {
3535 if (Item
[I
]->Type
== DI_RADIOBUTTON
&& (Item
[I
]->Flags
& DIF_GROUP
))
3538 if (Item
[I
- 1]->Type
!= DI_RADIOBUTTON
)
3545 При изменении состояния каждого элемента посылаем сообщение
3546 посредством функции SendDlgMessage - в ней делается все!
3548 J
= Item
[I
]->Selected
;
3549 Item
[I
]->Selected
= 0;
3556 } while (I
< ItemCount
&& Item
[I
]->Type
== DI_RADIOBUTTON
&& !(Item
[I
]->Flags
& DIF_GROUP
));
3558 Item
[CurRB
]->Selected
= 1;
3562 При изменении состояния каждого элемента посылаем сообщение
3563 посредством функции SendDlgMessage - в ней делается все!
3565 if (!SendDlgMessage((HANDLE
)this, DN_BTNCLICK
, PrevRB
, 0)
3566 || !SendDlgMessage((HANDLE
)this, DN_BTNCLICK
, CurRB
, 1)) {
3567 // вернем назад, если пользователь не захотел...
3568 Item
[CurRB
]->Selected
= 0;
3569 Item
[PrevRB
]->Selected
= 1;
3576 int Dialog::Do_ProcessFirstCtrl()
3578 CriticalSectionLock
Lock(CS
);
3580 if (FarIsEdit(Item
[FocusPos
]->Type
)) {
3581 ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->ProcessKey(KEY_HOME
);
3584 for (unsigned I
= 0; I
< ItemCount
; I
++)
3585 if (CanGetFocus(Item
[I
]->Type
)) {
3595 int Dialog::Do_ProcessNextCtrl(int Up
, BOOL IsRedraw
)
3597 CriticalSectionLock
Lock(CS
);
3598 unsigned OldPos
= FocusPos
;
3599 unsigned PrevPos
= 0;
3601 if (FarIsEdit(Item
[FocusPos
]->Type
) && (Item
[FocusPos
]->Flags
& DIF_EDITOR
))
3602 PrevPos
= ((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->GetCurPos();
3604 unsigned I
= ChangeFocus(FocusPos
, Up
? -1 : 1, FALSE
);
3605 Item
[FocusPos
]->Focus
= 0;
3609 if (FarIsEdit(Item
[I
]->Type
) && (Item
[I
]->Flags
& DIF_EDITOR
))
3610 ((DlgEdit
*)(Item
[I
]->ObjPtr
))->SetCurPos(PrevPos
);
3612 if (Item
[FocusPos
]->Type
== DI_RADIOBUTTON
&& (Item
[I
]->Flags
& DIF_MOVESELECT
))
3613 ProcessKey(KEY_SPACE
);
3614 else if (IsRedraw
) {
3616 ShowDialog(FocusPos
);
3622 int Dialog::Do_ProcessTab(int Next
)
3624 CriticalSectionLock
Lock(CS
);
3627 if (ItemCount
> 1) {
3628 // Must check for DI_EDIT since DIF_EDITOR and DIF_LISTNOAMPERSAND are equal
3629 if (Item
[FocusPos
]->Type
==DI_EDIT
&& (Item
[FocusPos
]->Flags
& DIF_EDITOR
)) {
3632 while (Item
[I
]->Type
==DI_EDIT
&& (Item
[I
]->Flags
& DIF_EDITOR
))
3633 I
= ChangeFocus(I
, Next
? 1 : -1, TRUE
);
3635 I
= ChangeFocus(FocusPos
, Next
? 1 : -1, TRUE
);
3639 && Item
[I
]->Type
== DI_EDIT
&& Item
[I
- 1]->Type
== DI_EDIT
3640 && (Item
[I
]->Flags
& DIF_EDITOR
) && (Item
[I
- 1]->Flags
& DIF_EDITOR
)
3641 && !((DlgEdit
*)Item
[I
]->ObjPtr
)->GetLength())
3653 int Dialog::Do_ProcessSpace()
3655 CriticalSectionLock
Lock(CS
);
3658 if (Item
[FocusPos
]->Type
== DI_CHECKBOX
) {
3659 int OldSelected
= Item
[FocusPos
]->Selected
;
3661 if (Item
[FocusPos
]->Flags
& DIF_3STATE
) {
3662 Item
[FocusPos
]->Selected
= (Item
[FocusPos
]->Selected
+ 1) % 3;
3664 Item
[FocusPos
]->Selected
= !Item
[FocusPos
]->Selected
;
3666 OldFocusPos
= FocusPos
;
3668 if (!SendDlgMessage((HANDLE
)this, DN_BTNCLICK
, FocusPos
, Item
[FocusPos
]->Selected
))
3669 Item
[OldFocusPos
]->Selected
= OldSelected
;
3673 } else if (Item
[FocusPos
]->Type
== DI_RADIOBUTTON
) {
3674 FocusPos
= ProcessRadioButton(FocusPos
);
3677 } else if (FarIsEdit(Item
[FocusPos
]->Type
) && !(Item
[FocusPos
]->Flags
& DIF_READONLY
)) {
3678 if (((DlgEdit
*)(Item
[FocusPos
]->ObjPtr
))->ProcessKey(KEY_SPACE
)) {
3679 Redraw(); // Перерисовка должна идти после DN_EDITCHANGE (imho)
3688 //////////////////////////////////////////////////////////////////////////
3691 Изменяет фокус ввода (воздействие клавишами
3692 KEY_TAB, KEY_SHIFTTAB, KEY_UP, KEY_DOWN,
3693 а так же Alt-HotKey)
3697 Довесок для сообщений DN_KILLFOCUS & DN_SETFOCUS
3701 Добавка для DI_USERCONTROL
3703 unsigned Dialog::ChangeFocus(unsigned CurFocusPos
, int Step
, int SkipGroup
)
3705 CriticalSectionLock
Lock(CS
);
3707 unsigned OrigFocusPos
= CurFocusPos
;
3708 // int FucusPosNeed=-1;
3709 // В функцию обработки диалога здесь передаем сообщение,
3710 // что элемент - LostFocus() - теряет фокус ввода.
3711 // if(DialogMode.Check(DMODE_INITOBJECTS))
3712 // FucusPosNeed=DlgProc((HANDLE)this,DN_KILLFOCUS,FocusPos,0);
3713 // if(FucusPosNeed != -1 && CanGetFocus(Item[FucusPosNeed].Type))
3714 // FocusPos=FucusPosNeed;
3720 if ((int)CurFocusPos
< 0)
3721 CurFocusPos
= ItemCount
- 1;
3723 if (CurFocusPos
>= ItemCount
)
3726 Type
= Item
[CurFocusPos
]->Type
;
3728 if (!(Item
[CurFocusPos
]->Flags
& (DIF_NOFOCUS
| DIF_DISABLE
| DIF_HIDDEN
))) {
3729 if (Type
== DI_LISTBOX
|| Type
== DI_BUTTON
|| Type
== DI_CHECKBOX
|| FarIsEdit(Type
)
3730 || Type
== DI_USERCONTROL
)
3733 if (Type
== DI_RADIOBUTTON
&& (!SkipGroup
|| Item
[CurFocusPos
]->Selected
))
3737 // убираем зацикливание с последующим подвисанием :-)
3738 if (OrigFocusPos
== CurFocusPos
)
3742 // Dialog::FocusPos=FocusPos;
3743 // В функцию обработки диалога здесь передаем сообщение,
3744 // что элемент GotFocus() - получил фокус ввода.
3745 // Игнорируем возвращаемое функцией диалога значение
3746 // if(DialogMode.Check(DMODE_INITOBJECTS))
3747 // DlgProc((HANDLE)this,DN_GOTFOCUS,FocusPos,0);
3748 return (CurFocusPos
);
3751 //////////////////////////////////////////////////////////////////////////
3754 Изменяет фокус ввода между двумя элементами.
3755 Вынесен отдельно с тем, чтобы обработать DN_KILLFOCUS & DM_SETFOCUS
3757 void Dialog::ChangeFocus2(unsigned SetFocusPos
)
3759 CriticalSectionLock
Lock(CS
);
3760 int FocusPosNeed
= -1;
3762 if (!(Item
[SetFocusPos
]->Flags
& (DIF_NOFOCUS
| DIF_DISABLE
| DIF_HIDDEN
))) {
3763 if (DialogMode
.Check(DMODE_INITOBJECTS
)) {
3764 FocusPosNeed
= (int)DlgProc((HANDLE
)this, DN_KILLFOCUS
, FocusPos
, 0);
3766 if (!DialogMode
.Check(DMODE_SHOW
))
3770 if (FocusPosNeed
!= -1 && CanGetFocus(Item
[FocusPosNeed
]->Type
))
3771 SetFocusPos
= FocusPosNeed
;
3773 Item
[FocusPos
]->Focus
= 0;
3775 // "снимать выделение при потере фокуса?"
3776 if (FarIsEdit(Item
[FocusPos
]->Type
)
3777 && !(Item
[FocusPos
]->Type
== DI_COMBOBOX
&& (Item
[FocusPos
]->Flags
& DIF_DROPDOWNLIST
))) {
3778 DlgEdit
*EditPtr
= (DlgEdit
*)Item
[FocusPos
]->ObjPtr
;
3779 EditPtr
->GetSelection(Item
[FocusPos
]->SelStart
, Item
[FocusPos
]->SelEnd
);
3781 if ((Opt
.Dialogs
.EditLine
& DLGEDITLINE_CLEARSELONKILLFOCUS
)) {
3782 EditPtr
->Select(-1, 0);
3786 Item
[SetFocusPos
]->Focus
= 1;
3788 // "не восстанавливать выделение при получении фокуса?"
3789 if (FarIsEdit(Item
[SetFocusPos
]->Type
)
3790 && !(Item
[SetFocusPos
]->Type
== DI_COMBOBOX
3791 && (Item
[SetFocusPos
]->Flags
& DIF_DROPDOWNLIST
))) {
3792 DlgEdit
*EditPtr
= (DlgEdit
*)Item
[SetFocusPos
]->ObjPtr
;
3794 if (!(Opt
.Dialogs
.EditLine
& DLGEDITLINE_NOTSELONGOTFOCUS
)) {
3795 if (Opt
.Dialogs
.EditLine
& DLGEDITLINE_SELALLGOTFOCUS
)
3796 EditPtr
->Select(0, EditPtr
->GetStrSize());
3798 EditPtr
->Select(Item
[SetFocusPos
]->SelStart
, Item
[SetFocusPos
]->SelEnd
);
3800 EditPtr
->Select(-1, 0);
3803 // при получении фокуса ввода переместить курсор в конец строки?
3804 if (Opt
.Dialogs
.EditLine
& DLGEDITLINE_GOTOEOLGOTFOCUS
) {
3805 EditPtr
->SetCurPos(EditPtr
->GetStrSize());
3809 // проинформируем листбокс, есть ли у него фокус
3810 if (Item
[FocusPos
]->Type
== DI_LISTBOX
)
3811 Item
[FocusPos
]->ListPtr
->ClearFlags(VMENU_LISTHASFOCUS
);
3813 if (Item
[SetFocusPos
]->Type
== DI_LISTBOX
)
3814 Item
[SetFocusPos
]->ListPtr
->SetFlags(VMENU_LISTHASFOCUS
);
3816 SelectOnEntry(FocusPos
, FALSE
);
3817 SelectOnEntry(SetFocusPos
, TRUE
);
3819 PrevFocusPos
= FocusPos
;
3820 FocusPos
= SetFocusPos
;
3822 if (DialogMode
.Check(DMODE_INITOBJECTS
))
3823 DlgProc((HANDLE
)this, DN_GOTFOCUS
, FocusPos
, 0);
3828 Функция SelectOnEntry - выделение строки редактирования
3829 Обработка флага DIF_SELECTONENTRY
3831 void Dialog::SelectOnEntry(unsigned Pos
, BOOL Selected
)
3833 // if(!DialogMode.Check(DMODE_SHOW))
3835 if (FarIsEdit(Item
[Pos
]->Type
) && (Item
[Pos
]->Flags
& DIF_SELECTONENTRY
)
3836 // && PrevFocusPos != -1 && PrevFocusPos != Pos
3838 DlgEdit
*edt
= (DlgEdit
*)Item
[Pos
]->ObjPtr
;
3842 edt
->Select(0, edt
->GetLength());
3846 //_SVS(SysLog(L"Selected=%d edt->GetLength()=%d",Selected,edt->GetLength()));
3851 int Dialog::SetAutomation(WORD IDParent
, WORD id
, FarDialogItemFlags UncheckedSet
,
3852 FarDialogItemFlags UncheckedSkip
, FarDialogItemFlags CheckedSet
, FarDialogItemFlags CheckedSkip
,
3853 FarDialogItemFlags Checked3Set
, FarDialogItemFlags Checked3Skip
)
3855 CriticalSectionLock
Lock(CS
);
3858 if (IDParent
< ItemCount
&& (Item
[IDParent
]->Flags
& DIF_AUTOMATION
) && id
< ItemCount
3859 && IDParent
!= id
) // Сами себя не юзаем!
3861 Ret
= Item
[IDParent
]->AddAutomation(id
, UncheckedSet
, UncheckedSkip
, CheckedSet
, CheckedSkip
,
3862 Checked3Set
, Checked3Skip
);
3868 //////////////////////////////////////////////////////////////////////////
3871 Заполняем выпадающий список для ComboBox
3873 int Dialog::SelectFromComboBox(DialogItemEx
*CurItem
,
3874 DlgEdit
*EditLine
, // строка редактирования
3875 VMenu
*ComboBox
) // список строк
3877 CriticalSectionLock
Lock(CS
);
3880 int EditX1
, EditY1
, EditX2
, EditY2
;
3881 int I
, Dest
, OriginalPos
;
3882 unsigned CurFocusPos
= FocusPos
;
3883 // if((Str=(char*)malloc(MaxLen)) )
3885 EditLine
->GetPosition(EditX1
, EditY1
, EditX2
, EditY2
);
3887 if (EditX2
- EditX1
< 20)
3888 EditX2
= EditX1
+ 20;
3890 SetDropDownOpened(TRUE
); // Установим флаг "открытия" комбобокса.
3891 SetComboBoxPos(CurItem
);
3892 // Перед отрисовкой спросим об изменении цветовых атрибутов
3893 BYTE RealColors
[VMENU_COLOR_COUNT
];
3894 FarListColors ListColors
= {0};
3895 ListColors
.ColorCount
= VMENU_COLOR_COUNT
;
3896 ListColors
.Colors
= RealColors
;
3897 ComboBox
->SetColors(nullptr);
3898 ComboBox
->GetColors(&ListColors
);
3900 if (DlgProc((HANDLE
)this, DN_CTLCOLORDLGLIST
, CurItem
->ID
, (LONG_PTR
)&ListColors
))
3901 ComboBox
->SetColors(&ListColors
);
3903 // Выставим то, что есть в строке ввода!
3904 // if(EditLine->GetDropDownBox()) //???
3905 EditLine
->GetString(strStr
);
3907 if (CurItem
->Flags
& (DIF_DROPDOWNLIST
| DIF_LISTNOAMPERSAND
))
3908 HiText2Str(strStr
, strStr
);
3910 ComboBox
->SetSelectPos(ComboBox
->FindItem(0, strStr
, LIFIND_EXACTMATCH
), 1);
3912 OriginalPos
= Dest
= ComboBox
->GetSelectPos();
3913 CurItem
->IFlags
.Set(DLGIIF_COMBOBOXNOREDRAWEDIT
);
3915 while (!ComboBox
->Done()) {
3916 if (!GetDropDownOpened()) {
3917 ComboBox
->ProcessKey(KEY_ESC
);
3921 INPUT_RECORD ReadRec
;
3922 FarKey Key
= ComboBox
->ReadInput(&ReadRec
);
3924 if (CurItem
->IFlags
.Check(DLGIIF_COMBOBOXEVENTKEY
) && ReadRec
.EventType
== KEY_EVENT
) {
3925 if (DlgProc((HANDLE
)this, DN_KEY
, FocusPos
, Key
))
3927 } else if (CurItem
->IFlags
.Check(DLGIIF_COMBOBOXEVENTMOUSE
) && ReadRec
.EventType
== MOUSE_EVENT
)
3928 if (!DlgProc((HANDLE
)this, DN_MOUSEEVENT
, 0, (LONG_PTR
)&ReadRec
.Event
.MouseEvent
))
3931 // здесь можно добавить что-то свое, например,
3932 I
= ComboBox
->GetSelectPos();
3934 if (Key
== KEY_TAB
) // Tab в списке - аналог Enter
3936 ComboBox
->ProcessKey(KEY_ENTER
);
3941 if (!DlgProc((HANDLE
)this, DN_LISTCHANGE
, CurFocusPos
, I
))
3942 ComboBox
->SetSelectPos(Dest
, Dest
< I
? -1 : 1); //????
3948 // во время навигации по DropDown листу - отобразим ЭТО дело в
3951 // Очень медленная реакция!
3952 if (EditLine
->GetDropDownBox())
3954 MenuItem
*CurCBItem
=ComboBox
->GetItemPtr();
3955 EditLine
->SetString(CurCBItem
->Name
);
3957 //EditLine->FastShow();
3963 // обработку multiselect ComboBox
3965 ComboBox
->ProcessInput();
3968 CurItem
->IFlags
.Clear(DLGIIF_COMBOBOXNOREDRAWEDIT
);
3969 ComboBox
->ClearDone();
3972 if (GetDropDownOpened()) // Закрылся не программным путём?
3973 Dest
= ComboBox
->Modal::GetExitCode();
3978 ComboBox
->SetSelectPos(OriginalPos
, 0); //????
3980 SetDropDownOpened(FALSE
); // Установим флаг "закрытия" комбобокса.
3988 // ComboBox->GetUserData(Str,MaxLen,Dest);
3989 MenuItemEx
*ItemPtr
= ComboBox
->GetItemPtr(Dest
);
3991 if (CurItem
->Flags
& (DIF_DROPDOWNLIST
| DIF_LISTNOAMPERSAND
)) {
3992 HiText2Str(strStr
, ItemPtr
->strName
);
3993 EditLine
->SetString(strStr
);
3995 EditLine
->SetString(ItemPtr
->strName
);
3997 EditLine
->SetLeftPos(0);
4005 //////////////////////////////////////////////////////////////////////////
4008 Заполняем выпадающий список из истории
4010 BOOL
Dialog::SelectFromEditHistory(DialogItemEx
*CurItem
, DlgEdit
*EditLine
, const wchar_t *HistoryName
,
4013 CriticalSectionLock
Lock(CS
);
4020 FARString strRegKey
= fmtSavedDialogHistory
;
4021 strRegKey
+= HistoryName
;
4022 History
DlgHist(HISTORYTYPE_DIALOG
, Opt
.DialogsHistoryCount
, strRegKey
.GetMB(), &Opt
.Dialogs
.EditHistory
,
4024 DlgHist
.ResetPosition();
4026 // создание пустого вертикального меню
4027 VMenu
HistoryMenu(L
"", nullptr, 0, Opt
.Dialogs
.CBoxMaxHeight
,
4028 VMENU_ALWAYSSCROLLBAR
| VMENU_COMBOBOX
| VMENU_NOTCHANGE
);
4029 HistoryMenu
.SetFlags(VMENU_SHOWAMPERSAND
);
4030 HistoryMenu
.SetBoxType(SHORT_SINGLE_BOX
);
4031 SetDropDownOpened(TRUE
); // Установим флаг "открытия" комбобокса.
4032 // запомним (для прорисовки)
4033 CurItem
->ListPtr
= &HistoryMenu
;
4034 ret
= DlgHist
.Select(HistoryMenu
, Opt
.Dialogs
.CBoxMaxHeight
, this, strStr
);
4035 // забудим (не нужен)
4036 CurItem
->ListPtr
= nullptr;
4037 SetDropDownOpened(FALSE
); // Установим флаг "закрытия" комбобокса.
4041 EditLine
->SetString(strStr
);
4042 EditLine
->SetLeftPos(0);
4043 EditLine
->SetClearFlag(0);
4051 //////////////////////////////////////////////////////////////////////////
4054 Работа с историей - добавление и reorder списка
4056 int Dialog::AddToEditHistory(const wchar_t *AddStr
, const wchar_t *HistoryName
)
4058 CriticalSectionLock
Lock(CS
);
4064 FARString strRegKey
= fmtSavedDialogHistory
;
4065 strRegKey
+= HistoryName
;
4066 History
DlgHist(HISTORYTYPE_DIALOG
, Opt
.DialogsHistoryCount
, strRegKey
.GetMB(), &Opt
.Dialogs
.EditHistory
,
4068 DlgHist
.AddToHistory(AddStr
);
4072 int Dialog::CheckHighlights(WORD CheckSymbol
, int StartPos
)
4074 CriticalSectionLock
Lock(CS
);
4081 for (I
= StartPos
; I
< (int)ItemCount
; I
++) {
4082 Type
= Item
[I
]->Type
;
4083 Flags
= Item
[I
]->Flags
;
4085 if ((!FarIsEdit(Type
) || (Type
== DI_COMBOBOX
&& (Flags
& DIF_DROPDOWNLIST
)))
4086 && !(Flags
& (DIF_SHOWAMPERSAND
| DIF_DISABLE
| DIF_HIDDEN
))) {
4087 const wchar_t *ChPtr
= wcschr(Item
[I
]->strData
, L
'&');
4092 if (Ch
&& Upper(CheckSymbol
) == Upper(Ch
))
4094 } else if (!CheckSymbol
)
4102 //////////////////////////////////////////////////////////////////////////
4105 Если жмакнули Alt-???
4107 int Dialog::ProcessHighlighting(FarKey Key
, unsigned FocusPos
, int Translate
)
4109 CriticalSectionLock
Lock(CS
);
4113 for (unsigned I
= 0; I
< ItemCount
; I
++) {
4114 Type
= Item
[I
]->Type
;
4115 Flags
= Item
[I
]->Flags
;
4117 if ((!FarIsEdit(Type
) || (Type
== DI_COMBOBOX
&& (Flags
& DIF_DROPDOWNLIST
)))
4118 && !(Flags
& (DIF_SHOWAMPERSAND
| DIF_DISABLE
| DIF_HIDDEN
)))
4119 if (IsKeyHighlighted(Item
[I
]->strData
, Key
, Translate
)) {
4120 int DisableSelect
= FALSE
;
4122 // Если ЭТО: DlgEdit(пред контрол) и DI_TEXT в одну строку, то...
4123 if (I
> 0 && Type
== DI_TEXT
&& // DI_TEXT
4124 FarIsEdit(Item
[I
- 1]->Type
) && // и редактор
4125 Item
[I
]->Y1
== Item
[I
- 1]->Y1
&& // и оба в одну строку
4126 (I
+ 1 < ItemCount
&& Item
[I
]->Y1
!= Item
[I
+ 1]->Y1
)) // ...и следующий контрол в другой строке
4128 // Сначала сообщим о случившемся факте процедуре обработки диалога, а потом...
4129 if (!DlgProc((HANDLE
)this, DN_HOTKEY
, I
, Key
))
4130 break; // сказали не продолжать обработку...
4132 // ... если предыдущий контрол задизаблен или невидим, тогда выходим.
4133 if ((Item
[I
- 1]->Flags
& (DIF_DISABLE
| DIF_HIDDEN
))) // и не задисаблен
4136 I
= ChangeFocus(I
, -1, FALSE
);
4137 DisableSelect
= TRUE
;
4138 } else if (Item
[I
]->Type
== DI_TEXT
|| Item
[I
]->Type
== DI_VTEXT
4139 || Item
[I
]->Type
== DI_SINGLEBOX
|| Item
[I
]->Type
== DI_DOUBLEBOX
) {
4140 if (I
+ 1 < ItemCount
) // ...и следующий контрол
4142 // Сначала сообщим о случившемся факте процедуре обработки диалога, а потом...
4143 if (!DlgProc((HANDLE
)this, DN_HOTKEY
, I
, Key
))
4144 break; // сказали не продолжать обработку...
4146 // ... если следующий контрол задизаблен или невидим, тогда выходим.
4147 if ((Item
[I
+ 1]->Flags
& (DIF_DISABLE
| DIF_HIDDEN
))) // и не задисаблен
4150 I
= ChangeFocus(I
, 1, FALSE
);
4151 DisableSelect
= TRUE
;
4155 // Сообщим о случивщемся факте процедуре обработки диалога
4156 if (!DlgProc((HANDLE
)this, DN_HOTKEY
, I
, Key
))
4157 break; // сказали не продолжать обработку...
4162 if ((Item
[I
]->Type
== DI_CHECKBOX
|| Item
[I
]->Type
== DI_RADIOBUTTON
)
4163 && (!DisableSelect
|| (Item
[I
]->Flags
& DIF_MOVESELECT
))) {
4166 } else if (Item
[I
]->Type
== DI_BUTTON
) {
4167 ProcessKey(KEY_ENTER
, I
);
4170 // при ComboBox`е - "вываливаем" последний //????
4171 else if (Item
[I
]->Type
== DI_COMBOBOX
) {
4172 ProcessOpenComboBox(Item
[I
]->Type
, Item
[I
], I
);
4173 // ProcessKey(KEY_CTRLDOWN);
4184 //////////////////////////////////////////////////////////////////////////
4186 функция подравнивания координат edit классов
4188 void Dialog::AdjustEditPos(int dx
, int dy
)
4190 CriticalSectionLock
Lock(CS
);
4191 DialogItemEx
*CurItem
;
4194 if (!DialogMode
.Check(DMODE_CREATEOBJECTS
))
4197 ScreenObject
*DialogScrObject
;
4199 for (unsigned I
= 0; I
< ItemCount
; I
++) {
4201 int Type
= CurItem
->Type
;
4203 if ((CurItem
->ObjPtr
&& FarIsEdit(Type
)) || (CurItem
->ListPtr
&& Type
== DI_LISTBOX
)) {
4204 if (Type
== DI_LISTBOX
)
4205 DialogScrObject
= (ScreenObject
*)CurItem
->ListPtr
;
4207 DialogScrObject
= (ScreenObject
*)CurItem
->ObjPtr
;
4209 DialogScrObject
->GetPosition(x1
, y1
, x2
, y2
);
4214 DialogScrObject
->SetPosition(x1
, y1
, x2
, y2
);
4218 ProcessCenterGroup();
4221 //////////////////////////////////////////////////////////////////////////
4223 Работа с доп. данными экземпляра диалога
4224 Пока простое копирование (присвоение)
4226 void Dialog::SetDialogData(LONG_PTR NewDataDialog
)
4228 DataDialog
= NewDataDialog
;
4231 //////////////////////////////////////////////////////////////////////////
4234 При расчётах времён копирования проще/надёжнее учитывать время ожидания
4235 пользовательских ответов в одном месте (здесь).
4236 Сброс этой переменной должен осуществляться перед общим началом операции
4242 + Для того, чтобы послать DM_CLOSE нужно переопределить Process
4244 static std::atomic
<int> s_in_dialog
{0};
4246 void Dialog::Process()
4248 // if(DialogMode.Check(DMODE_SMALLDIALOG))
4249 SetRestoreScreenMode(TRUE
);
4253 if (ExitCode
== -1) {
4256 DialogMode
.Set(DMODE_BEGINLOOP
);
4258 if (1 == ++s_in_dialog
) {
4259 btm
= GetProcessUptimeMSec();
4260 save
= WaitUserTime
;
4264 FrameManager
->ExecuteModal(this);
4265 save
+= (GetProcessUptimeMSec() - btm
);
4267 if (0 == --s_in_dialog
)
4268 WaitUserTime
= save
;
4272 for (unsigned i
= 0; i
< ItemCount
; i
++)
4273 DialogItemExToDialogItemEx(Item
[i
], &pSaveItemEx
[i
]);
4276 void Dialog::CloseDialog()
4278 CriticalSectionLock
Lock(CS
);
4279 GetDialogObjectsData();
4281 if (DlgProc((HANDLE
)this, DN_CLOSE
, ExitCode
, 0)) {
4282 DialogMode
.Set(DMODE_ENDLOOP
);
4285 if (DialogMode
.Check(DMODE_BEGINLOOP
)
4286 && (DialogMode
.Check(DMODE_MSGINTERNAL
) || FrameManager
->ManagerStarted())) {
4287 DialogMode
.Clear(DMODE_BEGINLOOP
);
4288 FrameManager
->DeleteFrame(this);
4291 _DIALOG(CleverSysLog
CL(L
"Close Dialog"));
4297 установка help topic'а и прочие радости, временно перетащенные сюда
4300 void Dialog::SetHelp(const wchar_t *Topic
)
4302 CriticalSectionLock
Lock(CS
);
4307 HelpTopic
= nullptr;
4309 if (Topic
&& *Topic
) {
4310 HelpTopic
= new (std::nothrow
) wchar_t[wcslen(Topic
) + 1];
4313 wcscpy(HelpTopic
, Topic
);
4317 void Dialog::ShowHelp()
4319 CriticalSectionLock
Lock(CS
);
4321 if (HelpTopic
&& *HelpTopic
) {
4322 Help::Present(HelpTopic
);
4326 void Dialog::ClearDone()
4328 CriticalSectionLock
Lock(CS
);
4330 DialogMode
.Clear(DMODE_ENDLOOP
);
4333 void Dialog::SetExitCode(int Code
)
4335 CriticalSectionLock
Lock(CS
);
4337 DialogMode
.Set(DMODE_ENDLOOP
);
4343 возвращаем наше название для меню по F12
4345 int Dialog::GetTypeAndName(FARString
&strType
, FARString
&strName
)
4347 CriticalSectionLock
Lock(CS
);
4348 strType
= Msg::DialogType
;
4350 const wchar_t *lpwszTitle
= GetDialogTitle();
4353 strName
= lpwszTitle
;
4355 return MODALTYPE_DIALOG
;
4358 int Dialog::GetMacroMode()
4360 return MACRO_DIALOG
;
4363 int Dialog::FastHide()
4365 return Opt
.AllCtrlAltShiftRule
& CASR_DIALOG
;
4368 void Dialog::ResizeConsole()
4370 CriticalSectionLock
Lock(CS
);
4372 DialogMode
.Set(DMODE_RESIZED
);
4378 COORD c
= {(SHORT
)(ScrX
+ 1), (SHORT
)(ScrY
+ 1)};
4379 SendDlgMessage(reinterpret_cast<HANDLE
>(this), DN_RESIZECONSOLE
, 0, reinterpret_cast<LONG_PTR
>(&c
));
4382 GetPosition(x1
, y1
, x2
, y2
);
4383 c
.X
= Min(x1
, ScrX
- 1);
4384 c
.Y
= Min(y1
, ScrY
- 1);
4385 if (c
.X
!= x1
|| c
.Y
!= y1
) {
4388 SendDlgMessage(reinterpret_cast<HANDLE
>(this), DM_MOVEDIALOG
, TRUE
, reinterpret_cast<LONG_PTR
>(&c
));
4389 Dialog::SetComboBoxPos();
4393 // void Dialog::OnDestroy()
4397 // Эта функция потеряла своё значение при текущем менеджере
4398 // и системе создания и уничтожения фреймов.
4400 // if(DialogMode.Check(DMODE_RESIZED))
4402 // Frame *BFrame=FrameManager->GetBottomFrame();
4404 // BFrame->UnlockRefresh();
4407 // А вот этот DM_KILLSAVESCREEN здесь только вредит. Удаление
4408 // диалога происходит без восстановления ShadowSaveScr и вот
4409 // они: "артефакты" непрорисовки.
4411 // SendDlgMessage((HANDLE)this,DM_KILLSAVESCREEN,0,0);
4415 LONG_PTR WINAPI
Dialog::DlgProc(HANDLE hDlg
, int Msg
, int Param1
, LONG_PTR Param2
)
4417 if (DialogMode
.Check(DMODE_ENDLOOP
))
4421 FarDialogEvent de
= {hDlg
, Msg
, Param1
, Param2
, 0};
4423 if (!reinterpret_cast<Dialog
*>(hDlg
)->CheckDialogMode(DMODE_NOPLUGINS
)) {
4424 if (CtrlObject
->Plugins
.ProcessDialogEvent(DE_DLGPROCINIT
, &de
))
4427 Result
= RealDlgProc(hDlg
, Msg
, Param1
, Param2
);
4428 if (!reinterpret_cast<Dialog
*>(hDlg
)->CheckDialogMode(DMODE_NOPLUGINS
)) {
4430 if (CtrlObject
->Plugins
.ProcessDialogEvent(DE_DLGPROCEND
, &de
))
4436 //////////////////////////////////////////////////////////////////////////
4439 функция обработки диалога (по умолчанию)
4440 Вот именно эта функция и является последним рубежом обработки диалога.
4441 Т.е. здесь должна быть ВСЯ обработка ВСЕХ сообщений!!!
4443 LONG_PTR WINAPI
DefDlgProc(HANDLE hDlg
, int Msg
, int Param1
, LONG_PTR Param2
)
4445 _DIALOG(CleverSysLog
CL(L
"Dialog.DefDlgProc()"));
4446 _DIALOG(SysLog(L
"hDlg=%p, Msg=%ls, Param1=%d (0x%08X), Param2=%d (0x%08X)", hDlg
, _DLGMSG_ToName(Msg
),
4447 Param1
, Param1
, Param2
, Param2
));
4449 if (!hDlg
|| hDlg
== INVALID_HANDLE_VALUE
)
4452 FarDialogEvent de
= {hDlg
, Msg
, Param1
, Param2
, 0};
4454 if (!reinterpret_cast<Dialog
*>(hDlg
)->CheckDialogMode(DMODE_NOPLUGINS
)) {
4455 if (CtrlObject
->Plugins
.ProcessDialogEvent(DE_DEFDLGPROCINIT
, &de
)) {
4459 Dialog
*Dlg
= (Dialog
*)hDlg
;
4460 CriticalSectionLock
Lock(Dlg
->CS
);
4461 DialogItemEx
*CurItem
= nullptr;
4466 return FALSE
; // изменений не было!
4468 return TRUE
; // согласен с закрытием
4470 return -1; // "Согласен с потерей фокуса"
4472 return 0; // always 0
4474 return Param2
; // что передали, то и...
4476 return TRUE
; // согласен с перемещалкой.
4477 case DN_DRAWDIALOGDONE
: {
4478 if (Param1
== 1) // Нужно отрисовать "салазки"?
4482 вывод текста в углу может приводить к ошибкам изображения
4483 1) когда диалог перемещается в угол
4484 2) когда диалог перемещается из угла
4485 сделал вывод красных палочек по углам
4487 Text(Dlg
->X1
, Dlg
->Y1
, 0xCE, L
"\\");
4488 Text(Dlg
->X1
, Dlg
->Y2
, 0xCE, L
"/");
4489 Text(Dlg
->X2
, Dlg
->Y1
, 0xCE, L
"/");
4490 Text(Dlg
->X2
, Dlg
->Y2
, 0xCE, L
"\\");
4495 case DN_DRAWDIALOG
: {
4498 case DN_CTLCOLORDIALOG
:
4500 case DN_CTLCOLORDLGITEM
:
4502 case DN_CTLCOLORDLGLIST
:
4505 return 0; // always 0
4506 case DM_GETDIALOGINFO
: {
4507 bool Result
= false;
4511 DialogInfo
*di
= reinterpret_cast<DialogInfo
*>(Param2
);
4513 if (static_cast<size_t>(di
->StructSize
) >= offsetof(DialogInfo
, Id
) + sizeof(di
->Id
)) {
4524 // предварительно проверим...
4525 if (Param1
< 0 || (unsigned)Param1
>= Dlg
->ItemCount
|| !Dlg
->Item
)
4528 CurItem
= Dlg
->Item
[Param1
];
4529 Type
= CurItem
->Type
;
4534 case DN_DRAWDLGITEM
:
4541 return ((Type
== DI_BUTTON
&& !(CurItem
->Flags
& DIF_BTNNOCLOSE
)) ? FALSE
: TRUE
);
4548 case DM_GETSELECTION
: // Msg=DM_GETSELECTION, Param1=ID, Param2=*EditorSelect
4550 case DM_SETSELECTION
:
4557 LONG_PTR
Dialog::CallDlgProc(int nMsg
, int nParam1
, LONG_PTR nParam2
)
4559 CriticalSectionLock
Lock(CS
);
4560 return Dialog::DlgProc((HANDLE
)this, nMsg
, nParam1
, nParam2
);
4563 //////////////////////////////////////////////////////////////////////////
4564 LONG_PTR
SendDlgMessageSynched(HANDLE hDlg
, int Msg
, int Param1
, LONG_PTR Param2
)
4566 Dialog
*Dlg
= (Dialog
*)hDlg
;
4567 CriticalSectionLock
Lock(Dlg
->CS
);
4568 _DIALOG(CleverSysLog
CL(L
"Dialog.SendDlgMessage()"));
4569 _DIALOG(SysLog(L
"hDlg=%p, Msg=%ls, Param1=%d (0x%08X), Param2=%d (0x%08X)", hDlg
, _DLGMSG_ToName(Msg
),
4570 Param1
, Param1
, Param2
, Param2
));
4572 // Сообщения, касаемые только диалога и не затрагивающие элементы
4574 /*****************************************************************/
4575 case DM_RESIZEDIALOG
:
4576 // изменим вызов RESIZE.
4578 /*****************************************************************/
4579 case DM_MOVEDIALOG
: {
4581 W1
= Dlg
->X2
- Dlg
->X1
+ 1;
4582 H1
= Dlg
->Y2
- Dlg
->Y1
+ 1;
4583 Dlg
->OldX1
= Dlg
->X1
;
4584 Dlg
->OldY1
= Dlg
->Y1
;
4585 Dlg
->OldX2
= Dlg
->X2
;
4586 Dlg
->OldY2
= Dlg
->Y2
;
4589 if (Param1
> 0) // абсолютно?
4591 Dlg
->X1
= ((COORD
*)Param2
)->X
;
4592 Dlg
->Y1
= ((COORD
*)Param2
)->Y
;
4595 Dlg
->CheckDialogCoord();
4596 } else if (!Param1
) // значит относительно
4598 Dlg
->X1
+= ((COORD
*)Param2
)->X
;
4599 Dlg
->Y1
+= ((COORD
*)Param2
)->Y
;
4600 } else // Resize, Param2=width/height
4605 W1
= ((COORD
*)Param2
)->X
;
4606 H1
= ((COORD
*)Param2
)->Y
;
4607 Dlg
->RealWidth
= W1
;
4608 Dlg
->RealHeight
= H1
;
4610 if (W1
< OldW1
|| H1
< OldH1
) {
4611 Dlg
->DialogMode
.Set(DMODE_DRAWING
);
4615 for (unsigned int I
= 0; I
< Dlg
->ItemCount
; I
++) {
4616 Item
= Dlg
->Item
[I
];
4618 if (Item
->Flags
& DIF_HIDDEN
)
4621 Rect
.Left
= Item
->X1
;
4622 Rect
.Top
= Item
->Y1
;
4624 if (Item
->X2
>= W1
) {
4625 Rect
.Right
= Item
->X2
- (OldW1
- W1
);
4626 Rect
.Bottom
= Item
->Y2
;
4627 Dlg
->SetItemRect(I
, &Rect
);
4630 if (Item
->Y2
>= H1
) {
4631 Rect
.Right
= Item
->X2
;
4632 Rect
.Bottom
= Item
->Y2
- (OldH1
- H1
);
4633 Dlg
->SetItemRect(I
, &Rect
);
4637 Dlg
->DialogMode
.Clear(DMODE_DRAWING
);
4641 // проверили и скорректировали
4642 if (Dlg
->X1
+ W1
< 0)
4645 if (Dlg
->Y1
+ H1
< 0)
4654 Dlg
->X2
= Dlg
->X1
+ W1
- 1;
4655 Dlg
->Y2
= Dlg
->Y1
+ H1
- 1;
4657 if (Param1
> 0) // абсолютно?
4659 Dlg
->CheckDialogCoord();
4662 if (Param1
< 0) // размер?
4664 ((COORD
*)Param2
)->X
= Dlg
->X2
- Dlg
->X1
+ 1;
4665 ((COORD
*)Param2
)->Y
= Dlg
->Y2
- Dlg
->Y1
+ 1;
4667 ((COORD
*)Param2
)->X
= Dlg
->X1
;
4668 ((COORD
*)Param2
)->Y
= Dlg
->Y1
;
4671 int I
= Dlg
->IsVisible(); // && Dlg->DialogMode.Check(DMODE_INITOBJECTS);
4677 Dlg
->AdjustEditPos(Dlg
->X1
- Dlg
->OldX1
, Dlg
->Y1
- Dlg
->OldY1
);
4680 Dlg
->Show(); // только если диалог был виден
4684 /*****************************************************************/
4686 if (Dlg
->DialogMode
.Check(DMODE_INITOBJECTS
))
4691 /*****************************************************************/
4692 case DM_ENABLEREDRAW
: {
4693 int Prev
= Dlg
->IsEnableRedraw
;
4696 Dlg
->IsEnableRedraw
++;
4697 else if (Param1
== FALSE
)
4698 Dlg
->IsEnableRedraw
--;
4700 // Edit::DisableEditOut(!Dlg->IsEnableRedraw?FALSE:TRUE);
4702 if (!Dlg
->IsEnableRedraw
&& Prev
!= Dlg
->IsEnableRedraw
)
4703 if (Dlg
->DialogMode
.Check(DMODE_INITOBJECTS
)) {
4712 case DM_ENABLEREDRAW:
4715 Dlg->IsEnableRedraw++;
4717 Dlg->IsEnableRedraw--;
4719 if(!Dlg->IsEnableRedraw)
4720 if(Dlg->DialogMode.Check(DMODE_INITOBJECTS))
4729 /*****************************************************************/
4730 case DM_SHOWDIALOG
: {
4731 // if(!Dlg->IsEnableRedraw)
4736 Залочим прорисовку при прятании диалога, в противном
4737 случае ОТКУДА менеджер узнает, что отрисовывать
4740 if (!Dlg
->IsVisible()) {
4745 if (Dlg
->IsVisible()) {
4753 /*****************************************************************/
4754 case DM_SETDLGDATA
: {
4755 LONG_PTR PrewDataDialog
= Dlg
->DataDialog
;
4756 Dlg
->DataDialog
= Param2
;
4757 return PrewDataDialog
;
4759 /*****************************************************************/
4760 case DM_GETDLGDATA
: {
4761 return Dlg
->DataDialog
;
4763 /*****************************************************************/
4765 int *KeyArray
= (int *)Param2
;
4766 Dlg
->DialogMode
.Set(DMODE_KEY
);
4768 for (unsigned int I
= 0; I
< (unsigned)Param1
; ++I
)
4769 Dlg
->ProcessKey(KeyArray
[I
]);
4771 Dlg
->DialogMode
.Clear(DMODE_KEY
);
4774 /*****************************************************************/
4777 Dlg
->ExitCode
= Dlg
->FocusPos
;
4779 Dlg
->ExitCode
= Param1
;
4782 return TRUE
; // согласен с закрытием
4784 /*****************************************************************/
4785 case DM_GETDLGRECT
: {
4788 Dlg
->GetPosition(x1
, y1
, x2
, y2
);
4789 ((SMALL_RECT
*)Param2
)->Left
= x1
;
4790 ((SMALL_RECT
*)Param2
)->Top
= y1
;
4791 ((SMALL_RECT
*)Param2
)->Right
= x2
;
4792 ((SMALL_RECT
*)Param2
)->Bottom
= y2
;
4798 /*****************************************************************/
4799 case DM_GETDROPDOWNOPENED
: // Param1=0; Param2=0
4801 return Dlg
->GetDropDownOpened();
4803 /*****************************************************************/
4804 case DM_KILLSAVESCREEN
: {
4806 Dlg
->SaveScr
->Discard();
4808 if (Dlg
->ShadowSaveScr
)
4809 Dlg
->ShadowSaveScr
->Discard();
4813 /*****************************************************************/
4817 =-1 - получить состояние
4822 case DM_ALLKEYMODE
: {
4824 return IsProcessAssignMacroKey
;
4826 BOOL OldIsProcessAssignMacroKey
= IsProcessAssignMacroKey
;
4827 IsProcessAssignMacroKey
= Param1
;
4828 return OldIsProcessAssignMacroKey
;
4830 /*****************************************************************/
4831 case DM_SETMOUSEEVENTNOTIFY
: // Param1 = 1 on, 0 off, -1 - get
4833 int State
= Dlg
->DialogMode
.Check(DMODE_MOUSEEVENT
) ? TRUE
: FALSE
;
4837 Dlg
->DialogMode
.Clear(DMODE_MOUSEEVENT
);
4839 Dlg
->DialogMode
.Set(DMODE_MOUSEEVENT
);
4844 /*****************************************************************/
4845 case DN_RESIZECONSOLE
: {
4846 return Dlg
->CallDlgProc(Msg
, Param1
, Param2
);
4848 case DM_GETDIALOGINFO
: {
4849 return DefDlgProc(hDlg
, DM_GETDIALOGINFO
, Param1
, Param2
);
4853 /*****************************************************************/
4854 if (Msg
>= DM_USER
) {
4855 return Dlg
->CallDlgProc(Msg
, Param1
, Param2
);
4858 /*****************************************************************/
4859 DialogItemEx
*CurItem
= nullptr;
4864 предварительно проверим...
4866 для DM_USER проверять _не_надо_!
4868 if ((unsigned)Param1
>= Dlg
->ItemCount
|| !Dlg
->Item
)
4871 // CurItem=&Dlg->Item[Param1];
4872 CurItem
= Dlg
->Item
[Param1
];
4873 Type
= CurItem
->Type
;
4874 const wchar_t *Ptr
= CurItem
->strData
;
4876 if (FarIsEdit(Type
) && CurItem
->ObjPtr
)
4877 Ptr
= const_cast<const wchar_t *>(((DlgEdit
*)(CurItem
->ObjPtr
))->GetStringAddr());
4880 /*****************************************************************/
4881 case DM_LISTSORT
: // Param1=ID Param=Direct {0|1}
4882 case DM_LISTADD
: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
4883 case DM_LISTADDSTR
: // Param1=ID Param2=String
4884 case DM_LISTDELETE
: // Param1=ID Param2=FarListDelete: StartIndex=BeginIndex, Count=количество (<=0 - все!)
4885 case DM_LISTGETITEM
: // Param1=ID Param2=FarListGetItem: ItemsNumber=Index, Items=Dest
4886 case DM_LISTSET
: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
4887 case DM_LISTGETCURPOS
: // Param1=ID Param2=FarListPos
4888 case DM_LISTSETCURPOS
: // Param1=ID Param2=FarListPos Ret: RealPos
4889 case DM_LISTUPDATE
: // Param1=ID Param2=FarList: ItemsNumber=Index, Items=Src
4890 case DM_LISTINFO
: // Param1=ID Param2=FarListInfo
4891 case DM_LISTFINDSTRING
: // Param1=ID Param2=FarListFind
4892 case DM_LISTINSERT
: // Param1=ID Param2=FarListInsert
4893 case DM_LISTGETDATA
: // Param1=ID Param2=Index
4894 case DM_LISTSETDATA
: // Param1=ID Param2=FarListItemData
4895 case DM_LISTSETTITLES
: // Param1=ID Param2=FarListTitles: TitleLen=strlen(Title), BottomLen=strlen(Bottom)
4896 case DM_LISTGETTITLES
: // Param1=ID Param2=FarListTitles: TitleLen=strlen(Title), BottomLen=strlen(Bottom)
4897 case DM_LISTGETDATASIZE
: // Param1=ID Param2=Index
4898 case DM_LISTSETMOUSEREACTION
: // Param1=ID Param2=FARLISTMOUSEREACTIONTYPE Ret=OldSets
4899 case DM_SETCOMBOBOXEVENT
: // Param1=ID Param2=FARCOMBOBOXEVENTTYPE Ret=OldSets
4900 case DM_GETCOMBOBOXEVENT
: // Param1=ID Param2=0 Ret=Sets
4902 if (Type
== DI_LISTBOX
|| Type
== DI_COMBOBOX
) {
4903 VMenu
*ListBox
= CurItem
->ListPtr
;
4909 case DM_LISTINFO
: // Param1=ID Param2=FarListInfo
4911 return ListBox
->GetVMenuInfo((FarListInfo
*)Param2
);
4913 case DM_LISTSORT
: // Param1=ID Param=Direct {0|1}
4915 ListBox
->SortItems((int)Param2
);
4918 case DM_LISTFINDSTRING
: // Param1=ID Param2=FarListFind
4920 FarListFind
*lf
= reinterpret_cast<FarListFind
*>(Param2
);
4921 return ListBox
->FindItem(lf
->StartIndex
, lf
->Pattern
, lf
->Flags
);
4923 case DM_LISTADDSTR
: // Param1=ID Param2=String
4925 Ret
= ListBox
->AddItem((wchar_t *)Param2
);
4928 case DM_LISTADD
: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
4930 FarList
*ListItems
= (FarList
*)Param2
;
4935 Ret
= ListBox
->AddItem(ListItems
);
4938 case DM_LISTDELETE
: // Param1=ID Param2=FarListDelete: StartIndex=BeginIndex, Count=количество (<=0 - все!)
4941 FarListDelete
*ListItems
= (FarListDelete
*)Param2
;
4943 if (!ListItems
|| (Count
= ListItems
->Count
) <= 0)
4944 ListBox
->DeleteItems();
4946 ListBox
->DeleteItem(ListItems
->StartIndex
, Count
);
4950 case DM_LISTINSERT
: // Param1=ID Param2=FarListInsert
4952 if ((Ret
= ListBox
->InsertItem((FarListInsert
*)Param2
)) == -1)
4957 case DM_LISTUPDATE
: // Param1=ID Param2=FarListUpdate: Index=Index, Items=Src
4959 if (Param2
&& ListBox
->UpdateItem((FarListUpdate
*)Param2
))
4964 case DM_LISTGETITEM
: // Param1=ID Param2=FarListGetItem: ItemsNumber=Index, Items=Dest
4966 FarListGetItem
*ListItems
= (FarListGetItem
*)Param2
;
4971 MenuItemEx
*ListMenuItem
;
4973 if ((ListMenuItem
= ListBox
->GetItemPtr(ListItems
->ItemIndex
))) {
4974 // ListItems->ItemIndex=1;
4975 FarListItem
*Item
= &ListItems
->Item
;
4976 memset(Item
, 0, sizeof(FarListItem
));
4977 Item
->Flags
= ListMenuItem
->Flags
;
4978 Item
->Text
= ListMenuItem
->strName
;
4980 if(ListMenuItem->UserDataSize <= sizeof(DWORD)) //???
4981 Item->UserData=ListMenuItem->UserData;
4988 case DM_LISTGETDATA
: // Param1=ID Param2=Index
4990 if (Param2
< ListBox
->GetItemCount())
4991 return (LONG_PTR
)ListBox
->GetUserData(nullptr, 0, (int)Param2
);
4995 case DM_LISTGETDATASIZE
: // Param1=ID Param2=Index
4997 if (Param2
< ListBox
->GetItemCount())
4998 return ListBox
->GetUserDataSize((int)Param2
);
5002 case DM_LISTSETDATA
: // Param1=ID Param2=FarListItemData
5004 FarListItemData
*ListItems
= (FarListItemData
*)Param2
;
5006 if (ListItems
&& ListItems
->Index
< ListBox
->GetItemCount()) {
5007 Ret
= ListBox
->SetUserData(ListItems
->Data
, ListItems
->DataSize
,
5010 if (!Ret
&& ListBox
->GetUserData(nullptr, 0, ListItems
->Index
))
5011 Ret
= sizeof(DWORD
);
5020 + Сообщение для добавления в список строк, с удалением
5021 уже существующих, т.с. "чистая" установка
5023 case DM_LISTSET
: // Param1=ID Param2=FarList: ItemsNumber=Count, Items=Src
5025 FarList
*ListItems
= (FarList
*)Param2
;
5030 ListBox
->DeleteItems();
5031 Ret
= ListBox
->AddItem(ListItems
);
5034 // case DM_LISTINS: // Param1=ID Param2=FarList: ItemsNumber=Index, Items=Dest
5035 case DM_LISTSETTITLES
: // Param1=ID Param2=FarListTitles
5037 FarListTitles
*ListTitle
= (FarListTitles
*)Param2
;
5038 ListBox
->SetTitle(ListTitle
->Title
);
5039 ListBox
->SetBottomTitle(ListTitle
->Bottom
);
5040 break; // return TRUE;
5042 case DM_LISTGETTITLES
: // Param1=ID Param2=FarListTitles
5045 FarListTitles
*ListTitle
= (FarListTitles
*)Param2
;
5046 FARString strTitle
, strBottomTitle
;
5047 ListBox
->GetTitle(strTitle
);
5048 ListBox
->GetBottomTitle(strBottomTitle
);
5050 if (!strTitle
.IsEmpty() || !strBottomTitle
.IsEmpty()) {
5051 if (ListTitle
->Title
&& ListTitle
->TitleLen
)
5052 far_wcsncpy((wchar_t *)ListTitle
->Title
, strTitle
,
5053 ListTitle
->TitleLen
);
5055 ListTitle
->TitleLen
= (int)strTitle
.GetLength() + 1;
5057 if (ListTitle
->Bottom
&& ListTitle
->BottomLen
)
5058 far_wcsncpy((wchar_t *)ListTitle
->Bottom
, strBottomTitle
,
5059 ListTitle
->BottomLen
);
5061 ListTitle
->BottomLen
= (int)strBottomTitle
.GetLength() + 1;
5069 case DM_LISTGETCURPOS
: // Param1=ID Param2=FarListPos
5071 return Param2
? ListBox
->GetSelectPos((FarListPos
*)Param2
)
5072 : ListBox
->GetSelectPos();
5074 case DM_LISTSETCURPOS
: // Param1=ID Param2=FarListPos Ret: RealPos
5076 /* 26.06.2001 KM Подадим перед изменением позиции об этом сообщение */
5077 int CurListPos
= ListBox
->GetSelectPos();
5078 Ret
= ListBox
->SetSelectPos((FarListPos
*)Param2
);
5080 if (Ret
!= CurListPos
)
5081 if (!Dlg
->CallDlgProc(DN_LISTCHANGE
, Param1
, Ret
))
5082 Ret
= ListBox
->SetSelectPos(CurListPos
, 1);
5084 break; // т.к. нужно перерисовать!
5086 case DM_LISTSETMOUSEREACTION
: // Param1=ID Param2=FARLISTMOUSEREACTIONTYPE Ret=OldSets
5088 int OldSets
= CurItem
->IFlags
.Flags
;
5090 if (Param2
== LMRT_ONLYFOCUS
) {
5091 CurItem
->IFlags
.Clear(DLGIIF_LISTREACTIONNOFOCUS
);
5092 CurItem
->IFlags
.Set(DLGIIF_LISTREACTIONFOCUS
);
5093 } else if (Param2
== LMRT_NEVER
) {
5094 CurItem
->IFlags
.Clear(DLGIIF_LISTREACTIONNOFOCUS
| DLGIIF_LISTREACTIONFOCUS
);
5095 // ListBox->ClearFlags(VMENU_MOUSEREACTION);
5097 CurItem
->IFlags
.Set(DLGIIF_LISTREACTIONNOFOCUS
| DLGIIF_LISTREACTIONFOCUS
);
5098 // ListBox->SetFlags(VMENU_MOUSEREACTION);
5101 if ((OldSets
& (DLGIIF_LISTREACTIONNOFOCUS
| DLGIIF_LISTREACTIONFOCUS
))
5102 == (DLGIIF_LISTREACTIONNOFOCUS
| DLGIIF_LISTREACTIONFOCUS
))
5103 OldSets
= LMRT_ALWAYS
;
5104 else if (!(OldSets
& (DLGIIF_LISTREACTIONNOFOCUS
| DLGIIF_LISTREACTIONFOCUS
)))
5105 OldSets
= LMRT_NEVER
;
5107 OldSets
= LMRT_ONLYFOCUS
;
5111 case DM_GETCOMBOBOXEVENT
: // Param1=ID Param2=0 Ret=Sets
5113 return (CurItem
->IFlags
.Check(DLGIIF_COMBOBOXEVENTKEY
) ? CBET_KEY
: 0)
5114 | (CurItem
->IFlags
.Check(DLGIIF_COMBOBOXEVENTMOUSE
) ? CBET_MOUSE
: 0);
5116 case DM_SETCOMBOBOXEVENT
: // Param1=ID Param2=FARCOMBOBOXEVENTTYPE Ret=OldSets
5118 int OldSets
= CurItem
->IFlags
.Flags
;
5119 CurItem
->IFlags
.Clear(DLGIIF_COMBOBOXEVENTKEY
| DLGIIF_COMBOBOXEVENTMOUSE
);
5121 if (Param2
& CBET_KEY
)
5122 CurItem
->IFlags
.Set(DLGIIF_COMBOBOXEVENTKEY
);
5124 if (Param2
& CBET_MOUSE
)
5125 CurItem
->IFlags
.Set(DLGIIF_COMBOBOXEVENTMOUSE
);
5131 // уточнение для DI_COMBOBOX - здесь еще и DlgEdit нужно корректно заполнить
5132 if (!CurItem
->IFlags
.Check(DLGIIF_COMBOBOXNOREDRAWEDIT
) && Type
== DI_COMBOBOX
5133 && CurItem
->ObjPtr
) {
5134 MenuItemEx
*ListMenuItem
;
5136 if ((ListMenuItem
= ListBox
->GetItemPtr(ListBox
->GetSelectPos()))) {
5137 if (CurItem
->Flags
& (DIF_DROPDOWNLIST
| DIF_LISTNOAMPERSAND
))
5138 ((DlgEdit
*)(CurItem
->ObjPtr
))->SetHiString(ListMenuItem
->strName
);
5140 ((DlgEdit
*)(CurItem
->ObjPtr
))->SetString(ListMenuItem
->strName
);
5142 ((DlgEdit
*)(CurItem
->ObjPtr
))->Select(-1, -1); // снимаем выделение
5146 if (Dlg
->DialogMode
.Check(DMODE_SHOW
) && ListBox
->UpdateRequired()) {
5147 Dlg
->ShowDialog(Param1
);
5157 /*****************************************************************/
5158 case DM_SETHISTORY
: // Param1 = ID, Param2 = LPSTR HistoryName
5160 if (Type
== DI_EDIT
|| Type
== DI_FIXEDIT
) {
5161 if (Param2
&& *(const wchar_t *)Param2
) {
5162 CurItem
->Flags
|= DIF_HISTORY
;
5163 CurItem
->strHistory
= (const wchar_t *)Param2
;
5165 if (Type
== DI_EDIT
&& (CurItem
->Flags
& DIF_USELASTHISTORY
)) {
5166 Dlg
->ProcessLastHistory(CurItem
, Param1
);
5169 CurItem
->Flags
&= ~DIF_HISTORY
;
5170 CurItem
->strHistory
.Clear();
5173 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) {
5174 Dlg
->ShowDialog(Param1
);
5183 /*****************************************************************/
5184 case DM_ADDHISTORY
: {
5185 if (Param2
&& (Type
== DI_EDIT
|| Type
== DI_FIXEDIT
) && (CurItem
->Flags
& DIF_HISTORY
)) {
5186 return Dlg
->AddToEditHistory((const wchar_t *)Param2
, CurItem
->strHistory
);
5191 /*****************************************************************/
5192 case DM_GETCURSORPOS
: {
5196 if (FarIsEdit(Type
) && CurItem
->ObjPtr
) {
5197 ((COORD
*)Param2
)->X
= ((DlgEdit
*)(CurItem
->ObjPtr
))->GetCurPos();
5198 ((COORD
*)Param2
)->Y
= 0;
5200 } else if (Type
== DI_USERCONTROL
&& CurItem
->UCData
) {
5201 ((COORD
*)Param2
)->X
= CurItem
->UCData
->CursorPos
.X
;
5202 ((COORD
*)Param2
)->Y
= CurItem
->UCData
->CursorPos
.Y
;
5208 /*****************************************************************/
5209 case DM_SETCURSORPOS
: {
5210 if (FarIsEdit(Type
) && CurItem
->ObjPtr
&& ((COORD
*)Param2
)->X
>= 0) {
5211 DlgEdit
*EditPtr
= (DlgEdit
*)(CurItem
->ObjPtr
);
5212 EditPtr
->SetCurPos(((COORD
*)Param2
)->X
);
5214 Dlg
->ShowDialog(Param1
);
5216 } else if (Type
== DI_USERCONTROL
&& CurItem
->UCData
) {
5218 учтем, что координаты для этого элемента всегда относительные!
5221 COORD Coord
= *(COORD
*)Param2
;
5222 Coord
.X
+= CurItem
->X1
;
5224 if (Coord
.X
> CurItem
->X2
)
5225 Coord
.X
= CurItem
->X2
;
5227 Coord
.Y
+= CurItem
->Y1
;
5229 if (Coord
.Y
> CurItem
->Y2
)
5230 Coord
.Y
= CurItem
->Y2
;
5233 CurItem
->UCData
->CursorPos
.X
= Coord
.X
- CurItem
->X1
;
5234 CurItem
->UCData
->CursorPos
.Y
= Coord
.Y
- CurItem
->Y1
;
5236 // переместим если надо
5237 if (Dlg
->DialogMode
.Check(DMODE_SHOW
) && Dlg
->FocusPos
== (unsigned)Param1
) {
5238 // что-то одно надо убрать :-)
5239 MoveCursor(Coord
.X
+ Dlg
->X1
, Coord
.Y
+ Dlg
->Y1
); // ???
5240 Dlg
->ShowDialog(Param1
); // ???
5248 /*****************************************************************/
5249 case DM_GETEDITPOSITION
: {
5250 if (Param2
&& FarIsEdit(Type
)) {
5251 if (Type
== DI_MEMOEDIT
) {
5252 // EditorControl(ECTL_GETINFO,(EditorSetPosition *)Param2);
5255 EditorSetPosition
*esp
= (EditorSetPosition
*)Param2
;
5256 DlgEdit
*EditPtr
= (DlgEdit
*)(CurItem
->ObjPtr
);
5258 esp
->CurPos
= EditPtr
->GetCurPos();
5259 esp
->CurTabPos
= EditPtr
->GetCellCurPos();
5260 esp
->TopScreenLine
= 0;
5261 esp
->LeftPos
= EditPtr
->GetLeftPos();
5262 esp
->Overtype
= EditPtr
->GetOvertypeMode();
5269 /*****************************************************************/
5270 case DM_SETEDITPOSITION
: {
5271 if (Param2
&& FarIsEdit(Type
)) {
5272 if (Type
== DI_MEMOEDIT
) {
5273 // EditorControl(ECTL_SETPOSITION,(EditorSetPosition *)Param2);
5276 EditorSetPosition
*esp
= (EditorSetPosition
*)Param2
;
5277 DlgEdit
*EditPtr
= (DlgEdit
*)(CurItem
->ObjPtr
);
5278 EditPtr
->SetCurPos(esp
->CurPos
);
5279 EditPtr
->SetCellCurPos(esp
->CurTabPos
);
5280 EditPtr
->SetLeftPos(esp
->LeftPos
);
5281 EditPtr
->SetOvertypeMode(esp
->Overtype
);
5282 Dlg
->ShowDialog(Param1
);
5290 /*****************************************************************/
5292 // Return MAKELONG(Visible,Size)
5293 case DM_GETCURSORSIZE
: {
5294 if (FarIsEdit(Type
) && CurItem
->ObjPtr
) {
5297 ((DlgEdit
*)(CurItem
->ObjPtr
))->GetCursorType(Visible
, Size
);
5298 return MAKELONG(Visible
, Size
);
5299 } else if (Type
== DI_USERCONTROL
&& CurItem
->UCData
) {
5300 return MAKELONG(CurItem
->UCData
->CursorVisible
, CurItem
->UCData
->CursorSize
);
5305 /*****************************************************************/
5306 // Param2=MAKELONG(Visible,Size)
5307 // Return MAKELONG(OldVisible,OldSize)
5308 case DM_SETCURSORSIZE
: {
5309 bool Visible
= false;
5312 if (FarIsEdit(Type
) && CurItem
->ObjPtr
) {
5313 ((DlgEdit
*)(CurItem
->ObjPtr
))->GetCursorType(Visible
, Size
);
5314 ((DlgEdit
*)(CurItem
->ObjPtr
))->SetCursorType(LOWORD(Param2
) != 0, HIWORD(Param2
));
5315 } else if (Type
== DI_USERCONTROL
&& CurItem
->UCData
) {
5316 Visible
= CurItem
->UCData
->CursorVisible
;
5317 Size
= CurItem
->UCData
->CursorSize
;
5318 CurItem
->UCData
->CursorVisible
= LOWORD(Param2
) != 0;
5319 CurItem
->UCData
->CursorSize
= HIWORD(Param2
);
5320 int CCX
= CurItem
->UCData
->CursorPos
.X
;
5321 int CCY
= CurItem
->UCData
->CursorPos
.Y
;
5323 if (Dlg
->DialogMode
.Check(DMODE_SHOW
) && Dlg
->FocusPos
== (unsigned)Param1
&& CCX
!= -1
5325 SetCursorType(CurItem
->UCData
->CursorVisible
, CurItem
->UCData
->CursorSize
);
5328 return MAKELONG(Visible
, Size
);
5330 /*****************************************************************/
5331 case DN_LISTCHANGE
: {
5332 return Dlg
->CallDlgProc(Msg
, Param1
, Param2
);
5334 /*****************************************************************/
5335 case DN_EDITCHANGE
: {
5338 if (!ConvertItemEx(CVTITEM_TOPLUGIN
, &Item
, CurItem
, 1))
5339 return FALSE
; // no memory TODO: may be needed diagnostic
5342 if (CurItem
->Type
== DI_EDIT
|| CurItem
->Type
== DI_COMBOBOX
|| CurItem
->Type
== DI_FIXEDIT
5343 || CurItem
->Type
== DI_PSWEDIT
) {
5344 reinterpret_cast<DlgEdit
*>(CurItem
->ObjPtr
)->SetCallbackState(false);
5345 const wchar_t *original_PtrData
= Item
.PtrData
;
5346 I
= Dlg
->CallDlgProc(DN_EDITCHANGE
, Param1
, (LONG_PTR
)&Item
);
5348 if (Type
== DI_COMBOBOX
&& CurItem
->ListPtr
)
5349 CurItem
->ListPtr
->ChangeFlags(VMENU_DISABLED
, CurItem
->Flags
& DIF_DISABLE
);
5351 if (original_PtrData
)
5352 free((void *)original_PtrData
);
5353 reinterpret_cast<DlgEdit
*>(CurItem
->ObjPtr
)->SetCallbackState(true);
5358 /*****************************************************************/
5360 LONG_PTR Ret
= Dlg
->CallDlgProc(Msg
, Param1
, Param2
);
5362 if (Ret
&& (CurItem
->Flags
& DIF_AUTOMATION
) && CurItem
->AutoCount
&& CurItem
->AutoPtr
) {
5363 DialogItemAutomation
*Auto
= CurItem
->AutoPtr
;
5366 for (UINT I
= 0; I
< CurItem
->AutoCount
; ++I
, ++Auto
) {
5367 DWORD NewFlags
= Dlg
->Item
[Auto
->ID
]->Flags
;
5368 Dlg
->Item
[Auto
->ID
]->Flags
=
5369 (NewFlags
& (~Auto
->Flags
[Param2
][1])) | Auto
->Flags
[Param2
][0];
5370 // здесь намеренно в обработчик не посылаются эвенты об изменении
5377 /*****************************************************************/
5379 if (Type
== DI_CHECKBOX
|| Type
== DI_RADIOBUTTON
)
5380 return CurItem
->Selected
;
5384 /*****************************************************************/
5385 case DM_SET3STATE
: {
5386 if (Type
== DI_CHECKBOX
) {
5387 int OldState
= CurItem
->Flags
& DIF_3STATE
? TRUE
: FALSE
;
5390 CurItem
->Flags
|= DIF_3STATE
;
5392 CurItem
->Flags
&= ~DIF_3STATE
;
5399 /*****************************************************************/
5401 if (Type
== DI_CHECKBOX
) {
5402 int Selected
= CurItem
->Selected
;
5404 if (Param2
== BSTATE_TOGGLE
)
5405 Param2
= ++Selected
;
5407 if (CurItem
->Flags
& DIF_3STATE
)
5412 CurItem
->Selected
= (int)Param2
;
5414 if (Selected
!= (int)Param2
&& Dlg
->DialogMode
.Check(DMODE_SHOW
)) {
5416 if ((CurItem
->Flags
& DIF_AUTOMATION
) && CurItem
->AutoCount
&& CurItem
->AutoPtr
) {
5417 DialogItemAutomation
*Auto
= CurItem
->AutoPtr
;
5420 for (UINT I
= 0; I
< CurItem
->AutoCount
; ++I
, ++Auto
) {
5421 DWORD NewFlags
= Dlg
->Item
[Auto
->ID
]->Flags
;
5422 Dlg
->Item
[Auto
->ID
]->Flags
=
5423 (NewFlags
& (~Auto
->Flags
[Param2
][1])) | Auto
->Flags
[Param2
][0];
5424 // здесь намеренно в обработчик не посылаются эвенты об изменении
5431 Dlg
->ShowDialog(Param1
);
5436 } else if (Type
== DI_RADIOBUTTON
) {
5437 Param1
= Dlg
->ProcessRadioButton(Param1
);
5439 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) {
5449 /*****************************************************************/
5450 case DN_DRAWDLGITEM
: {
5453 if (!ConvertItemEx(CVTITEM_TOPLUGIN
, &Item
, CurItem
, 1))
5454 return FALSE
; // no memory TODO: may be needed diagnostic
5456 INT_PTR I
= Dlg
->CallDlgProc(Msg
, Param1
, (LONG_PTR
)&Item
);
5458 if ((Type
== DI_LISTBOX
|| Type
== DI_COMBOBOX
) && CurItem
->ListPtr
)
5459 CurItem
->ListPtr
->ChangeFlags(VMENU_DISABLED
, CurItem
->Flags
& DIF_DISABLE
);
5462 free((wchar_t *)Item
.PtrData
);
5466 /*****************************************************************/
5468 if (!CanGetFocus(Type
))
5471 if (Dlg
->FocusPos
== (unsigned)Param1
) // уже и так установлено все!
5474 Dlg
->ChangeFocus2(Param1
);
5476 if (Dlg
->FocusPos
== (unsigned)Param1
) {
5483 /*****************************************************************/
5484 case DM_GETFOCUS
: // Получить ID фокуса
5486 return Dlg
->FocusPos
;
5488 /*****************************************************************/
5489 case DM_GETCONSTTEXTPTR
: {
5490 return (LONG_PTR
)Ptr
;
5492 /*****************************************************************/
5496 FarDialogItemData IData
= {0, (wchar_t *)Param2
};
5497 return SendDlgMessage(hDlg
, DM_GETTEXT
, Param1
, (LONG_PTR
)&IData
);
5500 /*****************************************************************/
5503 if (Param2
) // если здесь nullptr, то это еще один способ получить размер
5505 FarDialogItemData
*did
= (FarDialogItemData
*)Param2
;
5516 if (!CurItem
->ObjPtr
)
5519 Ptr
= const_cast<const wchar_t *>(((DlgEdit
*)(CurItem
->ObjPtr
))->GetStringAddr());
5525 case DI_RADIOBUTTON
:
5527 Len
= StrLength(Ptr
) + 1;
5529 if (Type
== DI_BUTTON
) {
5530 if (!(CurItem
->Flags
& DIF_NOBRACKETS
)) {
5534 if (CurItem
->Flags
& DIF_SETSHIELD
) {
5539 if (!did
->PtrLength
)
5540 did
->PtrLength
= Len
;
5541 else if (Len
> did
->PtrLength
)
5542 Len
= did
->PtrLength
+ 1; // Прибавим 1, чтобы учесть нулевой байт.
5544 if (Len
> 0 && did
->PtrData
) {
5545 wmemmove(did
->PtrData
, Ptr
, Len
);
5546 did
->PtrData
[Len
- 1] = 0;
5550 case DI_USERCONTROL
:
5551 /*did->PtrLength=CurItem->Ptr.PtrLength; BUGBUG
5552 did->PtrData=(char*)CurItem->Ptr.PtrData;*/
5555 // if(!CurItem->ListPtr)
5557 // did->PtrLength=CurItem->ListPtr->GetUserData(did->PtrData,did->PtrLength,-1);
5560 default: // подразумеваем, что остались
5565 return Len
- (!Len
? 0 : 1);
5568 // здесь умышленно не ставим return, т.к. хотим получить размер
5569 // следовательно сразу должен идти "case DM_GETTEXTLENGTH"!!!
5570 /*****************************************************************/
5571 case DM_GETTEXTLENGTH
: {
5574 Len
= StrLength(Ptr
) + 1;
5576 if (!(CurItem
->Flags
& DIF_NOBRACKETS
))
5580 case DI_USERCONTROL
:
5581 // Len=CurItem->Ptr.PtrLength; BUGBUG
5588 case DI_RADIOBUTTON
:
5589 Len
= StrLength(Ptr
) + 1;
5597 if (CurItem
->ObjPtr
) {
5598 Len
= ((DlgEdit
*)(CurItem
->ObjPtr
))->GetLength() + 1;
5604 MenuItemEx
*ListMenuItem
;
5606 if ((ListMenuItem
= CurItem
->ListPtr
->GetItemPtr(-1))) {
5607 Len
= (int)ListMenuItem
->strName
.GetLength() + 1;
5617 return Len
- (!Len
? 0 : 1);
5619 /*****************************************************************/
5620 case DM_SETTEXTPTR
: {
5624 FarDialogItemData IData
= {(size_t)StrLength((wchar_t *)Param2
), (wchar_t *)Param2
};
5625 return SendDlgMessage(hDlg
, DM_SETTEXT
, Param1
, (LONG_PTR
)&IData
);
5628 case DM_SETTEXTPTRSILENT
: {
5632 if (CurItem
->Type
!= DI_FIXEDIT
&& CurItem
->Type
!= DI_EDIT
)
5635 reinterpret_cast<DlgEdit
*>(CurItem
->ObjPtr
)->SetCallbackState(false);
5636 FarDialogItemData IData
= {(size_t)StrLength((wchar_t *)Param2
), (wchar_t *)Param2
};
5637 intptr_t rv
= SendDlgMessage(hDlg
, DM_SETTEXT
, Param1
, (LONG_PTR
)&IData
);
5638 reinterpret_cast<DlgEdit
*>(CurItem
->ObjPtr
)->SetCallbackState(true);
5643 /*****************************************************************/
5646 int NeedInit
= TRUE
;
5647 FarDialogItemData
*did
= (FarDialogItemData
*)Param2
;
5660 case DI_RADIOBUTTON
:
5663 case DI_LISTBOX
: // меняет только текущий итем
5664 CurItem
->strData
= did
->PtrData
;
5665 Len
= (int)CurItem
->strData
.GetLength();
5673 case DI_USERCONTROL
:
5674 /*CurItem->Ptr.PtrLength=did->PtrLength;
5675 CurItem->Ptr.PtrData=did->PtrData;
5676 return CurItem->Ptr.PtrLength;*/
5683 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) {
5684 if (!Dlg
->DialogMode
.Check(DMODE_KEEPCONSOLETITLE
))
5685 ConsoleTitle::SetFarTitle(Dlg
->GetDialogTitle());
5686 Dlg
->ShowDialog(Param1
);
5690 return Len
- (!Len
? 0 : 1);
5693 case DI_RADIOBUTTON
:
5703 if (CurItem
->ObjPtr
) {
5704 DlgEdit
*EditLine
= (DlgEdit
*)(CurItem
->ObjPtr
);
5705 int ReadOnly
= EditLine
->GetReadOnly();
5706 EditLine
->SetReadOnly(0);
5707 EditLine
->DisableAC();
5708 EditLine
->SetString(CurItem
->strData
);
5709 EditLine
->RevertAC();
5710 EditLine
->SetReadOnly(ReadOnly
);
5712 if (Dlg
->DialogMode
.Check(DMODE_INITOBJECTS
)) // не меняем клеар-флаг, пока не проиницализировались
5713 EditLine
->SetClearFlag(0);
5715 EditLine
->Select(-1, 0); // снимаем выделение
5716 // ...оно уже снимается в DlgEdit::SetString()
5720 case DI_LISTBOX
: // меняет только текущий итем
5722 VMenu
*ListBox
= CurItem
->ListPtr
;
5725 FarListUpdate LUpdate
;
5726 LUpdate
.Index
= ListBox
->GetSelectPos();
5727 MenuItemEx
*ListMenuItem
= ListBox
->GetItemPtr(LUpdate
.Index
);
5730 LUpdate
.Item
.Flags
= ListMenuItem
->Flags
;
5731 LUpdate
.Item
.Text
= Ptr
;
5732 SendDlgMessage(hDlg
, DM_LISTUPDATE
, Param1
, (LONG_PTR
)&LUpdate
);
5739 default: // подразумеваем, что остались
5744 Dlg
->InitDialogObjects(Param1
); // переинициализируем элементы диалога
5746 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) // достаточно ли этого????!!!!
5748 Dlg
->ShowDialog(Param1
);
5752 // CurItem->strData = did->PtrData;
5753 return CurItem
->strData
.GetLength(); //???
5758 /*****************************************************************/
5759 case DM_SETMAXTEXTLENGTH
: {
5760 if ((Type
== DI_EDIT
|| Type
== DI_PSWEDIT
5761 || (Type
== DI_COMBOBOX
&& !(CurItem
->Flags
& DIF_DROPDOWNLIST
)))
5762 && CurItem
->ObjPtr
) {
5763 int MaxLen
= ((DlgEdit
*)(CurItem
->ObjPtr
))->GetMaxLength();
5764 // BugZ#628 - Неправильная длина редактируемого текста.
5765 ((DlgEdit
*)(CurItem
->ObjPtr
))->SetMaxLength((int)Param2
);
5766 // if (DialogMode.Check(DMODE_INITOBJECTS)) //???
5767 Dlg
->InitDialogObjects(Param1
); // переинициализируем элементы диалога
5768 if (!Dlg
->DialogMode
.Check(DMODE_KEEPCONSOLETITLE
))
5769 ConsoleTitle::SetFarTitle(Dlg
->GetDialogTitle());
5775 /*****************************************************************/
5776 case DM_GETDLGITEM
: {
5777 FarDialogItem
*Item
= (FarDialogItem
*)Param2
;
5778 return (LONG_PTR
)ConvertItemEx2(Item
, CurItem
);
5780 /*****************************************************************/
5781 case DM_GETDLGITEMSHORT
: {
5782 if (Param2
&& ConvertItemEx(CVTITEM_TOPLUGINSHORT
, (FarDialogItem
*)Param2
, CurItem
, 1))
5786 /*****************************************************************/
5788 case DM_SETDLGITEMSHORT
: {
5792 if (Type
!= ((FarDialogItem
*)Param2
)->Type
) // пока нефига менять тип
5796 if (!ConvertItemEx((Msg
== DM_SETDLGITEM
) ? CVTITEM_FROMPLUGIN
: CVTITEM_FROMPLUGINSHORT
,
5797 (FarDialogItem
*)Param2
, CurItem
, 1))
5798 return FALSE
; // invalid parameters
5800 CurItem
->Type
= Type
;
5802 if ((Type
== DI_LISTBOX
|| Type
== DI_COMBOBOX
) && CurItem
->ListPtr
)
5803 CurItem
->ListPtr
->ChangeFlags(VMENU_DISABLED
, CurItem
->Flags
& DIF_DISABLE
);
5805 // еще разок, т.к. данные могли быть изменены
5806 Dlg
->InitDialogObjects(Param1
);
5807 if (!Dlg
->DialogMode
.Check(DMODE_KEEPCONSOLETITLE
))
5808 ConsoleTitle::SetFarTitle(Dlg
->GetDialogTitle());
5810 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) {
5811 Dlg
->ShowDialog(Param1
);
5817 /*****************************************************************/
5820 + показать/скрыть элемент
5822 -1 - получить состояние
5825 Return: предыдущее состояние
5828 DWORD PrevFlags
= CurItem
->Flags
;
5832 CurItem
->Flags
&= ~DIF_HIDDEN
;
5834 CurItem
->Flags
|= DIF_HIDDEN
;
5836 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) // && (PrevFlags&DIF_HIDDEN) != (CurItem->Flags&DIF_HIDDEN))//!(CurItem->Flags&DIF_HIDDEN))
5838 if ((CurItem
->Flags
& DIF_HIDDEN
) && Dlg
->FocusPos
== (unsigned)Param1
) {
5839 Param2
= Dlg
->ChangeFocus(Param1
, 1, TRUE
);
5840 Dlg
->ChangeFocus2((int)Param2
);
5843 // Либо все, либо... только 1
5844 Dlg
->ShowDialog(Dlg
->GetDropDownOpened() || (CurItem
->Flags
& DIF_HIDDEN
) ? -1 : Param1
);
5849 return (PrevFlags
& DIF_HIDDEN
) ? FALSE
: TRUE
;
5851 /*****************************************************************/
5852 case DM_SETDROPDOWNOPENED
: // Param1=ID; Param2={TRUE|FALSE}
5854 if (!Param2
) // Закрываем любой открытый комбобокс или историю
5856 if (Dlg
->GetDropDownOpened()) {
5857 Dlg
->SetDropDownOpened(FALSE
);
5865 у DI_PSWEDIT не бывает хистори!
5868 && (Type
== DI_COMBOBOX
5869 || ((Type
== DI_EDIT
|| Type
== DI_FIXEDIT
) && (CurItem
->Flags
& DIF_HISTORY
)))) /* DJ $ */
5871 // Открываем заданный в Param1 комбобокс или историю
5872 if (Dlg
->GetDropDownOpened()) {
5873 Dlg
->SetDropDownOpened(FALSE
);
5877 if (SendDlgMessage(hDlg
, DM_SETFOCUS
, Param1
, 0)) {
5878 Dlg
->ProcessOpenComboBox(Type
, CurItem
, Param1
); //?? Param1 ??
5879 // Dlg->ProcessKey(KEY_CTRLDOWN);
5888 /*****************************************************************/
5889 case DM_SETITEMPOSITION
: // Param1 = ID; Param2 = SMALL_RECT
5891 return Dlg
->SetItemRect((int)Param1
, (SMALL_RECT
*)Param2
);
5893 /*****************************************************************/
5896 + переключение/получение состояния Enable/Disable элемента
5899 DWORD PrevFlags
= CurItem
->Flags
;
5903 CurItem
->Flags
&= ~DIF_DISABLE
;
5905 CurItem
->Flags
|= DIF_DISABLE
;
5907 if ((Type
== DI_LISTBOX
|| Type
== DI_COMBOBOX
) && CurItem
->ListPtr
)
5908 CurItem
->ListPtr
->ChangeFlags(VMENU_DISABLED
, CurItem
->Flags
& DIF_DISABLE
);
5911 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) //???
5913 Dlg
->ShowDialog(Param1
);
5917 return (PrevFlags
& DIF_DISABLE
) ? FALSE
: TRUE
;
5921 *(DWORD
*)Param2
= (DWORD
)Dlg
->CtlColorDlgItem(Param1
, CurItem
);
5922 *(DWORD
*)Param2
|= (CurItem
->Flags
& DIF_SETCOLOR
);
5927 CurItem
->Flags
&= ~(DIF_SETCOLOR
| DIF_COLORMASK
);
5928 CurItem
->Flags
|= Param2
& (DIF_SETCOLOR
| DIF_COLORMASK
);
5930 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) { //???
5931 Dlg
->ShowDialog(Param1
);
5938 case DM_GETTRUECOLOR
: {
5939 if (!CurItem
->TrueColors
) {
5940 memset((DialogItemTrueColors
*)Param2
, 0, sizeof(DialogItemTrueColors
));
5942 *(DialogItemTrueColors
*)Param2
= *CurItem
->TrueColors
;
5947 case DM_SETTRUECOLOR
: {
5948 if (!CurItem
->TrueColors
) {
5949 CurItem
->TrueColors
.reset(new DialogItemTrueColors
);
5951 *CurItem
->TrueColors
= *(const DialogItemTrueColors
*)Param2
;
5952 if (Dlg
->InCtlColorDlgItem
== 0 && Dlg
->DialogMode
.Check(DMODE_SHOW
)) { //???
5953 Dlg
->ShowDialog(Param1
);
5959 case DM_SETREADONLY
: {
5961 CurItem
->Flags
|= DIF_READONLY
;
5963 CurItem
->Flags
&= ~DIF_READONLY
;
5965 if (FarIsEdit(Type
)) {
5966 DlgEdit
*CurItemEdit
= (DlgEdit
*)CurItem
->ObjPtr
;
5968 CurItemEdit
->SetReadOnly(Param2
? 1 : 0);
5972 "%s: DM_SETREADONLY invoked for non-edit item %u\n",
5973 __FUNCTION__
, Param1
);
5975 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) { //???
5976 Dlg
->ShowDialog(Param1
);
5982 /*****************************************************************/
5983 // получить позицию и размеры контрола
5984 case DM_GETITEMPOSITION
: // Param1=ID, Param2=*SMALL_RECT
5988 if (Dlg
->GetItemRect(Param1
, Rect
)) {
5989 *reinterpret_cast<PSMALL_RECT
>(Param2
) = Rect
;
5995 /*****************************************************************/
5996 case DM_SETITEMDATA
: {
5997 LONG_PTR PrewDataDialog
= CurItem
->UserData
;
5998 CurItem
->UserData
= Param2
;
5999 return PrewDataDialog
;
6001 /*****************************************************************/
6002 case DM_GETITEMDATA
: {
6003 return CurItem
->UserData
;
6005 /*****************************************************************/
6006 case DM_EDITUNCHANGEDFLAG
: // -1 Get, 0 - Skip, 1 - Set; Выделение блока снимается.
6008 if (FarIsEdit(Type
)) {
6009 DlgEdit
*EditLine
= (DlgEdit
*)(CurItem
->ObjPtr
);
6010 int ClearFlag
= EditLine
->GetClearFlag();
6013 EditLine
->SetClearFlag((int)Param2
);
6014 EditLine
->Select(-1, 0); // снимаем выделение
6016 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) //???
6018 Dlg
->ShowDialog(Param1
);
6028 /*****************************************************************/
6029 case DM_GETSELECTION
: // Msg=DM_GETSELECTION, Param1=ID, Param2=*EditorSelect
6030 case DM_SETSELECTION
: // Msg=DM_SETSELECTION, Param1=ID, Param2=*EditorSelect
6032 if (FarIsEdit(Type
) && Param2
) {
6033 if (Msg
== DM_GETSELECTION
) {
6034 EditorSelect
*EdSel
= (EditorSelect
*)Param2
;
6035 DlgEdit
*EditLine
= (DlgEdit
*)(CurItem
->ObjPtr
);
6036 EdSel
->BlockStartLine
= 0;
6037 EdSel
->BlockHeight
= 1;
6038 EditLine
->GetSelection(EdSel
->BlockStartPos
, EdSel
->BlockWidth
);
6040 if (EdSel
->BlockStartPos
== -1 && !EdSel
->BlockWidth
)
6041 EdSel
->BlockType
= BTYPE_NONE
;
6043 EdSel
->BlockType
= BTYPE_STREAM
;
6044 EdSel
->BlockWidth
-= EdSel
->BlockStartPos
;
6050 EditorSelect
*EdSel
= (EditorSelect
*)Param2
;
6051 DlgEdit
*EditLine
= (DlgEdit
*)(CurItem
->ObjPtr
);
6053 // EdSel->BlockType=BTYPE_STREAM;
6054 // EdSel->BlockStartLine=0;
6055 // EdSel->BlockHeight=1;
6056 if (EdSel
->BlockType
== BTYPE_NONE
)
6057 EditLine
->Select(-1, 0);
6059 EditLine
->Select(EdSel
->BlockStartPos
, EdSel
->BlockStartPos
+ EdSel
->BlockWidth
);
6061 if (Dlg
->DialogMode
.Check(DMODE_SHOW
)) //???
6063 Dlg
->ShowDialog(Param1
);
6076 // Все, что сами не отрабатываем - посылаем на обработку обработчику.
6077 return Dlg
->CallDlgProc(Msg
, Param1
, Param2
);
6082 Посылка сообщения диалогу
6083 Некоторые сообщения эта функция обрабатывает сама, не передавая управление
6084 обработчику диалога.
6086 LONG_PTR WINAPI
SendDlgMessage(HANDLE hDlg
, int Msg
, int Param1
, LONG_PTR Param2
)
6091 return InterThreadCall
<LONG_PTR
, 0>(std::bind(SendDlgMessageSynched
, hDlg
, Msg
, Param1
, Param2
));
6094 void Dialog::SetPosition(int X1
, int Y1
, int X2
, int Y2
)
6096 CriticalSectionLock
Lock(CS
);
6099 RealWidth
= X2
- X1
+ 1;
6104 RealHeight
= Y2
- Y1
+ 1;
6108 ScreenObject::SetPosition(X1
, Y1
, X2
, Y2
);
6110 //////////////////////////////////////////////////////////////////////////
6111 BOOL
Dialog::IsInited()
6113 CriticalSectionLock
Lock(CS
);
6114 return DialogMode
.Check(DMODE_INITOBJECTS
);
6117 void Dialog::SetComboBoxPos(DialogItemEx
*CurItem
)
6119 if (GetDropDownOpened()) {
6121 CurItem
= Item
[FocusPos
];
6123 int EditX1
, EditY1
, EditX2
, EditY2
;
6124 ((DlgEdit
*)CurItem
->ObjPtr
)->GetPosition(EditX1
, EditY1
, EditX2
, EditY2
);
6126 if (EditX2
- EditX1
< 20)
6127 EditX2
= EditX1
+ 20;
6129 if (ScrY
- EditY1
< Min(Opt
.Dialogs
.CBoxMaxHeight
, CurItem
->ListPtr
->GetItemCount()) + 2
6130 && EditY1
> ScrY
/ 2)
6131 CurItem
->ListPtr
->SetPosition(EditX1
,
6132 Max(0, EditY1
- 1 - Min(Opt
.Dialogs
.CBoxMaxHeight
, CurItem
->ListPtr
->GetItemCount()) - 1),
6133 EditX2
, EditY1
- 1);
6135 CurItem
->ListPtr
->SetPosition(EditX1
, EditY1
+ 1, EditX2
, 0);
6139 bool Dialog::ProcessEvents()
6141 return !DialogMode
.Check(DMODE_ENDLOOP
);
6144 void Dialog::SetId(const GUID
&Id
)