Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Insert buttons into a window's caption area
#1
can this be done with qm ?
here is a c++ article about it:
Insert buttons into a window's caption area

thanks
pi
#2
Yes, but only for windows in current (qm) process. Also I think on XP and vista you have to do it differently. I cannot give an example because it would take very much time.
#3
what about a hook dll like qmshex.dll ?
in the first step only for vista.
register dll and feed it by a trigger list.
pi
#4
On vista, drawing in window caption is especially difficult or even impossible, unless you don't need the glass effect etc. The real solution would be to attach floating windows with buttons, like qm toolbars. And dll is not necessary. Detect window creation and movement using winevents.
#5
with floating windows you mean captionless dynamic dialogs ?
pi
#6
something similar
i would not use dialogs
warning: to make it to work well, especially on vista, you'll spend several months
better use qm toolbars
#7
so do like the 'hello world' example ?
pi
#8
Register a window class using RegisterClassEx. Create captionless windows using CreateWindowEx, owned by the target windows. To detect target window creation and movement, install winevents hook using SetWinEventHook: I want to use mouse event..
#9
RegisterClassEx
Quote:If the class did not exist, returns class atom

what do you mean by atom ?
pi
#10
an integer number that can be used with CreateWindowEx instead of class name. read more in msdn library.
#11
most of that you wrote i already have done many times.

so the storyline should be like this:

install winevents hook
watch for main windows and dialogs
create/attach captionless window using CreateWindowEx, owned by the target window
etc
pi
#12
exactly
#13
should i better make an exe for that ?
pi
#14
can be in exe or not
can be in any programming language
#15
Gintaras Wrote:something similar
i would not use dialogs
warning: to make it to work well, especially on vista, you'll spend several months
better use qm toolbars

I have been using this with a dialog because I do not understand how to use CreateWindowEx. This makes my program choppy when I move my main dialog. My guess is the CreateWindowEx would create a popup but this never seams to work. Can you please give me an example using CreateWindowEx for a button instead of a dialog?
#16
Macro
Code:
Copy      Help
;register class
int+ __xclass
if(!__xclass) __xclass=RegWinClass("xclass" &WndProc_xclass)

;create window
int style=WS_POPUP|WS_BORDER
int exstyle=WS_EX_TOOLWINDOW
int hwnd=CreateWindowEx(exstyle "xclass" 0 style 10 10 50 50 0 0 _hinst 0)

OnScreenDisplay "do you see your window in the top-left corner?"

;wait, or show a dialog
opt waitmsg 1
wait 10

;destroy
DestroyWindow hwnd

Function WndProc_xclass
Code:
Copy      Help
;/
function# hWnd message wParam lParam

;This is window procedure of windows of "xclass" class. It is similar to dialog procedure. Read about window procedures in MSDN library.
;WM_CREATE, WM_DESTROY and other messages are documented in MSDN library.

sel message
,case WM_CREATE
,ShowWindow hWnd SW_SHOWNOACTIVATE
,;here you can create controls (CreateControl), load graphics, etc
,
,case WM_DESTROY
,
,;add more messages here

ret DefWindowProc(hWnd message wParam lParam)
#17
Code:
Copy      Help
;wait, or show a dialog
opt waitmsg 1
wait 10

;destroy
DestroyWindow hwnd

Every time I take away the wait statement and show a dialog the window in the top left corner disappears. I even tried using notepad as the dialog and I just can not keep the window in the top left corner from disappearing. This might be because I always use the handle to the window and just discovered xclass and do not understand it.

Can you show me an example that will show the window in the top left corner of the screen as long as notepad is opened?
#18
the window disappears when the macro ends
#19
should be triggered with a general window created trigger function.
first check what kind of window has been created.
i find main windows and dialogs are interesting.

getwindowlist
windowsmetrics info about theme settings to make the buttons look perfect.
like get transparency level of caption area.
pi
#20
shame on me.
i have not continued this idea.

