Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Menu/Toolbar dlg in exe
#1
Hi All,
I created this to add Menu/Toolbar dlg in exe. It works pretty well but I am sure Gintaras could class it up!! Big Grin

Function TestExeDlgMenu
Code:
Copy      Help
\Dialog_Editor

function# hDlg message wParam lParam
if(hDlg) goto messages

CloseWindowsOf("DlgMenu" "#32770");err
run "$system$\notepad.exe" "" "" "" 0x1800 win("Notepad" "Notepad")
if(!ShowDialog("TestExeDlgMenu" &TestExeDlgMenu 0)) ret

;BEGIN DIALOG
;0 "" 0x80000840 0x90 0 0 385 11 "DlgMenu"
;3 Button 0x54032000 0x0 0 0 48 11 "Button1"
;4 Button 0x54032000 0x0 48 0 48 11 "Button2"
;5 Button 0x54032000 0x0 96 0 48 11 "Button3"
;6 Button 0x54032000 0x0 144 0 48 11 "Button4"
;7 Button 0x54032000 0x0 192 0 48 11 "Button5"
;8 Button 0x54032000 0x0 240 0 48 11 "Button6"
;9 Button 0x54032000 0x0 288 0 48 11 "Button7"
;10 Button 0x54032000 0x0 336 0 48 11 "Button8"
;1 Button 0x54030001 0x4 64 402 48 11 "OK"
;2 Button 0x54030000 0x4 118 402 48 11 "Cancel"
;END DIALOG
;DIALOG EDITOR: "" 0x2030502 "*" "" "" ""




ret
;messages
sel message
,case WM_INITDIALOG
,__GdiHandle-- hb=CreateSolidBrush(0xff00)
,Transparent hDlg 255 0xff00
,int+ NotePadHwnd = win("Notepad" "Notepad")
,SetWindowLong hDlg GWL_HWNDPARENT NotePadHwnd
,SetTimer hDlg 1 100 0
,;SendMessage hDlg WM_COMMAND 5 0 ;;execute gButton code. Or use function instead.
,SendMessage hDlg WM_TIMER 1 0 ;;execute gTimer code. Or use function instead.    
,case WM_TIMER
,sel wParam
,,case 1 goto gTimer    
,case WM_DESTROY    
,case WM_CTLCOLORDLG ret hb
,case WM_COMMAND goto messages2
,
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1

;gButton
ret

;gTimer
Zorder hDlg HWND_TOP SWP_NOACTIVATE
int x_NotePad y_NotePad cx_NotePad cy_NotePad;
ifi(NotePadHwnd)    
,GetWinXY NotePadHwnd x_NotePad y_NotePad cx_NotePad cy_NotePad
else
,CloseWindowsOf("DlgMenu" "#32770");err
,ret
int x_Dlg y_Dlg cx_Dlg cy_Dlg
GetWinXY hDlg x_Dlg y_Dlg cx_Dlg cy_Dlg
MoveWindow hDlg x_NotePad+25 y_NotePad+3 cx_NotePad-100 cy_Dlg  1;;need to leave enough room for max/min/close app dlg frame buttons and enough of frame to grab for moving/resizing
#2
It works. Improving would be endless.
#3
Yes, recreating all the things you already natively support in QM in Toolbars and menu's would indeed be endless. But this works for anyone who has QM dialog making skills to add anything they want into exe....Thanks for looking at it and giving it your blessing! :-)

S
#4
Sorry to kick this topic up, but I do not understand something.

The settimer line:

Code:
Copy      Help
SetTimer hDlg 1 100 0

The "gTimer SendMessage" line

Code:
Copy      Help
SendMessage hDlg WM_TIMER 1 0


If I disable the "gTimer SendMessage" line, the function seems to work exactly the same as with the "gTimer SendMessage" line enabled.

From:
https://msdn.microsoft.com/en-us/librar ... 85%29.aspx

Code:
Copy      Help
UINT_PTR WINAPI SetTimer(
  _In_opt_  HWND hWnd,
  _In_      UINT_PTR nIDEvent,
  _In_      UINT uElapse,
  _In_opt_  TIMERPROC lpTimerFunc
);

nIDEvent [in]
Type: UINT_PTR
A nonzero timer identifier. If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated. If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored. If the call is not intended to replace an existing timer, nIDEvent should be 0 if the hWnd is NULL.


