Форум » GUI » Проблема с MDI окнами » Ответить

Проблема с MDI окнами

Dr. Oldwarez: Вот, хочу перевести программу на MDI интерфейс и обнаружил неприятный сюрприз. В MDI окнах невозможно стало устанавливать свойства элементов управления после их создания. Например, нужно в программе редактирования, чтобы после создания GETBOXа в него блокировали ввод, если это режим правки строки и разрешали ввод в режиме дозаписи. wndEdit.txtID.ReadOnly:=!lNew где lNew - флаг режима дозаписи. Почему-то при перестановке окна в MDI выдаётся сбой, будто такого элемента управления нет.

Ответов - 34, стр: 1 2 All

gfilatov2002: Dr. Oldwarez пишет: В MDI окнах невозможно стало устанавливать свойства элементов управления после их создания. Дело в том, что MDI окна - это отдельная замутная история. Для них имя формы надо определять через функцию MyGetMdiHandle() и устанавливать свойства элементов таким образом setproperty(MyGetMdiHandle(),"EditMdi","VALUE","new set") Подробнее см. пример в папке basic\mdi_3

Dr. Oldwarez: Спасибо! Да, история и впрямь замутная.

Dr. Oldwarez: Начинаю уже понемногу разбираться с этой замутной историей. Уже знаю, что такое SETPROPERTY и GETPROPERTY и даже использовал их. Но вот следующая проблема, посерьёзнее. Нужно в функции сохранения таблицы использовать значения элементов управления, считанных из окна редактирования, типа Table->Field:=wndEdit.EditMdi.Value Стал использовать GETPROPERTY(MyGetMdiHandle(),"EditMdi","VALUE") и тут-то меня ожидал ОБЛОМ. Программа выругалась, что этот элемент управления будто бы НЕ СОЗДАН. Подскажите, пожалуйста, что делать. Заранее благодарен


Andrey: Я вообще то слабо еще разбираюсь в МиниГуи, но если даш самодостаточный пример, то попытаюсь помочь.

SergKis: gfilatov2002 пишет: Дело в том, что MDI окна - это отдельная замутная история. Хочу поделиться нашим опытом размутнения MDI окон, в рамках MiniGui и перевода задач с WVT. [pre2] 1. Для работы с child окнами мы сделали изменение (h_windowsMDI.prg): Function _DefineChildMDIWindow (...) ... ChildIndex := _HMG_ActiveMDIChildIndex + 1 IF AScan( _HMG_aFormNames, FormName ) > 0 // BK 3-Май-2012 16:09:05 FormName += '_'+alltrim(str(ChildIndex)) ENDIF // BK 3-Май-2012 16:09:46 ... т.е. первое имя child окна не искажается и можно использовать форму записи: FormChild.Browse_1 и т.д. Удобнее переносить примеры и свои наработки с такой формой записи. Но это изменение можно и не делать. 2. Добавили C функцию: HB_FUNC ( ISWINDOWHANDLE ) // Наличие окна по handle { hb_retl( IsWindow( (HWND) hb_parnl(1) ) ); } 3. Перед созданием окна можно делать: // IF _IsWindowDefined(::cWnd) // окно уже есть (func.в MiniGui) IF IsWindowHandle(::hWnd) // окно уже есть по handle определяем _MdiWindowsActivate(::hWnd) // сделать активным RETURN // выход без создания окна ENDIF или // IF _IsWindowDefined(::cWnd) // окно уже есть (func.в MiniGui) IF IsWindowHandle(::hWnd) // окно уже есть по handle определяем IF _MdiChildClose(::hWnd) == 0; DestroyActiveMdi(::hWnd) // разрушать окно ENDIF ENDIF // создаем окно DECLARE WINDOW Form_1 // Main MDI DEFINE WINDOW &( ::cWnd ) ; TITLE ::cTitle ; MDICHILD FOCUSED NOMINIMIZE ; ON INIT Self:OnInit() ; ON RELEASE Self:OnRelease() ; ON SIZE Self:OnReSize(.T.) ; ON MAXIMIZE Self:OnReSize(.T.) ::hWnd := GetFormHandle(::cWnd) // запомнили Handler окна ... Удобно использовать объекты. Но это на любителя. 4. Для работы на child mdi окне с модальным окном потребовалась функция сохранения-востановления _HMG_переменых: FUNCTION Set_Rest_HMG( aHmg ) LOCAL a IF empty( aHmg ) a := array(9) a[1] := _HMG_BeginWindowMDIActive a[2] := _HMG_ActiveStatusHandle a[3] := _hmg_UserWindowHandle a[4] := _HMG_SetFocusExecuted a[5] := _HMG_ThisFormName a[6] := _HMG_ThisControlName a[7] := _HMG_ActiveFontName a[8] := _HMG_ActiveFontSize a[9] := _HMG_ExtendedNavigation _HMG_BeginWindowMDIActive := .F. // снимаем MDI режим _HMG_ExtendedNavigation := .T. // навигация по Enter включена ELSE _HMG_BeginWindowMDIActive := aHmg[1] _HMG_ActiveStatusHandle := aHmg[2] _hmg_UserWindowHandle := aHmg[3] _HMG_SetFocusExecuted := aHmg[4] _HMG_ThisFormName := aHmg[5] _HMG_ThisControlName := aHmg[6] _HMG_ActiveFontName := aHmg[7] _HMG_ActiveFontSize := aHmg[8] _HMG_ExtendedNavigation := aHmg[9] ENDIF RETURN a Перед созданием модального окна сохраняем: a := Set_Rest_HMG() После работы с модальным окном востанавливаем: Set_Rest_HMG(a) 5. Максимально работать по Handler окон и контролов, а не по именам. [/pre2]

