News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

How to subclass correctly?

Started by Corso, June 11, 2015, 11:51:03 PM

Previous topic - Next topic

Corso

Hi again,

hhmmm so I don't have installed any extra language package etc.My normal used LP is German.So I did check again the problem with the manifest and its really weird.If I use the manifest then it dosen't work as I told before in my pre post and now I just checked the paramter of CreateWindowEx API for my Listview and found out that the problem only happens if I use LVS_REPORT dwStyle.If I remove it then its working again.What the heck...! :) So you getting almost crazy with all that problems you find out.

PS: I use XP SP3 too and in some targets I found / test I also had to remove the manifest file with any resources tool to get it run.

greetz

jj2007

This is pretty mysterious indeed. My best guess so far is that \Masm32\lib\comctl32.lib could be the culprit, as the problem seems to occur nowhere in the C/C++ world. As if the lib was built without a version 6 manifest ::)

There is one reference in a VB forum here, but it's not exactly the same problem.

Not tested: CreateActCtx is NOT equivalent to having a manifest file

Corso

Hi,

yes its very mysterious.Thanks for posting the links but it doesn't fix my problem.Anyway,so I have done some more checks and found again that problem seems to be connected with the SendMessage API (Using manifest + using SendMessage to send anything to SC procedere = sayonara & good night).Using same without manifest = your welcome again.Strange strange.Now I tried again to find any other API which I could use instead of SendMessage + SC and found three others which are working with SC & manifest...
;invoke SendMessage,LISTVIEW,uMsg,wParam,lParam
-------------
invoke PostMessage,LISTVIEW,uMsg,wParam,lParam
or
invoke SendMessageCallback,LISTVIEW,uMsg,wParam,lParam,0,0
or
invoke SendNotifyMessage,LISTVIEW,uMsg,wParam,lParam

...all three are working almost ok but I also need to return NM_RCLICK manually without to call CallWindowProc after.Maybe there are more other messages which I need to return later (not found yet during testing) etc.So maybe it doesn't play a big role which of the three APIs I do use now to send something into SC so I think there is no big difference to get it work now.The only problem what makes me unsure is the manifest issue and the possibly trouble to run my files later on other OS (Win7 or higher).Maybe I should add a info inside to remove the manifest if the file not starts on that systems etc also if this kind of solution is really bad. :(

greetz

jj2007

Interesting find. Indeed, your program works fine with manifest and one single PostMessage:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   .elseif uMsg == WM_NOTIFY   
              invoke PostMessage,LISTVIEW,uMsg,wParam,lParam
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      

Question is, why are you sending/posting this message? It is meant for hWnd, not for the control, and I doubt the control has any use for it.

So why not just do nothing here? Comment these two lines out, and it works. Note that even when commented out, the control and the main window receive notifications - first the control, then the main window. Typically, they look like this when right-clicking on a header column:
Noti sub        x:lParam                0018FC78
Noti main       x:lParam                0018E66C


I used the deb macro as follows:
    .if uMsg == WM_NOTIFY
   deb 4, "Noti sub", x:lParam

So you have all you need to track mouseclicks.

There are, btw, rare occasions where PostMessage is needed, in particular with RichEdit controls that are not yet fully initialised. But these are really rare. Normally, posting instead of sending is a no-no because the message pump depends on proper sequences, i.e. code normally must wait for the return from SM.

Corso

So as I told before already I was just looking for a way to send and get the original messages / wParam / lParam into my SC routine (what not happens normaly) thats all already.Now I just send them with the actually LV handle (I do change the LV variable each time with the actually visible LV) and then I got it in my SC "IF" then also was triggered as NM_CLICK in my LV and if not then not.

Yes PostMessage seems to be better if its not waiting till the message was handled as SendMessage does.Will see whether its an advantage later or not so I also think that some more other problem will occur later.I think I will try to code in stereo mode,one time with that method one time without just for testing to find possible more trouble and then I will decide which way I do use.

Thanks again so far and till later.

greetz

dedndave

a while back, Jochen was having another problem, where the code did not work correctly when using common controls v6

it just occured to me that it might be the window hierarchy
later versions have intermediate "worker" windows "above" the actual control window
you might want to look at the windows with WinSpy (free microsoft tool)
and see if the hierarchy changes with/without the manifest

Corso

Hi,