we still need a qm way to display extra window function icons on titlebars.
i need buttons for collapse, onTop, deskthumb, toMonitor.
perfect solution would be to overlay all titlebar buttons. Confusedhock:

Gintaras Wrote:Macro
Code:
Copy      Help
;register class
int+ __xclass
if(!__xclass) __xclass=RegWinClass("xclass" &WndProc_xclass)

;create window
int style=WS_POPUP|WS_BORDER
int exstyle=WS_EX_TOOLWINDOW
int hwnd=CreateWindowEx(exstyle "xclass" 0 style 10 10 50 50 0 0 _hinst 0)

OnScreenDisplay "do you see your window in the top-left corner?"

;wait, or show a dialog
opt waitmsg 1
wait 10

;destroy
DestroyWindow hwnd

Function WndProc_xclass
Code:
Copy      Help
;/
function# hWnd message wParam lParam

;This is window procedure of windows of "xclass" class. It is similar to dialog procedure. Read about window procedures in MSDN library.
;WM_CREATE, WM_DESTROY and other messages are documented in MSDN library.

sel message
,case WM_CREATE
,ShowWindow hWnd SW_SHOWNOACTIVATE
,;here you can create controls (CreateControl), load graphics, etc
,
,case WM_DESTROY
,
,;add more messages here

ret DefWindowProc(hWnd message wParam lParam)
pi
#21
Hi Gintaras,
Should have studied this part of forum a long time ago.
I "hang" dialogs a lot from various other application windows - they act like extra toolbars containing all sorts of controls - buttons, LBs, CBs, ActiveX WebBrowser controls, etc.
I use dialogs because toolbars can't be used in exe's.
Above you wrote:

Quote:Gintaras wrote:
something similar
i would not use dialogs
warning: to make it to work well, especially on vista, you'll spend several months
better use qm toolbars


I have been using this with a dialog because I do not understand how to use CreateWindowEx. This makes my program choppy when I move my main dialog. My guess is the CreateWindowEx would create a popup but this never seams to work. Can you please give me an example using CreateWindowEx for a button instead of a dialog?

And you gave WndProc_xclass example where it says:

Quote:This is window procedure of windows of "xclass" class. It is similar to dialog procedure. Read about window procedures in MSDN library.
;WM_CREATE, WM_DESTROY and other messages are documented in MSDN library.

sel message
,case WM_CREATE
,ShowWindow hWnd SW_SHOWNOACTIVATE
,;here you can create controls (CreateControl), load graphics, etc


My question is why is this better than creating dlg? In QM environment you have dialog editor so can use that to layout "application" as dialog window. In your example, it seems like would have to be manual coding effort to do this. Am I missing something fundamental?
If so, could you give simple example with a few button elements.
Thanks for any insight.
S
#22
To expand on my questions from prior post, let me give a couple examples for comments:

hook method:

Macro Startup
Code:
Copy      Help
run "$system$\notepad.exe" "" "" "" 0x800 win("Notepad" "Notepad")
ifi-( win("ToolbarDlg" "#32770"))
,mac "NotePadDlg"
mac "exe_window_trigger"

Function NotePadDlg
Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages

int- NotePadHwnd=win("Notepad" "Notepad")
str controls = "3"
str e3
if(!ShowDialog("NotePadDlg" &NotePadDlg &controls NotePadHwnd)) ret


;BEGIN DIALOG
;0 "" 0x90000A48 0x0 0 0 357 15 "ToolbarDlg"
;4 Button 0x54032000 0x0 260 0 48 14 "Button"
;5 Button 0x54032000 0x0 308 0 48 14 "Button"
;3 Edit 0x54030080 0x200 0 0 260 14 ""
;END DIALOG
;DIALOG EDITOR: "" 0x2030605 "" "" "" ""