The timer identifier has already been set in:
Code:
Copy      Help
SetTimer hDlg 1 100 0

So the below code always catches the timer id "1"

Code:
Copy      Help
    case WM_TIMER
    sel wParam
        case 1 goto gTimer

QUESTION:
Am I correct that I can safely remove the "gTimer SendMessage" line: SendMessage hDlg WM_TIMER 1 0 ?
#5
After SetTimer, the first WM_TIMER arrives after the timer period time, in this case 100 ms. But often we want it immediately. Then we can:
1. SendMessage, like here. It calls the dialog procedure.
2. Directly call the dialog procedure: TestExeDlgMenu hDlg WM_TIMER 1 0
3. goto gTimer. But then it must be the last statement under WM_INITDIALOG.
4. Put gTimer code in a function and call it on WM_TIMER and WM_INITDIALOG.
#6
Thank you for the explanation!
#7
What could be the cause when the window that has the button-dialog attached to it stays on top? (does not "wants" to be put at the back of the z order)

What I mean:
If I attach the buttons to notepad, sometimes notepad does not "wants" to be set to the back when I click a window that is behind it (partly overlapped by notepad). Notepad just stays on top and refuses to be set to the the back.

When close notepad (and the macro attached to it) and then restart the macro, notepad behaves noramally (with the dialogbuttons attached).

It may be a thing that can not be prevented because it is inherent to the timer code?
But if there is something there could be done about then it would be greatly appreciated.

(I use this code as a template for many executables, I can enhance about any application with a single executable containing this code!)
#8
Add flag SWP_NOOWNERZORDER when calling Zorder.
Zorder hDlg HWND_TOP SWP_NOACTIVATE|SWP_NOOWNERZORDER

See also:
Insert buttons into a window's caption area
#9
Thank you!!!
#10
Sorry to bother you with another question about this, but if have the following situation (extracted from code above):

Where the first "int+ ApplicationHwnd=..." does not work because of the regex addition.
The line directly below does work, but targets the wrong window (if there are multiple).

Function tcmd_extension
Code:
Copy      Help
,,int+ ApplicationHwnd=win(F"^{ini_winname_main_app}" ini_winclass_main_app 0x200) ;; Does not work
,,int+ ApplicationHwnd=win(F"{ini_winname_main_app}" ini_winclass_main_app) ;; Works
,,;.
,,;.
,,;.
,,;
,,ifi(ApplicationHwnd) ;; Code below in 'gTimer'

