LCF-AT Posted November 21, 2016 Posted November 21, 2016 Hi guys, so today I wanna ask some questions about subclassing again.So I thought I would know how to subclass correctly but before a few days I got some problems and now I think I dont know how to subclass correctly.So I have following problem now. I just created a dialog window and in this window to create just a simple static control and this I wanna subclass.So I just used CreateWIndowEx API to create static and right after this I used SetWindowLong API with the handle I got before for the static... invoke CreateWindowEx,0,chr$("STATIC"),NULL,WS_CHILD or WS_VISIBLE ,20, 20,200, 100,hWnd, 0,hInstance, 0 mov hWndStatic,eax invoke SetWindowLong,hWndStatic,GWL_WNDPROC,offset StaticSubclassProc mov OllyWndProc,eax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; StaticSubclassProc PROC hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .if uMsg == WM_CTLCOLORSTATIC ....... ret .elseif uMsg == WM_CONTEXTMENU ....... .endif invoke CallWindowProc,OllyWndProc,hWnd,uMsg,wParam,lParam ret StaticSubclassProc endp .....but if I do it on that way then I dont get the uMsg I wanna check above and nothing happens.Static gets no colors and no context menu if I click right mouse on it.The question is why I dont get the messages in this routine. Now I tried the same again but this time I used the main routine handle on the SetWindowLong API.... invoke SetWindowLong,hWnd,GWL_WNDPROC,offset StaticSubclassProc ...and now it works....but also not so as I wanted.Problem in this case is that I only get the main handle send into this routine and not the handle of my static control.So my goal was it to subclass the single static control to get messages into this routine who just have also the handle of my static control only to color it and to get context menu on the static only and not on entire dialog window too you know. So what is wrong now in that case?Maybe you can help and tell me what I did wrong etc. Thank you
kao Posted November 21, 2016 Posted November 21, 2016 http://stackoverflow.com/questions/22255534/subclassing-static-control-to-receive-wm-ctlcolorstatic - In short: WM_CTLCOLORSTATIC is always sent to parent window. That's just how Windows work. 1 hour ago, LCF-AT said: Problem in this case is that I only get the main handle send into this routine and not the handle of my static control. Yes, you do get handle of static control, it's sent as lParam. See https://msdn.microsoft.com/en-us/library/windows/desktop/bb787524(v=vs.85).aspx 1
LCF-AT Posted November 21, 2016 Author Posted November 21, 2016 Hi kao, thanks for the info.Ok on that way I can check lparam for static handle to color it.But what about the other MSG WM_CONTEXTMENU?How to check there whether it has static handle or whether not if I wanna just show the conext menu on the static control itself and not anywhere else of main window.How to handle this now? So what I dont understand is that I before always did subclass other controls like tabs and listviews with my method to use SetWIndowLong with the handle I got after CreateWIndowEx and there is was also working also WM_CONTEXTMENU.So if something was triggerd in the subclass of them then it also always has the handle of only the tab or LV into hWnd variable at routine top proc.So why isnt this not working with others like static too?So I dont wanna get the main handle into my subclass routines only the handles of controls I have subclassed to handle all simple and easy without to check the handles etxra etc you know. Example: So what is if I wanna use other MSGs like WM_RBUTTONDOWN in my static subclass?If I use main handle to subclass static then right button down gets triggered but only with main handle and if I subclass it with static handle then I dont get WM_RBUTTONDOWN.So again its same like WM_CONTEXTMENU too and I cant check any handle there and context etc will shown on the entire window and not on static alone. So then subclassing makkes not much sense or?So I thought I do just subclassing to handle my xy control stuff seperated in my own routine without to handle & care anymore about handle checking if I subclass any controls with a specific routine.Hmmm.So do you have any clue what to do then? greetz
kao Posted November 21, 2016 Posted November 21, 2016 3 hours ago, LCF-AT said: But what about the other MSG WM_CONTEXTMENU? Use SS_NOTIFY flag when creating static control. It's not entirely obvious but kinda documented in MSDN. Attached is example code based on MASM examples. RCLKMENU_SUBCLASSED.zip 1
LCF-AT Posted November 22, 2016 Author Posted November 22, 2016 Hi kao, thanks for the example.Good ok now it works with SS_NOTIFY flag but now I dont get WM_CTLCOLORSTATIC anymore and maybe other MSGs too. So is there no list of what MSGs I do get or not in subclasses using control x till control y? greetz
huntingspace Posted November 22, 2016 Posted November 22, 2016 (edited) LCF-AT, here an example: how to create button as static control. It may be useful for you to understand subclassing. StaticSubclassExample.zip Edited November 22, 2016 by huntingspace 1
LCF-AT Posted November 22, 2016 Author Posted November 22, 2016 Hi huntingspace, thanks for your example code.So I see you do handle WM_CTLCOLORSTATIC from main proc to color the static but the question is why I dont get this message into the static subclass proc?So what is the sens to subclass anything and then to handle MSGs for the subclassed control into main proc?So then I dont need to subclass any control anymore and have to handle everything from main proc only you know. So I dont understand why windows not send all the messages into the subclass procs if they hold the handles of controls which was subclassed.Like WM_CTLCOLORSTATIC for example. DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .......... .elseif (uMsg==WM_CTLCOLORSTATIC) mov eax,lParam .if (eax==hStaticButton2) ;invoke SetTextColor,wParam,0 invoke SetBkColor,wParam,StaticColor invoke CreateSolidBrush,StaticColor ret .endif Above your code part of main routine.You do check for WM_CTLCOLORSTATIC and then you check the handle it holds in lParam and if match then color.So why does windows not check the handle to + sending them exactly this MSG into the subclass so that I then can handle it there?So in my eyes its just ridiculous.No idea so maybe I do think wrong or whatever but for me there is no logic why to subclass if I dont get the messages send to my subclass. Another example.So at the moment I try to create a Olly plugin and did also create a static control I did subclass and where I have same trouble.So if I do subclass the static with the static handle then I dont get all messages into the routine but if I subclass the Olly handle then I get also all messages into the subclass routine but then I only get the Olly main handle and no static handle what I could check etc.Thats just bad.There is no real clear solution how to handle this correctly or I dont know it etc. greetz
huntingspace Posted November 22, 2016 Posted November 22, 2016 According to MSDN reference WM_CTLCOLORSTATIC message is only handled by parent window when the control is about to be drawn. Whereas the subclassing (child) window can handle WM_PAINT message instead of WM_CTLCOLORSTATIC message. Therefore if you include WM_PAINT message in subclass procedure WM_CTLCOLORSTATIC message will not be sent to the parent handler anymore.
huntingspace Posted November 23, 2016 Posted November 23, 2016 An example: how to replace WM_CTLCOLORSTATIC message by WM_PAINT in subclass window. StaticSubclassExample2.zip 1
LCF-AT Posted November 23, 2016 Author Posted November 23, 2016 Hi and thanks again for the example huntingspace.All in all I am still not satisfied and to choose other methods to handle some stuff on other messages instead to do it on the default messages just because I dont get them in subclass. Also sooner or later I will get other trouble situations too like if I need to update new position which was set etc and I dont get the infos into my subclass then. So the question is what I should do.So it seems there is no mater way to handle this right or 100 % correctly I was looking for. Ok I have another small question about how to build routines correctly.So I did check diffrent source codes I found and find always other routine handlings about this... .if uMSG ... .elseif uMSG .... .elseif uMSG .... .else invoke CallWindowPro .. ret .endif xor eax,eax ret ------------------- ------------------- .if uMSG ... .elseif uMSG .... .elseif uMSG .... .endif invoke CallWindowPro .. ret ------------------- ------------------ .if uMSG ... .elseif uMSG .... .elseif uMSG .... .else mov eax,FALSE ret .endif mov eax, TRUE ret So what is now the correctly way?When I have to return True or false etc?Normaly I thought if a messages was catched then I do return true and if not then false and what about some MSGs which was catched like WM_CTLCOLORSTATIC so when I know that I have to return them only on MSG?Also in some Olly plugin sources I do find some code was just does return 0 or True.So I am not sure what of them I have to return directly 0/1 or not etc you know.Do you have some small helpfully infos about that? Thanks again.
huntingspace Posted November 24, 2016 Posted November 24, 2016 MSDN references contain more detailed information about system messages and you need to learn it to understand that it is necessary to return the system. For example, MSDN reference tells us information about the WM_INITDIALOG message: Quote Return value The dialog box procedure should return TRUE to direct the system to set the keyboard focus to the control specified by wParam. Otherwise, it should return FALSE to prevent the system from setting the default keyboard focus. That is to say this system message can return either TRUE or FALSE. It all depends on your task. For example, the WM_PAINT message always returns FALSE: Quote Return value An application returns zero if it processes this message. And, for example, the WM_CTLCOLORSTATIC message always returns handle to a brush that the system uses to paint the background of the control: Quote Return value If an application processes this message, the return value is a handle to a brush that the system uses to paint the background of the static control. And other messages like WM_CTLCOLOREDIT, WM_CTLCOLORLISTBOX, WM_CTLCOLORDLG, WM_CTLCOLORBTN that paint the user interface in main window handler also return handle to a brush. Another system messages that are not handled always return FALSE. 1
LCF-AT Posted November 24, 2016 Author Posted November 24, 2016 Hi again huntingspace, thanks again for the infos so far.So it seems I have to check all MSGs on MSDN to find out what to return.So do you have maybe any kind of template which is empty and only holds all important MSGs you need to handle extra?I made a short one so this should be now correctly right? .if uMsg == WM_INITDIALOG ;TRUE ret .elseif uMsg == WM_COMMAND ;FALSE ret mov eax,FALSE ret .elseif uMsg == WM_CLOSE ;FALSE ret mov eax,FALSE ret .elseif uMsg == WM_SIZE ;FALSE ret mov eax,FALSE ret .elseif uMsg == WM_NOTIFY ; Ret not important? .elseif uMsg == WM_ERASEBKGND ; True ret .elseif uMsg == WM_CTLCOLORSTATIC ; Eax brush Handle & ret ret .elseif uMsg == WM_CONTEXTMENU ; No ret to handle .elseif uMsg == WM_PAINT ; FALSE ret mov eax,FALSE ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .else mov eax,FALSE ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .endif mov eax,TRUE ret One thing about the subclass stuff and not getting all MSGs into them.So does it make sense to catch the MSGs from main proc and send them into the subclass proc manually via sendmessage API?Like this.... Main Proc .elseif uMsg == WM_CTLCOLORSTATIC mov edi, lParam .if edi == hWndCmd invoke SendMessage,edi,uMsg,wParam,lParam ret .else mov eax,FALSE .endif ret Subclass proc .elseif uMsg == WM_CTLCOLORSTATIC mov eax, hWndCmd .if lParam == eax invoke GetSysColor,COLOR_INFOBK invoke CreateSolidBrush,eax mov edi, eax invoke SetBkMode,wParam,TRANSPARENT mov eax, edi ret .endif xor eax,eax ret ...or is it a disadvantage?I mean so I could send all MSGs into subclass I dont get there but on the other hand I could also handle all in main proc.Normaly I would only have the basic code on my main proc and dont wanna write the entire codes into this proc to keep it small and clean and if I subclass then I can handle all codes seperated etc you know.So whats better now?Just wanna also try to prevent possible problems later I dont wanna have just because I do code on a wrong way so I wanna do it correctly anyhow. greetz
huntingspace Posted November 24, 2016 Posted November 24, 2016 Not bad, LCF-AT. You begin little by little to understand the system messages. I have recently been programming in FASM and use a such template: MainProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM mov edx,uMsg cmp edx,WM_INITDIALOG je wminitdialog cmp edx,WM_COMMAND je wmcommand cmp edx,WM_CLOSE je wmclose cmp edx,WM_CTLCOLORSTATIC je wmcolorstatic cmp edx,WM_SIZE je wmsize cmp edx,WM_NOTIFY je wmnotify cmp edx,WM_CONTEXTMENU je wmcontextmenu cmp edx,WM_PAINT je wmpaint jmp exit0 wminitdialog: ; some code jmp exit1 wmcommand: ; some code jmp exit0 wmclose: ; some code jmp exit0 wmcolorstatic: ; some code jmp finish ... wmpaint: ; some code exit0: xor eax,eax ret exit1: xor eax,eax inc eax finish: ret MainProc endp It seems to me this template is more comfortable and optimized. Certainly I don't know your task but I think you should do the static control without subclassing. It seems to me you are greatly complicate the issue by subclassing. In fact many messages can be processed in main proc and you need not resend messages into subclassing proc. 1
LCF-AT Posted November 24, 2016 Author Posted November 24, 2016 Hi again, thanks again for your answer + template.So since I dont use MultiASM plugin anymore in Olly where I need to use labels I always like to use use this if / else / endif syntax thing and dont use labels anymore (rarly) in WinASM. So there is not really kind of special task I wanna handle etc so I am just testing here & there and find mostly any kind of problem where I need to find any solution/s you know.Maybe your are right and subclassing isnt always good & needed so I will keep this now in my mind. greetz
LCF-AT Posted November 26, 2016 Author Posted November 26, 2016 Hi again, I have small new question.I wanna ask whether you know how to build any kind of custom tooltips which I can use for my systemtray icon.Normaly I do use only tray icon + the app titel in szTip of NOTIFYICONDATA struct but I would also like to show informations which gets also updated in realtime like the time for example etc.Also the szTip is limited.So do you have anything for that maybe?Below a picture what I mean... ....something like this. greetz
LCF-AT Posted November 26, 2016 Author Posted November 26, 2016 Hi raggy, ok try it again so I have deleted 45 PMs now. greetz
LCF-AT Posted November 26, 2016 Author Posted November 26, 2016 Hi, some more questions about creating a tooltip / Baloontip on tray icon. - How to get the infos if the mouse pointer does stops on my tray icon?So I thought I could create any small window to show directly over the icon what I also do update maybe each second via Timer but for this I need to find out when the mouse is on my tray icon. - So I tried the NOTIFYICONDATA again on MSDN and there I can read somethine about NIF_REALTIME flag but I am not sure whether its really possible to show a info with that what gets updated also in realtime if the info is still shown.So my tests did fail. Has anyone any idea which could help? greetz
LCF-AT Posted November 28, 2016 Author Posted November 28, 2016 Hi again, ok so now I found out how to check whether mouse cursor is on my tray icon / checking my set callback from NOTIFYICONDATA for WM_MOUSEMOVE in lparam.Ok this I got now so far.If I go on my tray icon then my created window gets shown so that good so far but now I have a next problem about how to find out whether the mouse pointer is away from my tray icon.I checked again MSDN and found something to use TrackMouseEvent API and set the dwFlag to TME_LEAVE whats sending the MSG WM_MOUSELEAVE where I could close or hide the created window again.Problem in this case is that it gets triggerd the whole time and my window is shown / hidden like rapid fire.My code look so about this so maybe you can see the problem... .elseif uMsg == WM_MOUSELEAVE invoke ShowWindow,htooltip,SW_HIDE .elseif uMsg == WM_SHELLNOTIFY ; callback MSG .if wParam == IDI_TRAY && lParam == WM_MOUSEMOVE mov TRACK.cbSize, sizeof TRACKMOUSEEVENT mov TRACK.dwFlags,TME_LEAVE mov eax,hWnd ; main proc handle mov TRACK.hwndTrack,eax invoke TrackMouseEvent,addr TRACK invoke ShowWindow,htooltip,SW_SHOW ....so now that the problem about this.Now I tried to find any other solution like checking the mousecursor whether its on tray icon & outside of tray icon etc but I also dont get it working so far.Has anyone any idea how to handle that? greetz
Teddy Rogers Posted November 29, 2016 Posted November 29, 2016 Have not read the whole topic so not entirely sure what you are trying to do. If you are only intent on checking for mouse cursor movement over the tray icon wait for WM_MOUSEMOVE in lParam of your window callback procedure. If it's not active you know you don't need to have your customised tray icon tooltip from appearing anymore. I have no idea why you are checking WM_SHELLNOTIFY? Ted.
LCF-AT Posted November 29, 2016 Author Posted November 29, 2016 Hi Ted, so I do already check for WM_MOUSEMOVE in lparam at my callback WM_SHELLNOTIFY / so I could also set any other etc.If I got this then I can send / show a window over my icon (GetCursorPos + movewindow API).The problem now is how to find out whethe rmouse is no more on my icon you know.If I go away from my icon then no MSG xy will send which I could check.Only thing what I can do so far is to set a timer what does show my window for 3 seconds or so + hiding / destroy my window again.Do you have any better idea maybe I could try? PS: So you know Win7 right,so there you get also a small window to see of any stuff you have into the taskbar like notepad file etc so something like this I wanna have too just over my tray icon with actually & updated (in realtime )app infos.Yesterday I also played a little to create a window to show it but its just transparent and only see the borders (I used tooltip class for CreateWInodwEx API) and also if I set colors with TTM_SETTIPBKCOLOR isnt working anyhow.So I have to test a lot more to get this thing showing / working like I imagine. PS: Do you have maybe some example code for PureBasic which I could check a little etc? greetz
huntingspace Posted November 29, 2016 Posted November 29, 2016 Hi, LCF-AT There is a good sample with system tray notifications but it is written in delphi. Perhaps it will be useful for you. CoolTrayIcon.zip
Teddy Rogers Posted November 29, 2016 Posted November 29, 2016 (edited) In PureBasic it goes something like this... Declare MenuCallback(hWnd, uMsg, wParam, lParam) If OpenWindow(0, #Null, #Null, #Null, #Null, "", #PB_Window_Invisible) AddSysTrayIcon(0, WindowID(0), LoadImage_(#Null, #OIC_BANG, #IMAGE_ICON, #Null, #Null, #LR_SHARED)) SysTrayIconToolTip(0, "I am a tooltip!") SetWindowCallback(@MenuCallback()) Repeat Event = WaitWindowEvent() Until Event = #PB_Event_CloseWindow EndIf Procedure MenuCallback(hWnd, uMsg, wParam, lParam) Select uMsg Case #WM_USER + 11477 Select lParam Case #WM_MOUSEMOVE LPTRACKMOUSEEVENT.TRACKMOUSEEVENT LPTRACKMOUSEEVENT\cbSize = SizeOf(LPTRACKMOUSEEVENT) LPTRACKMOUSEEVENT\dwFlags = #TME_LEAVE LPTRACKMOUSEEVENT\hwndTrack = hWnd LPTRACKMOUSEEVENT\dwHoverTime = #HOVER_DEFAULT TrackMouseEvent_(@LPTRACKMOUSEEVENT) Case #WM_RBUTTONUP Debug "#WM_RBUTTONUP" End EndSelect Case #WM_MOUSELEAVE Debug "#WM_MOUSELEAVE" EndSelect ProcedureReturn #PB_ProcessPureBasicEvents EndProcedure Ted. Edited November 29, 2016 by Teddy Rogers 1
LCF-AT Posted November 29, 2016 Author Posted November 29, 2016 Hi Ted, thanks for the code but I dont get it again.So I did this before too to catch WM_MOUSEMOVE in lparam and there I set TrackMouseEvent but right there it will also send a MSG to WM_MOUSELEAVE where I hide the window again.I made a short example code & file so maybe you can see whats wrong inside.Just a tray Icon and if you go with mouse on it then it does show / hide rapidly.So it dosent just send a MSG to WM_MOUSELEAVE if I leave the icon so also if I am on it so thats the problem. Tray Tooltip.rar greetz
huntingspace Posted November 30, 2016 Posted November 30, 2016 Some sample in MASM about SysTray Icon. SysTray.rar 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now