so if its using manifest then it will load comctl32.dll version 6.0.2600.6028 from the X86_Microsoft.Windows.Common-Controls.... folder.Thats the highest version I have.Without manifest its loading comctl32.dll version 5 from system32 folder (clear).All in all I don't see any reason why its working with PostMessage and not with SendMessage.I tried to check both files with Dependency Walker and there I get same results except that the one who will not run gets a stackoverflow...
LoadLibraryA("UxTheme.dll") called from "COMCTL32.DLL" at address 0x773A3FAF.
LoadLibraryA("UxTheme.dll") returned 0x5B0F0000.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "EnableThemeDialogTexture") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0FB45B.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "OpenThemeData") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F73B8.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "GetThemeTextExtent") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F2E63.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "IsThemeBackgroundPartiallyTransparent") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B10AEF2.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "DrawThemeParentBackground") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B10AF7D.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "DrawThemeBackground") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F2BEF.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "GetThemeBackgroundContentRect") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F3E8A.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "DrawThemeText") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F2FF8.
Second chance exception 0xC00000FD (Stack Overflow) occurred in "USER32.DLL" at address 0x7E368526.
Exited "123BONES.EXE" (process 0xB10) with code -1073741571 (0xC00000FD).

Here the one which is working...
LoadLibraryA("UxTheme.dll") called from "COMCTL32.DLL" at address 0x773A3FAF.
LoadLibraryA("UxTheme.dll") returned 0x5B0F0000.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "EnableThemeDialogTexture") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0FB45B.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "OpenThemeData") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F73B8.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "GetThemeTextExtent") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F2E63.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "IsThemeBackgroundPartiallyTransparent") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B10AEF2.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "DrawThemeParentBackground") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B10AF7D.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "DrawThemeBackground") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F2BEF.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "GetThemeBackgroundContentRect") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F3E8A.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "DrawThemeText") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F2FF8.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "GetThemeInt") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F459D.
GetProcAddress(0x7C910000 [NTDLL.DLL], "RtlDllShutdownInProgress") called from "MSCTF.DLL" at address 0x746DFA60 and returned 0x7C920501.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "HitTestThemeBackground") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0FB999.
GetProcAddress(0x5B0F0000 [UXTHEME.DLL], "CloseThemeData") called from "COMCTL32.DLL" at address 0x773A4010 and returned 0x5B0F4773.

No stackoverflow after DrawThemeText.

greetz

Corso

Hi again,

short info: So it seems that using a manifest + subclassing makes much strange trouble.I do use same code with & without manifest and see that the behavior of Listview acting different so for example my drag & drop function is no more working correctly (lines get selected & created randomly etc.) what not happens if I don't use the manifest then all is working fine again.Hhmm.So I think if I wanna keep using a manifest then I shouldn't no more try to send & handle any WM_NOTIFY etc in my SC routines (also if its working without manifest).

greetz

ragdog

Hi Corso

Your subclass has a little bug your can test it it works with Manifest controls.



.if uMsg == WM_INITDIALOG
invoke GetDlgItem,hWnd,1002
mov         hListview,eax
    invoke SetWindowLong,hListview,GWL_WNDPROC, offset ListviewSubclass
    mov         OldListview , eax

.elseif uMsg==WM_NOTIFY
invoke SendMessage,hListview,WM_NOTIFY,wParam,lParam




ListviewSubclass PROC hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

.if uMsg==WM_NOTIFY

push ebx
mov ebx,lParam
  mov eax, (NMHDR PTR [ebx]).hwndFrom
.if (eax==hListview)
mov eax, (NMHDR PTR [ebx]).code
.if eax == NM_CLICK
invoke MessageBox,hWnd,chr$ ("NM_CLICK"),0,0
.elseif eax == NM_DBLCLK
invoke MessageBox,hWnd,chr$ ("NM_DBLCLK"),0,0
.elseif eax == LVN_ITEMCHANGED
invoke MessageBox,hWnd,chr$ ("LVN_ITEMCHANGED"),0,0
.elseif eax==NM_RCLICK
invoke MessageBox,hWnd,chr$ ("NM_RCLICK"),0,0
.endif
.endif
pop ebx
.elseif uMsg == WM_CHAR
invoke MessageBox,hWnd,chr$ ("WM_CHAR"),0,0
.else
invoke CallWindowProc,OldListview ,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
ListviewSubclass ENDP


Greets,

Corso

Hi ragdog,