ret
;messages
DT_AutoSizeControls hDlg message "3sh 4mh 5mh "
sel message
,case WM_INITDIALOG
,int x y cx cy
,GetWinXY(NotePadHwnd x y cx cy)
,mov+ x+50 y+5 cx-225 0 hDlg 0x200
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1

Function exe_window_trigger
Code:
Copy      Help
function hHook event hwnd idObject idChild dwEventThread dwmsEventTime

def EVENT_OBJECT_LOCATIONCHANGE 0x800B



if getopt(nargs)!=7
,int hh=SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE EVENT_OBJECT_LOCATIONCHANGE 0 &exe_window_trigger 0 0 WINEVENT_OUTOFCONTEXT)
,if(!hh) end F"{ERR_FAILED}. {_s.dllerror}"
,opt waitmsg 1
,wait -1
,UnhookWinEvent hh
,ret

;This code runs whenever a window has locationchange.
int NotePadHwnd=win("Notepad" "Notepad")
int ToolbarDlgHwnd = win("ToolbarDlg" "#32770")
if (hwnd ==  NotePadHwnd)
,out "App Window has moved"
,;outw hwnd
,ifi(NotePadHwnd)
,,int x y cx cy
,,GetWinXY(NotePadHwnd x y cx cy)
,,mov+ x+50 y+5 cx-225 0 ToolbarDlgHwnd 0x200
,else
,,ifi(ToolbarDlgHwnd)
,,,clo ToolbarDlgHwnd


Timer (rep) loop method:

Function NotePadDlg2
Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages
run "$system$\notepad.exe" "" "" "" 0x800 win("Notepad" "Notepad")
int- NotePadHwnd=win("Notepad" "Notepad")
str controls = "3"
str e3
if(!ShowDialog("NotePadDlg2" &NotePadDlg2 &controls NotePadHwnd)) ret


;BEGIN DIALOG
;0 "" 0x90000A48 0x0 0 0 357 15 "ToolbarDlg"
;4 Button 0x54032000 0x0 260 0 48 14 "Button"
;5 Button 0x54032000 0x0 308 0 48 14 "Button"
;3 Edit 0x54030080 0x200 0 0 260 14 ""
;END DIALOG
;DIALOG EDITOR: "" 0x2030605 "" "" "" ""

ret
;messages
DT_AutoSizeControls hDlg message "3sh 4mh 5mh "
sel message
,case WM_INITDIALOG
,RECT- r r_prev
,SetTimer hDlg 1 10 0
,case WM_TIMER
,,int x y cx cy
,,ifi(NotePadHwnd)
,,,GetWindowRect NotePadHwnd &r            
,,,if(memcmp(&r &r_prev sizeof(RECT)))
,,,,;MoveWindow hDlg r.left+50 r.top+5 r.right-r.left-100 0 1
,,,,mov+ r.left+50 r.top+5 r.right-r.left-225 0 hDlg 0x200

,,,
,,,;GetWinXY(NotePadHwnd x y cx cy)
,,,;mov+ x+50 y+5 cx-225 0 hDlg 0x200
,,else
,,,clo hDlg
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1


The SetWinEventHook seems much quicker - no wobble compared to Timer Loop even with short period. I imagine it is less of drain on CPU usage.

I kind of cobbled the hook method from other posts. Is there a better way of doing this?

Stuart
#23
Quote:My question is why is this better than creating dlg? In QM environment you have dialog editor so can use that to layout "application" as dialog window. In your example, it seems like would have to be manual coding effort to do this.
CreateWindowEx is more lightweight (dialogs also use it, but wrap it in several layers of code), therefore would be better for simple floating windows like QM toolbars. But if you use many various controls, then better dialogs, because much easier.
Quote:Is there a better way of doing this?
I don't know better ways. Just need to optimize exe_window_trigger, now it looks slow. Does not check parameters, calls win.
#24
Thanks. That confirms my relief that my QM dialog building skills were still useful!
However, would it be possible to provide very simple example (e.g 1-2 buttons) using CreateWindowEx.