SergKis: SergKis пишет:Хочу поделиться ... Прервали. Продолжение: [pre2] 6. Нам показалось удобным иметь свой ToolBar на каждом child окне (как в Clipper последняя строка экрана): ::hTBar := _DefineSplitBox(::cWnd) // Handler для определения Height ToolBar DEFINE TOOLBAR &( ::cTBar ) OF &( ::cWnd ) CAPTION ::cTBarCapt BUTTONSIZE ::nTBarBtnW,::nTBarBtnH FLAT BUTTON TB_New ; CAPTION '' ; PICTURE 'page_new' ; TOOLTIP gTxt("BtnNew")+' F2' ; ACTION BrwEvent("VK_F2") BUTTON TB_Del ; CAPTION '' ; PICTURE 'page_del' ; TOOLTIP gTxt("BtnDel")+' F3' ; ACTION BrwEvent("VK_F3") BUTTON TB_Edit ; CAPTION '' ; PICTURE 'page_edit' ; TOOLTIP gTxt("BtnEdit")+' F4' ; ACTION BrwEvent("VK_F4") ; SEPARATOR IF ::lEnter BUTTON TB_Enter ; CAPTION '' ; PICTURE 'page_enter' ; TOOLTIP gTxt("BtnEnter")+' Enter' ; ACTION BrwEvent("VK_RETURN") ; SEPARATOR ENDIF .... END TOOLBAR 7. Изменили h_label.prg (вертикальная центровка текста): Function _DefineLabel ( ControlName, ParentFormName, x, y, Caption, w, h,; fontname, fontsize, bold, BORDER, CLIENTEDGE, HSCROLL, VSCROLL,; TRANSPARENT, aRGB_bk, aRGB_font, ProcedureName, tooltip, HelpId, invisible,; italic, underline, strikeout, autosize, rightalign, centeralign,; blink, mouseover, mouseleave, nId, VCenterAlign ) // BK 10.06.2012 ... DEFAULT underline TO FALSE DEFAULT strikeout TO FALSE DEFAULT VCenterAlign TO TRUE // BK 10.06.2012 ... if centeralign ; Style += ES_CENTER endif IF VCenterAlign ; Style += SS_CENTERIMAGE // BK 10.06.2012 ENDIF ... 8. Формирование Browse: @ ::nBrwY, ::nBrwX BROWSE &( ::cBrw ) ; WIDTH ::nBrwW ; HEIGHT ::nBrwH ; HEADERS ::aHeads ; WIDTHS ::aWidth ; WORKAREA &( ::cAls ) ; FIELDS ::aFields ; VALUE Self:CurRec(.F.) ; TOOLTIP ::aToolTip ; DYNAMICBACKCOLOR ::aBgColor ; DYNAMICFORECOLOR ::aFgColor ; ON CHANGE Self:BrwOnChange() ; EDIT INPLACE ; APPEND ; INPUTITEMS ::aInputItem ; DISPLAYITEMS ::aDisplayItem ; ON HEADCLICK ::aHdrClick ; WHEN ::aWhen ; VALID ::aValid ; VALIDMESSAGES ::aMessage ; READONLY ::aROnly ; DELETE ; IMAGE ::aImage ; JUSTIFY ::aJustify ; HEADERIMAGE ::aImageHdr ::nBrwI := GetControlIndex(::cBrw, ::cWnd) // Browse index ::hBrw := _HMG_aControlHandles [::nBrwI] // Browse handle _HMG_aControlMiscData2[::nBrwI] := Self // Browse CARGO запомнили объект [/pre2] MDI окна заработали. Одна задача (квартплата) на 90% переведена с WVT, другие в наальной стадии.