Is there a way around this?
The window names are:
- "Total Commander" , for the first window
- "[#] Total Commander" for all the other windows (#=number beginning with '2' then '3' etc....)

It always needs to attach dialog-buttons to "Total Commander" not the one starting with "[#] "
#11
int+ ApplicationHwnd=win(F"^/Q{ini_winname_main_app}/E" ini_winclass_main_app "" 0x200)
or use flag 1 and wildcard characters
#12
Thank you!!!
#13
I added a menu bar definition, how to cancel the display button, only display the menu bar, and the position of the menu bar is always placed in the middle of the title bar.

Some code, can't understand Huh ,  I hope someone can provide an example, thanks in advance


Function TestExeDlgMenu
Code:
Copy      Help
\Dialog_Editor

function# hDlg message wParam lParam
if(hDlg) goto messages

CloseWindowsOf("DlgMenu" "#32770");err
run "$system$\notepad.exe" "" "" "" 0x1800 win("Notepad" "Notepad")

str md=
;BEGIN MENU
;>&File
;,&Open :501 0x0 0x0 Co
;,&Save :502 0x0 0x0 Cs
;,>Submenu
;,,Item1 :551
;,,Item2 :552
;,,<
;,-
;,E&xit :2
;,<
;>&Edit
;,Cu&t :601
;,&Copy :602
;,&Paste :603
;,<
;>&Help
;,&About :901
;,<
;END MENU

;;menu bar example:
;if(!ShowDialog(dd &sub.DlgProc &controls 0 0 0 0 0 0 0 0 md)) ret
;;popup menu example:
;int i=ShowMenu(md); out i

if(!ShowDialog("TestExeDlgMenu" &TestExeDlgMenu 0)) ret

;BEGIN DIALOG
;0 "" 0x80000840 0x90 0 0 385 11 "DlgMenu"
;3 Button 0x54032000 0x0 0 0 48 11 "Button1"
;4 Button 0x54032000 0x0 48 0 48 11 "Button2"
;5 Button 0x54032000 0x0 96 0 48 11 "Button3"
;6 Button 0x54032000 0x0 144 0 48 11 "Button4"
;7 Button 0x54032000 0x0 192 0 48 11 "Button5"
;8 Button 0x54032000 0x0 240 0 48 11 "Button6"
;9 Button 0x54032000 0x0 288 0 48 11 "Button7"
;10 Button 0x54032000 0x0 336 0 48 11 "Button8"
;1 Button 0x54030001 0x4 64 402 48 11 "OK"
;2 Button 0x54030000 0x4 118 402 48 11 "Cancel"
;END DIALOG
;DIALOG EDITOR: "" 0x2030502 "*" "" "" ""

ret
;messages
sel message
,case WM_INITDIALOG
,__GdiHandle-- hb=CreateSolidBrush(0xff00)
,Transparent hDlg 255 0xff00
,int+ NotePadHwnd = win("Notepad" "Notepad")
,SetWindowLong hDlg GWL_HWNDPARENT NotePadHwnd
,SetTimer hDlg 1 100 0
,;SendMessage hDlg WM_COMMAND 5 0 ;;execute gButton code. Or use function instead.
,SendMessage hDlg WM_TIMER 1 0 ;;execute gTimer code. Or use function instead.
,case WM_TIMER
,sel wParam
,,case 1 goto gTimer
,case WM_DESTROY
,case WM_CTLCOLORDLG ret hb
,case WM_COMMAND goto messages2
,
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1

;gButton
ret

;gTimer
Zorder hDlg HWND_TOP SWP_NOACTIVATE
int x_NotePad y_NotePad cx_NotePad cy_NotePad;
ifi(NotePadHwnd)
,GetWinXY NotePadHwnd x_NotePad y_NotePad cx_NotePad cy_NotePad
else
,CloseWindowsOf("DlgMenu" "#32770");err
,ret
int x_Dlg y_Dlg cx_Dlg cy_Dlg
GetWinXY hDlg x_Dlg y_Dlg cx_Dlg cy_Dlg
MoveWindow hDlg x_NotePad+25 y_NotePad+3 cx_NotePad-100 cy_Dlg  1;;need to leave enough room for max/min/close app dlg frame buttons and enough of frame to grab for moving/resizing
#14
Macro Macro362
Code:
Copy      Help
CloseWindowsOf("DlgMenu" "#32770");err
int w
run "$system$\notepad.exe" "" "" "" 0x1800 win("Notepad" "Notepad") w

str md=
;BEGIN MENU
;>&File
;,&Open :501 0x0 0x0 Co
;,&Save :502 0x0 0x0 Cs
;,>Submenu
;,,Item1 :551
;,,Item2 :552
;,,<
;,-
;,E&xit :2
;,<
;>&Edit
;,Cu&t :601
;,&Copy :602
;,&Paste :603
;,<
;>&Help
;,&About :901
;,<
;END MENU

str dd=
;BEGIN DIALOG
;0 "" 0x80000840 0x90 0 0 385 11 "DlgMenu"
;END DIALOG
;DIALOG EDITOR: "" 0x2030502 "*" "" "" ""

if(!ShowDialog(dd &sub.DlgProc 0 0 128 0 0 0 0 0 0 md)) ret

#sub DlgProc v
function# hDlg message wParam lParam
sel message
,case WM_INITDIALOG
,__GdiHandle-- hb=CreateSolidBrush(0xff00)
,Transparent hDlg 255 0xff00
,SetWindowLong hDlg GWL_HWNDPARENT w
,SetTimer hDlg 1 100 0
,;SendMessage hDlg WM_COMMAND 5 0 ;;execute gButton code. Or use function instead.
,SendMessage hDlg WM_TIMER 1 0 ;;execute gTimer code. Or use function instead.
,hid- hDlg
,case WM_TIMER
,sel wParam
,,case 1 goto gTimer
,case WM_DESTROY
,case WM_CTLCOLORDLG ret hb
,case WM_COMMAND goto messages2
,
ret
;messages2
sel wParam
,case 501
,out "Open"
,case IDCANCEL
,out "Exit"
act w; err
ret 1

;gTimer
Zorder hDlg HWND_TOP SWP_NOACTIVATE
int x_NotePad y_NotePad cx_NotePad cy_NotePad;
if !IsWindow(w)
,CloseWindowsOf("DlgMenu" "#32770");err
,ret
GetWinXY w x_NotePad y_NotePad cx_NotePad cy_NotePad
int x_Dlg y_Dlg cx_Dlg cy_Dlg
GetWinXY hDlg x_Dlg y_Dlg cx_Dlg cy_Dlg
MoveWindow hDlg x_NotePad+150 y_NotePad+3 cx_NotePad-300 cy_Dlg  1;;need to leave enough room for max/min/close app dlg frame buttons and enough of frame to grab for moving/resizing

The last line sets dialog position relative to the window.
#15
Thanks for your help, the effect is great, but the hotkeys in the menu are not available. Huh

When I click on the menu and then press the hotkey is in effect, in addition, I found a problem, use the hotkey ctrl+p to exit Notepad, the menu will delay for a few seconds to disappear

Is there a way to make the hotkeys Directly effective in the notpad?

I have an idea,

When I press ctrl, the menu will be activated. Then, when I press ctrl+p, the hotkey in the menu will take effect. Idea

If these functions can be implemented, I think that almost all functions of QM, such as toolbars, menus, context menus, hotkeys, and AutoText, can be used after generating exe files. I hope developers can continue to improve it.  Tongue


Macro Macro3
Code:
Copy      Help
CloseWindowsOf("DlgMenu" "#32770");err
int w
run "$system$\notepad.exe" "" "" "" 0x1800 win("" "Notepad") w

str md=
;BEGIN MENU
;>&File
;,&Open :501 0x0 0x0 Co
;,&Save :502 0x0 0x0 Cs
;,>Submenu
;,,Item1 :551
;,,Item2 :552
;,,<
;,-
;,E&xit :555 0x0 0x0 Cp
;,<
;>&Edit
;,Cu&t :601
;,&Copy :602
;,&Paste :603
;,<
;>&Help
;,&About :901
;,<
;END MENU

str dd=
;BEGIN DIALOG
;0 "" 0x80000840 0x90 0 0 385 11 "DlgMenu"
;END DIALOG
;DIALOG EDITOR: "" 0x2030502 "*" "" "" ""

if(!ShowDialog(dd &sub.DlgProc 0 0 128 0 0 0 0 0 0 md)) ret

#sub DlgProc v
function# hDlg message wParam lParam
sel message
,case WM_INITDIALOG
,__GdiHandle-- hb=CreateSolidBrush(0xff00)
,Transparent hDlg 255 0xff00
,SetWindowLong hDlg GWL_HWNDPARENT w
,SetTimer hDlg 1 100 0
,;SendMessage hDlg WM_COMMAND 5 0 ;;execute gButton code. Or use function instead.
,SendMessage hDlg WM_TIMER 1 0 ;;execute gTimer code. Or use function instead.
,hid- hDlg
,case WM_TIMER
,sel wParam
,,case 1 goto gTimer
,case WM_DESTROY
,case WM_CTLCOLORDLG ret hb
,case WM_COMMAND goto messages2
,
ret
;messages2
sel wParam
,case 501
,out "Open"
,case IDCANCEL
,out "Exit"
,case 555 ;;E&xit
,int w1=win("" "Notepad")
,clo w1
act w; err
ret 1

;gTimer
Zorder hDlg HWND_TOP SWP_NOACTIVATE
int x_NotePad y_NotePad cx_NotePad cy_NotePad;
if !IsWindow(w)
,CloseWindowsOf("DlgMenu" "#32770");err
,ret
GetWinXY w x_NotePad y_NotePad cx_NotePad cy_NotePad
int x_Dlg y_Dlg cx_Dlg cy_Dlg
GetWinXY hDlg x_Dlg y_Dlg cx_Dlg cy_Dlg
MoveWindow hDlg x_NotePad+150 y_NotePad+3 cx_NotePad-300 cy_Dlg  1;;need to leave enough room for max/min/close app dlg frame buttons and enough of frame to grab for moving/resizing


Forum Jump:


Users browsing this thread: 1 Guest(s)