just check my first post I wrote on this topic there you can see the trouble I get with that code you did postet.Just see the pictures.You can move the LV lines but they keep on same position if you do exit the SC routine without CallWindowProc API.If you exit with CallWindowProc + using SendMessage API + manifest = dosen't work and you get stackoverflow exception but without manifest its working again.All in all there are a lot strange situations I found out this week what makes it almost impossible to think to be safe now with any of these methods (SC / API / manifest).The good thing is that all is working fine (so far) if I don't use a manifest but then the app optic is really bad and edgy.The only thing I can do now is to handle the WM_NOTIFY stuff again in my main routine also if I bump it full of code in the worst case and I can say "bye bye clean coding". :(

PS: If got any more ideas then tell us.

greetz

ragdog

Hi Corso

I have test it with  change column size is right what you say ,this problem is on WM_Notify
But it give a dirty trick make you own fake messages.

.const
WM_NOTIFY_ equ WM_APP+101   ; your own fake messages


.if uMsg == WM_INITDIALOG
invoke GetDlgItem,hWnd,1002
mov hListview,eax
    invoke SetWindowLong,hListview,GWL_WNDPROC, offset ListviewSubclass
    mov OldListview , eax

.elseif uMsg==WM_NOTIFY
invoke SendMessage,hListview,WM_NOTIFY_,wParam,lParam ; send notify to your own Notify messages



ListviewSubclass PROC hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

.if uMsg==WM_NOTIFY_  ; your own fake messages

push ebx
mov ebx,lParam
mov eax, (NMHDR PTR [ebx]).hwndFrom
.if (eax==hListview)
mov eax, (NMHDR PTR [ebx]).code
.if eax == NM_CLICK
invoke MessageBox,hWnd,chr$ ("NM_CLICK"),0,0
.elseif eax == NM_DBLCLK
invoke MessageBox,hWnd,chr$ ("NM_DBLCLK"),0,0
.elseif eax == LVN_ITEMCHANGED
invoke MessageBox,hWnd,chr$ ("LVN_ITEMCHANGED"),0,0
.elseif eax==NM_RCLICK
invoke MessageBox,hWnd,chr$ ("NM_RCLICK"),0,0
.endif
.endif
pop ebx
.elseif uMsg == WM_CHAR
invoke MessageBox,hWnd,chr$ ("WM_CHAR"),0,0
.else
invoke CallWindowProc,OldListview ,hWnd,uMsg,wParam,lParam
ret
.endif

xor eax,eax
ret
ListviewSubclass ENDP


Greets,

Corso

Hi ragdog,

hey coolio!Nice fake method you did postet so now everything is working + manifest & SM API hehe!  :biggrin: Just crazy that the solution is so simple but also very effective.Just great ragdog so you made my day.Thank you.

greetz

Corso

Hi guys,

so I need again some help and hope that you have some answers for me.The problem I got now is that I don't know exactly how to show original icons (unchanged) into a tray popup menu.First I tried to create popup menus in any controls (Listview / Tabs etc) I did subclass and used DRAWITEMSTRUCT and its also working fine so far catching WM_DRAWITEM & WM_MEASUREITEM in my subclass routines for the controls (so I need to subclass to get WM_DRAWITEM & WM_MEASUREITEM messages).Now I wanna also show icons on same way (or any other) in my tray popup menu but I don't have any control for that what I could subclass.The only thing what I can do is to show icons in my tray popup menu by SetMenuItemBitmaps API but I don't like to use bitmaps for icons so they look very bad.The question is how to get icons in my tray popup menu or how to subclass the tray without to have any control handle.You know what I mean right.Would be nice if you could maybe help me again with that problem.

PS: My tray is build similar as in the Iczelion tutorial 23.

Thank you

dedndave

one way to display an icon is to use a static control
for example, static controls are used by MessageBox to display text and/or icons

https://msdn.microsoft.com/en-us/library/windows/desktop/bb760769%28v=vs.85%29.aspx

Corso

Hi again,

hhmm good ok but I wanted to show the icons in my tray popup menu you know.But anyway so I found what I did wrong so just didn't use the right ownerflag in ModifyMenu API and also didn't create the popup menu directly at WM_SHELLNOTIFY but after changing that all is working now. :)

So now I got another problem with a subclassed edit control I have created what I wanna use as searchmask and which should also work in realtime.So if I enter anything then my app should read the entered data (letter/s) and search them in my LV and if it was found then it jumps to line in my LV etc you know what I mean right.The problem I got with that is that I can't catch the first entered letter right after it was entered.I used WM_CHAR to catch anything and then I use WM_GETTEXT to get text of my edit control but it always hangs one entered letter behind.Just if I enter the second letter then WM_GETTEXT gets the first entered letter and so on.Also if I add checks for entered letters I don't get it working for 100 % without also to check the selections in edit control (EM_GETSEL).So do you have any idea how to handle that problem or maybe you wrote a short code piece for that in the past which I could use or you have any example about that anywhere.Would be nice if anyone could help again.Thanks.

greetz