Dr. Oldwarez: Не, у меня проблема такая: есть EDIT-окно, где содержимое строки таблицы отображается в разных textbox-ах и т.д. При нажатии кнопки btnSave всё содержимое полей редактирования должно сохраняться в строку таблицы, для чего есть отдельная функция SaveTable(lNew), вызываемая при нажатии кнопки btnSave FUNCTION SaveTable(lNew) ................... wndEdit.TextBox1.Value:=Table->Field_1 wndEdit.TextBox2.Value:=Table->Field_2 .................... RETURN и вот тут-то оно ругается, что окно wndEdit не создано, хотя оно явно создано, иначе, откуда бы взялась кнопка вызова функции?

SergKis: Dr.Oldwarez пишет: у меня проблема такая ... Родной текст создания MDI child окон:[pre2]Function _DefineChildMDIWindow (...) ... ChildIndex := _HMG_ActiveMDIChildIndex + 1 // это счетчик, создающий уникальное имя child окон FormName += '_'+alltrim(str(ChildIndex)) // МЕНЯЕТСЯ ИМЯ ОКНА прибавлением индекса .[/pre2] Ваше : wndEdit.TextBox1.Value:=Table->Field_1 wndEdit.TextBox2.Value:=Table->Field_2 действительно идет к несуществующему окну "wndEdit", потому что через I_VAR.CH оно превращается: SetProperty("wndEdit","TextBox2","Value",Table->Field_2), а _DefineChildMDIWindow (...) создало окно с именем:"wndEdit"+'_'+alltrim(str(ChildIndex)). Для правильной работы ВСЕГДА надо запоминать ДЕЙСТВИТЕЛЬНОЕ имя окна: cWnd := _GetWindowProperty( , "PROP_FORMNAME") Пример: DEFINE WINDOW wndEdit ; ... END WINDOW cWndName := _GetWindowProperty( , "PROP_FORMNAME") и теперь возможно выполнять: SetProperty(cWndName,"TextBox2","Value",Table->Field_2) т.е. в родном варианте miniGUI при работе с MDI окнами ЗАБУДЬТЕ обращения через псевдо объект: wndEdit.TextBox1.Value !!!

Andrey: SergKis пишет: т.е. в родном варианте miniGUI при работе с MDI окнами ЗАБУДЬТЕ обращения через псевдо объект: wndEdit.TextBox1.Value !!! Супер ! Спасибо за совет !

SergKis: SergKis пишет:через I_VAR.CH ... Прошу прощения I_VAR.CH - это список HMG_... переменных

Dr. Oldwarez: Огромное спасибо за помощь! Правда переделывать программу в 20 тыс строк исходного кода - это воистину Геркулесов труд.