Also:
re hook method, you said:
Quote:need to optimize exe_window_trigger, now it looks slow. Does not check parameters, calls win.

Not sure I understand about calling win and which parameters to chec. Would it also be possible to provide basic example based on what I did or something else easier for you to demonstrate....nothing fancy necessary Big Grin

Thanks so much for all your help,

S
#25
Basic example.

Macro attach dialog to window
Code:
Copy      Help
type TB5016752 hdlg howner
ARRAY(TB5016752) a

int hhFore=SetWinEventHook(EVENT_SYSTEM_FOREGROUND EVENT_SYSTEM_FOREGROUND 0 &sub.HookProcFore 0 0 WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNTHREAD)
if(!hhFore) end F"{ERR_FAILED}. {_s.dllerror}"
int hhLoc=SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE EVENT_OBJECT_LOCATIONCHANGE 0 &sub.HookProcLoc 0 0 WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNTHREAD)
if(!hhLoc) end F"{ERR_FAILED}. {_s.dllerror}"
int idTimer=SetTimer(0 1 500 0)

MSG m
rep
,if(GetMessage(&m 0 0 0)<1) break
,sel m.message
,,case WM_TIMER
,,if(m.wParam=idTimer) sub.Timer1
,,continue
,,
,,case WM_APP
,,if IsWindow(m.wParam)
,,,int h=sub.Dialog(m.wParam)
,,,if h
,,,,TB5016752& r=a[]; r.howner=m.wParam; r.hdlg=h
,,,,sub.Attach(a.len-1)
,,continue
,
,TranslateMessage &m; DispatchMessage &m

UnhookWinEvent hhFore
UnhookWinEvent hhLoc
int i
for(i a.len-1 -1 -1) clo a[i].hdlg


#sub HookProcFore v
function hHook event hwnd idObject idChild dwEventThread dwmsEventTime

if(!hwnd or idObject or idChild) ret
str sc.getwinclass(hwnd); err ret
sel sc 1
,case "Notepad"
,int i
,for(i 0 a.len) if(hwnd=a[i].howner) ret
,PostMessage 0 WM_APP hwnd 0


#sub HookProcLoc v
function hHook event hwnd idObject idChild dwEventThread dwmsEventTime

;This code runs whenever a window
;or mouse pointer, caret, control, etc
;has locationchange.

;outw hwnd
if(!hwnd) ret ;;probably mouse
;out idObject
if(idObject!=OBJID_WINDOW) ret ;;eg caret
;out idChild
if(idChild) ret
int style=GetWinStyle(hwnd); if(style&WS_CHILD) ret

int i
for(i 0 a.len) if(hwnd=a[i].howner) sub.Attach(i); break


#sub Attach v
function i

;out "App Window has moved"
TB5016752& r=a[i]
int x y cx cy
GetWinXY(r.howner x y cx cy)
mov+ x+50 y+5 cx-225 0 r.hdlg 0x200


#sub Timer1 v
int i
for i 0 a.len
,if !IsWindow(a[i].howner)
,,clo a[i].hdlg; err


#sub Dialog v
function# hwndOwner

str dd=
;BEGIN DIALOG
;0 "" 0x90C80AC8 0x0 0 0 224 32 "Dialog"
;END DIALOG
;DIALOG EDITOR: "" 0x2040303 "*" "" "" ""

int h=ShowDialog(dd &sub.DlgProc 0 hwndOwner 1)
act hwndOwner; err
ret h


#sub DlgProc v
function# hDlg message wParam lParam

sel message
,case WM_INITDIALOG
,case WM_DESTROY
,int i
,for(i a.len-1 -1 -1) if(hDlg=a[i].hdlg) a.remove(i); break
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1
#26
Looks Fantastic!!!! Can't wait to get to my computer to give it a whirl.
Thank you so very much!
S


Forum Jump:


Users browsing this thread: 2 Guest(s)