Написал код (возможно кроссплатформенный) используя свой старый AutoIt3-код, даже не ожидал что тот же подход - новый цикл опроса сработает и в PureBasic
EnableExplicit
Enumeration
#Win0
#Win1
EndEnumeration
Enumeration
#w0_btn
#w1_btnYes
#w1_btnNo
#w1_ch
#w1_txt
#StatusBar
EndEnumeration
Global LngCheck$, LngYes$, LngNo$, Title$, Text$, OSLang
Define Answer
Declare MsgAsk(Title$, Text$, Width = 270, Height = 170, ChBox = 0, LngCheck$ = "Not to ask any more", LngYes$ = "Yes", LngNo$ = "No", WinID = -1)
Define UserIntLang, *Lang
If OpenLibrary(0, "kernel32.dll")
*Lang = GetFunction(0, "GetUserDefaultUILanguage")
If *Lang
UserIntLang = CallFunctionFast(*Lang)
EndIf
CloseLibrary(0)
EndIf
; En
LngCheck$ = "Not to ask any more"
LngYes$ = "Yes"
LngNo$ = "No"
Title$ = "Message"
Text$ = "Use as default?"
; Ru
If UserIntLang = 1049
LngCheck$ = "Больше не спрашивать"
LngYes$ = "OK"
LngNo$ = "Отмена"
Title$ = "Сообщение"
Text$ = "Использовать по умолчанию?"
EndIf
OpenWindow(#Win0, 0, 0, 420, 300, "Win", #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
ButtonGadget(#w0_btn, 20, 20, 90, 30, "Question")
TextGadget(#StatusBar, 20, 60, 330, 150 , "")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #w0_btn
Answer = MsgAsk(Title$, Text$, 250, 100, 1, LngCheck$, LngYes$, LngNo$, #Win0)
SetGadgetText(#StatusBar, "Answer = " + Str(Answer & 1) + #CRLF$ + "Check = " + Str(Answer & 2) + #CRLF$ + "Close = " + Str(Answer & 4))
EndSelect
Case #PB_Event_CloseWindow
CloseWindow(#Win0)
End
EndSelect
ForEver
Procedure MsgAsk(Title$, Text$, Width = 270, Height = 170, ChBox = 0, LngCheck$ = "Not to ask any more", LngYes$ = "Yes", LngNo$ = "No", WinID = -1)
Protected Answer, hWnd
If Width < 170
Width = 170
EndIf
If WinID > -1
hWnd = WindowID(WinID)
DisableWindow(WinID, 1)
Else
hWnd = 0
EndIf
OpenWindow(#Win1, 0, 0, Width, Height, Title$, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, hWnd)
TextGadget(#w1_txt, 10, 10, Width - 20, Height - 75, Text$)
CheckBoxGadget(#w1_ch, 10, Height - 65, Width - 20, 17, LngCheck$)
; SetGadgetState(#w1_ch, ChBox)
If ChBox
SetGadgetState(#w1_ch, #PB_Checkbox_Checked)
EndIf
ButtonGadget(#w1_btnYes, (Width - 150) / 2, Height - 40, 70, 28, LngYes$)
ButtonGadget(#w1_btnNo, (Width - 150) / 2 + 80, Height - 40, 70, 28, LngNo$)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #w1_btnYes
Answer | 1
Break
Case #w1_btnNo
Break
EndSelect
Case #PB_Event_CloseWindow
Answer | 4
Break
EndSelect
ForEver
If GetGadgetState(#w1_ch)
Answer | 2
EndIf
If hWnd
DisableWindow(WinID, 0)
EndIf
CloseWindow(#Win1)
ProcedureReturn Answer
EndProcedureну и сразу подняли тему такой же мессаги на WinAPI, я его перевёл на русский язык и сделал две правки - уменьшил позицию чекбокса с 95 на 73, так как наваливался на кнопки и закомментировал *lpcs\cy + 30 так как увеличение высоты мессаги у меня на Win10 не сдвигает кнопки вниз, поэтому нет смысла в этом действии.
; Sparkie, updated for PB6+ by Fred
; https://www.purebasic.fr/english/viewtopic.php?p=171031#p171031
; *****************************************************
; Code : MessageRequester с флажком "Больше не спрашивать"
; Author : Sparkie
; Date : Ноябрь 17, 2006
; OS : Windows только
; License : Вы можете использовать это по своему усмотрению.
; (упоминание авторства и ссылки на оригинал приветствуются)
; *****************************************************
Global hHook = 0, oldProc = 0, NotAskAgain = 0
; Этого до сих пор нет в PB по умолчанию
#BS_TEXT = 0
; Убедитесь, что идентификатор флажка <> любой из других кнопок MessageRequester
#CheckBoxID = 12
; Подкласс процедуры MessageRequester()
Procedure MsgBoxProc(hwnd, msg, wParam, lParam)
result = CallWindowProc_(oldProc, hwnd, msg, wParam, lParam)
Select msg
Case #WM_DESTROY
; Получает дескриптор флажка
hCheckBox = GetDlgItem_(hwnd, #CheckBoxID)
; Получает состояние флажка. 0 - не отмечено, 1 - отмечено
; Для этого теста добавлено: Global var = состояние CheckBox.
; В реальной программе можно сохранить значение в файл config/ini
; или, можно использовать настройку в реестре
NotAskAgain = SendMessage_(hCheckBox, #BM_GETCHECK, 0, 0)
EndSelect
ProcedureReturn result
EndProcedure
; наша hook Procedure()
Procedure CBTProc(nCode, wParam, lParam)
result = CallNextHookEx_(hHook, nCode, wParam, lParam)
; Здесь создание MessageRequester
If nCode = #HCBT_CREATEWND
*cbt_cw.CBT_CREATEWND = lParam
*lpcs.CREATESTRUCT = *cbt_cw\lpcs
; Применить только если это наш MessageRequester
If *lpcs\hWndParent = WindowID(0) And *lpcs\lpszClass = 32770
; Измените размер MessageRequester, чтобы освободить место для нашего CheckBoxGadget.
; *lpcs\cy + 30 ; на Win10 не смещает вниз кнопки ОК, Отмена, так что это бессмысленно
EndIf
result = 0
EndIf
; MessageRequester вот-вот станет активным
; Здесь добавляется флажок "Больше не спрашивать".
If nCode = #HCBT_ACTIVATE
hMsgBox = wParam
; Подкласс MessageRequester
oldProc = SetWindowLong_(hMsgBox, #GWL_WNDPROC, @MsgBoxProc())
hCheckBox = CreateWindowEx_(0, "Button", "Больше не спрашивать", #BS_AUTOCHECKBOX | #BS_TEXT | #WS_GROUP | #WS_TABSTOP | #WS_CHILD | #WS_VISIBLE, 10, 73, 150, 25, hMsgBox, #CheckBoxID, GetModuleHandle_(0), 0)
hFont = GetStockObject_(#DEFAULT_GUI_FONT)
SendMessage_(hCheckBox, #WM_SETFONT, hFont, 0) ; иначе жирный шрифт
; Освобождает hook
If hHook
UnhookWindowsHookEx_(hHook)
hHook = 0
EndIf
result = 0
EndIf
ProcedureReturn result
EndProcedure
If OpenWindow(0, 100, 100, 300, 200, "Больше не спрашивать", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
ButtonGadget(1, 10, 40, 280, 27, "Показать свой MessageRequester")
TextGadget(2, 10, 80, 280, 25, "")
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget And EventGadget() = 1
; Создаёт локальный хук для наблюдения за MessageRequester
If NotAskAgain
MessageRequester("Извини", "Вы просили больше не показывать это сообщение.", #MB_OK | #MB_ICONINFORMATION)
Else
hHook = SetWindowsHookEx_(#WH_CBT, @CBTProc(), 0, GetCurrentThreadId_())
MessageRequester("Добро пожаловать", "Вы хотите продолжить?", #MB_YESNO | #MB_ICONQUESTION)
EndIf
Select NotAskAgain
Case 0
SetGadgetText(2, "Не отмечено 'Больше не спрашивать'")
Case 1
SetGadgetText(2, "Отмечено 'Больше не спрашивать'")
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
; На всякий случай повтороное удаление хука, если он все еще существует.
If hHook
UnhookWindowsHookEx_(hHook)
hHook = 0
EndIf
EndОтредактировано AZJIO (17.04.2023 09:50:01)