SergKis: Dr.Oldwarez пишет:Правда переделывать программу в 20 тыс строк исходного кода ... Если дело только в обращении через псевдо объект, то возьмите h_windowsMdi.prg к своему проекту и в своем prg файле с main(..) , например, в самом конце добавьте #include "h_windowsMdi.prg". В h_windowsMdi.prg закоментируйте Memvar, сделайте изменения: [pre2] IF AScan( _HMG_aFormNames, FormName ) > 0 // BK 3-Май-2012 16:09:05 FormName += '_'+alltrim(str(ChildIndex)) ENDIF // BK 3-Май-2012 16:09:46 [/pre2] Соберите проект. Все должно работать, имя окна не будет меняться.

SergKis: Возможно кому-то будут полезны наши тесты с MDI окнами. Примеры MDI Сборка VC9 и своя miniGui, hb 2.0

Vlad04: Конечно, полезны!

Andrey: SergKis пишет: Возможно кому-то будут полезны наши тесты с MDI окнами. Спасибо за примеры !

SergKis: Возвращаюсь к вопросу искажения имени окна в MDI окнах. Я думаю многие были бы удивлены, если при открытии dbf с алиасом AAA получили бы алиас AAA_1327. Так сейчас происходит в MDI окнах. Возможно, я что-то не понимаю, но алгоритм со счетчиком нужен, если имя окна cFormName не задано, а в остальном он должен быть таким же, как и в не MDI окнах, т.е. при повторении имени - ошибка и управление уникальностью имен - это дело человека. Или я в чем-то не прав ?

rovix: SergKis пишет: Возможно кому-то будут полезны наши тесты с MDI окнами. Примеры MDI Сборка VC9 и своя miniGui, hb 2.0 Ссылочка протухла, можно ещё раз выложить?

rovix: SergKis пишет: В h_windowsMdi.prg закоментируйте Memvar, сделайте изменения: IF AScan( _HMG_aFormNames, FormName ) > 0 // BK 3-Май-2012 16:09:05 FormName += '_'+alltrim(str(ChildIndex)) ENDIF // BK 3-Май-2012 16:09:46 А для тех кто в танке можно подробнее? Я вот смотрю в этот файл, там строки немного другие [pre2] IF ValType( FormName ) == "U" FormName := _HMG_TempWindowName ENDIF ChildIndex := _HMG_ActiveMDIChildIndex + 1 FormName += '_' + AllTrim( Str( ChildIndex ) ) [/pre2], ну да ладно, вроде последняя строка из приведённого фрагмента, однако смущает и первая строка - во что она переделает FormName? а закомментировать memvar, это какое из двух имеющихся? [pre2] MEMVAR mVar #ifdef _TSBROWSE_ MEMVAR _TSB_aControlhWnd, _TSB_aControlObjects, _TSB_aClientMDIhWnd #endif [/pre2]

SergKis: rovix пишет:Ссылочка протухла, можно ещё раз выложить? Test MDI

SergKis: rovix пишет:можно подробнее [pre2] IF ValType( FormName ) == "U" FormName := _HMG_TempWindowName ENDIF ChildIndex := _HMG_ActiveMDIChildIndex + 1 IF AScan( _HMG_aFormNames, FormName ) > 0 // окно с именем FormName уже есть FormName += '_' + AllTrim( Str( ChildIndex ) ) ENDIF ... [/pre2] rovix пишет:а закомментировать memvar, это какое из двух имеющихся? [pre2] /* комментируем все строки здесь MEMVAR mVar #ifdef _TSBROWSE_ MEMVAR _TSB_aControlhWnd, _TSB_aControlObjects, _TSB_aClientMDIhWnd #endif */ [/pre2] Правильно перенести эти строки перед : MEMVAR mVar #ifdef _TSBROWSE_ MEMVAR _TSB_aControlhWnd, _TSB_aControlObjects, _TSB_aClientMDIhWnd #endif FUNCTION MAIN() ... RETURN



полная версия страницы