The MASM Forum

General => The Campus => Topic started by: Corso on June 11, 2015, 11:51:03 PM

Title: How to subclass correctly?
Post by: Corso on June 11, 2015, 11:51:03 PM
Hello together,

just wanna ask some little questions and hope to get some help.So the main problems I got if I subclass any control is how to get the messages & right NMHDR datas also into my subclass procederes as I also get in my first main procedere.I did some tests and found that I don't get same messages & NMHDR datas in my subclasses and tried then to send the same message & parameters via SendMessage API into my subclasses what also works (not sure whether this way is correctly or not) but I get also some trouble with the control so its no more updated correctly (Listview for example).

So I have created just a dialog with a Listview & Tabcontrol which I both have subclassed.Below some code excerpts.
;;; First Main Routine
.if uMsg == WM_INITDIALOG
....
invoke SetWindowLong,LISTVIEW,GWL_WNDPROC, addr LISTVIEWPROC
mov OLDLISTVIEWPROC, eax

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

.endif
xor eax,eax
ret

;;; Listview Subclass routine
.elseif uMsg == WM_NOTIFY
        mov ebx,lParam
        mov eax, (NM_LISTVIEW ptr [ebx]).hdr.code
        .if eax == NM_DBLCLK
            mov EDIT, 1h ; edit entry
            invoke SendMessage,hWnd, LVM_GETNEXTITEM, -1, LVNI_SELECTED or LVNI_FOCUSED
            .if eax!=-1
                invoke DialogBoxParam,hInstance,1004,hWnd,addr AddDlgProc,TRUE
            .endif
        .endif
...................
.else   
    invoke CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
    ret
.endif   
    xor eax,eax
    Ret

As I said its working so far but something is going wrong with my Listview so just have a look on my pictures below...so this picture I made if I use the code above in my subclass for the Listview..
(http://i62.tinypic.com/macup0.png)
...now on this picture you can see that it works correctly without subclassing and if I handle all just in my main procedere.
(http://i60.tinypic.com/s10scy.png)
So what could be the problem in my case and how can do it correctly without to get later such problems?Subclassing is new for me so before I did never done this but it seems to be a good idea to catch the WM messages into the subclass routines which also got triggered by them itself.Maybe you can help and show me how to work correctly with subclasses.

The next little question I have turns around tabcontrols and I wanna know whether there is any basic way to create a tabcontrol drag & drop code.So I know how to build a drag & drop code for a Listview for example but for a tabcontrol I can't find any drag commands as LVN_BEGINDRAG for Listview and a similar CREATEDRAGIMAGE command for a Tabcontrol is also not to find.On MSDN I found that I could use the Extended Style TCS_EX_REGISTERDROP but there I found no code example how to do it so maybe you can also help me with that issue.

PS: One infos to my code above.So normaly I don't use a top procedere with GetMessage / TranslateMessage & DispatchMessage loop.Just a info,so I do start only with a DialogBoxParam call same as you can see in the \Dialog\bones tempalte.

Thank you and greetz
Title: Re: How to subclass correctly?
Post by: dedndave on June 12, 2015, 01:13:24 AM
first, EBX (and ESI, EDI, EBP) should be preserved across callback functions
use EDX, instead (or PUSH and POP EBX)
        mov edx,lParam
        mov eax, (NM_LISTVIEW ptr [edx]).hdr.code


second, you probably want the original callback to handle ALL messages
at least, WM_NOTIFY - it's not getting any WM_NOTIFY messages the way you have it
    .if uMsg == WM_NOTIFY
        ;do stuff
    .endif
    invoke CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
    ret

a simplified example, but you get the idea
Title: Re: How to subclass correctly?
Post by: Corso on June 12, 2015, 03:34:18 AM
Hello dedndave,

thank you for your answer so far but I still don't get it.So I get normaly WM_NOTIFY also in my subclass routine but I can't check for NM_DBLCLK and thats the reason why I tried to send it manually what also works but then I get the trouble you can see on my pictures above so something I'am doing still wrong.I made again a short version of my code which I post below so that you can see the entire stuff.Would be nice if you could just check the code and then tell me what I have to change to get it working correctly.Thank you.
.586
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include     \masm32\include\All.inc

DlgProc   PROTO :DWORD,:DWORD,:DWORD,:DWORD
LISTVIEWPROC  PROTO :DWORD,:DWORD,:DWORD,:DWORD

.const
IDD_MAIN equ 1000
IDB_EXIT equ 1001

.data
Header1 db "No.",0h
Header2 db "Name",0h
Header3 db "Link",0h

.data?
hInstance       dd ?
hWnd_Main         dd ?
LISTVIEW          dd ?
OLDTABPROC        dd ?
OLDLISTVIEWPROC   dd ?

lvc LV_COLUMN <>
TabCtrlItem TC_ITEM <>

.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke InitCommonControls
invoke DialogBoxParam, hInstance, IDD_MAIN, 0, addr DlgProc, TRUE
invoke ExitProcess, eax

DlgProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,200
invoke SendMessage, hWnd, WM_SETICON, 1, eax
push hWnd
pop  hWnd_Main
invoke CreateWindowEx,WS_EX_CLIENTEDGE,chr$("SysListView32"),NULL,WS_CHILD or LVS_REPORT or WS_VISIBLE or  WS_TABSTOP or LVS_SHOWSELALWAYS \
                                               ,10,10,550,450,hWnd_Main,0,hInstance,NULL

mov LISTVIEW, eax
    invoke SetWindowLong,LISTVIEW,GWL_WNDPROC, addr LISTVIEWPROC    
    mov OLDLISTVIEWPROC, eax
   
mov lvc.imask,LVCF_TEXT+LVCF_WIDTH
mov lvc.pszText,offset Header1
mov lvc.lx,50
invoke SendMessage,LISTVIEW, LVM_INSERTCOLUMN,0,addr lvc
or lvc.imask,LVCF_FMT
mov lvc.fmt,LVCFMT_LEFT
mov lvc.pszText,offset Header2
mov lvc.lx,300
invoke SendMessage,LISTVIEW, LVM_INSERTCOLUMN, 1 ,addr lvc
or lvc.imask,LVCF_FMT
mov lvc.fmt,LVCFMT_LEFT
mov lvc.pszText,offset Header3
mov lvc.lx,150
invoke SendMessage,LISTVIEW, LVM_INSERTCOLUMN, 2 ,addr lvc      
mov eax, LVS_EX_FULLROWSELECT or LVS_EX_HEADERDRAGDROP or LVS_EX_GRIDLINES
invoke SendMessage, LISTVIEW, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, eax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.elseif uMsg == WM_COMMAND
.if wParam == IDB_EXIT
invoke SendMessage, hWnd, WM_CLOSE, 0, 0
.endif
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd, 0
.endif

xor eax,eax
ret
DlgProc endp

LISTVIEWPROC proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM


    .if uMsg == WM_NOTIFY
        mov edx,lParam
        mov eax, (NM_LISTVIEW ptr [edx]).hdr.code
          .if eax == NM_DBLCLK
            nop
          .endif 
    .else
    invoke CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
    ret
   .endif   
    xor eax,eax
Ret
LISTVIEWPROC endp

end start

greetz
Title: Re: How to subclass correctly?
Post by: fearless on June 12, 2015, 08:53:19 AM
A list view control notifies its parent window of events by sending a WM_NOTIFY message. If you sublclass a listview you will still need to handle the WM_NOTIFY in the parent. MFC has a concept of forwarding using WM_REFLECT_NOTIFY which is sort of what your doing in the parent dialog with the sendmessage, but it would forward on all WM_NOTIFY messages to the listview including ones for other controls, which isnt what you want to be doing im guessing.

So you probably need to handle this in the parent.

Its possible to use SetWindowSubclass, subclassing the listviews parent and only processing the WM_NOTIFY for your listview there

Havnt tried it, but this might work, but id probably opt with just handling everything in the parent, much simplier and avoids any other complications.


ListviewNotify PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD ; prototype for our sublcassed parent window to handle only listview notifications

Invoke SetWindowSubclass, hWin, ListviewNotify, 1, hListview ; where do we call this, probably after listview creation in the dialogs WM_INITDIALOG perhaps?


ListviewNotify PROC USES ECX hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD,uIdSubclass:DWORD,dwRefData:DWORD

    mov eax, uMsg
    .IF eax == WM_NCDESTROY
        Invoke RemoveWindowSubclass, hWin, ListviewNotify, uIdSubclass
   
    .ELSEIF eax == WM_NOTIFY
        mov ecx, lParam
        mov eax, [ecx].NMHDR.hwndFrom
        .IF eax == dwRefData ; dwRefData contains the handle to our listview so only do the following if its our listview thats notifies us.
            mov eax, [ecx].NMHDR.code
           
            .IF eax == NM_CLICK
                ; do stuff
            .ELSEIF eax == NM_DBLCLK
                ; do stuff
            .ELSEIF eax == NM_LVN_KEYDOWN
                ; do stuff
            .ELSEIF eax == LVN_ITEMCHANGED
                ; do stuff
            .ENDIF
             
        .ENDIF
    .ENDIF
    Invoke DefSubclassProc, hWin, uMsg, wParam, lParam ; default processing for the parent of the listview, ie our main dialog or main window
   
    ret
ListviewNotify ENDP


So probably just handle it all in the parent like so:

    .ELSEIF eax == WM_NOTIFY
        mov ecx, lParam
        mov eax, [ecx].NMHDR.hwndFrom
        .IF eax == hListview
            mov eax, [ecx].NMHDR.code
            .IF eax == NM_CLICK
           
            .ELSEIF eax == NM_DBLCLK
           
            .ELSEIF eax == NM_LVN_KEYDOWN
           
            .ELSEIF eax == LVN_ITEMCHANGED
           
            .ENDIF           
           
        .ELSEIF eax == hTabcontrol
            mov eax, [ecx].NMHDR.code
            .IF eax == ??? ; insert our tab notifications
           
            .ENDIF
        .ENDIF


maybe add in debug messages like the vKim like debug tools from donkey or a simple messagebox calls in each NM_ to check each is working, for testing purposes.
Title: Re: How to subclass correctly?
Post by: Corso on June 12, 2015, 01:58:40 PM
Hello fearless,

thanks for your answer.So my main goal was it not to handle anything in my main routine anymore to keep it clean and I thought if I do subclass some controls then the problem would be fixed but it seems that the subclass stuff has some special rules I need to find out and follow.So now I tried your idea to use the SetWindowSubclass API with my Listviews and it does work on a first test but I also see again some problems.Problem one is that I need to check in your method for the NMHDR.hwndFrom what I normaly don't need to check if I subclass via SetWindowLong API and NM_CLICK get triggered only if I click in my Listview.With your method I got now the problem that NM_CLICK etc of my tabcontrol gets also triggered in my Listview procedere where I then also again need to check for the hwndFrom as in your example and thats a bad situation if I wanna handle each subclassed controls in their own procedres.Problem two is that with your method I also need to log all handles & uIdSubclass IDs of each created Listview what makes again much work.Just imagine like a browser where you can create tons of tabs and now imagine for each tab will created and shown a own Listview I need to handle in that case and a another problem I see with your method is that I don't get messages as WM_CHAR & WM_KEYDOWN (NM_KEYDOWN & NM_CHAR dosen't work with your example and I don't have a NM_LVN_KEYDOWN message in my windows.inc) in my subclass routine.All in all its really not simple.So what should I do now?

PS: One other question about this board.So of course I am new (Hello again to all) but does the captcha & the seven same questions verification disappear someday after some posts or have I to fill it every time if I do post anything?

greetz
Title: Re: How to subclass correctly?
Post by: jj2007 on June 12, 2015, 09:41:02 PM
I'd suggest you post your complete code, and explain what exactly you don't like...

Another option is to replace your includes with include masmbasic.inc, and install a message monitor with the deb (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1019) macro, either below the main WndProc or under the subclass:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
...
WndProc proc uses esi edi ebx hWnd, uMsg, wParam:WPARAM, lParam:LPARAM
      inc msgCount      ; v v v ignore specific messages
      NoDebMsg CATSTR NoDebMsg, <, WM_ENTERIDLE>
      deb 4, "msg", chg:msgCount


Typical output:
msg     chg:msgCount    1       uMsg = Start monitoring
msg     chg:msgCount    2       uMsg = WM_GETMINMAXINFO
msg     chg:msgCount    3       uMsg = WM_NCCREATE
msg     chg:msgCount    4       uMsg = WM_NCCALCSIZE
msg     chg:msgCount    5       uMsg = WM_CREATE
msg     chg:msgCount    6       uMsg = WM_WINDOWPOSCHANGING
msg     chg:msgCount    7       uMsg = WM_NCCALCSIZE
msg     chg:msgCount    8       uMsg = WM_WINDOWPOSCHANGED
msg     chg:msgCount    9       uMsg = WM_MOVE
msg     chg:msgCount    10      uMsg = WM_SIZE
msg     chg:msgCount    11      uMsg = WM_PARENTNOTIFY
msg     chg:msgCount    12      uMsg = WM_WINDOWPOSCHANGING
msg     chg:msgCount    13      uMsg = WM_ACTIVATEAPP
msg     chg:msgCount    14      uMsg = WM_NCACTIVATE
msg     chg:msgCount    15      uMsg = WM_ACTIVATE
msg     chg:msgCount    16      uMsg = WM_IME_SETCONTEXT
msg     chg:msgCount    17      uMsg = WM_IME_NOTIFY
msg     chg:msgCount    18      uMsg = WM_SETFOCUS
msg     chg:msgCount    19      uMsg = WM_KILLFOCUS
msg     chg:msgCount    20      uMsg = WM_IME_SETCONTEXT
msg     chg:msgCount    21      uMsg = WM_COMMAND
msg     chg:msgCount    22      uMsg = WM_SHOWWINDOW
msg     chg:msgCount    23      uMsg = WM_WINDOWPOSCHANGING
msg     chg:msgCount    24      uMsg = WM_NCPAINT
msg     chg:msgCount    25      uMsg = WM_GETTEXT
msg     chg:msgCount    26      uMsg = WM_ERASEBKGND
msg     chg:msgCount    27      uMsg = WM_WINDOWPOSCHANGED
msg     chg:msgCount    28      uMsg = WM_SIZE
msg     chg:msgCount    32      uMsg = WM_MOVE
msg     chg:msgCount    33      uMsg = WM_PAINT
msg     chg:msgCount    34      uMsg = WM_CTLCOLOREDIT
msg     chg:msgCount    38      uMsg = WM_CTLCOLOREDIT
msg     chg:msgCount    51      uMsg = WM_USER
msg     chg:msgCount    52      uMsg = WM_NCACTIVATE
msg     chg:msgCount    53      uMsg = WM_GETTEXT
msg     chg:msgCount    54      uMsg = WM_ACTIVATE
msg     chg:msgCount    55      uMsg = WM_ACTIVATEAPP


If you need more info:
deb 4, "msg", x:wParam, x:lParam, chg:msgCount
The x: forces hex output, useful if wParam or lParam have info in hi and lowords.
Title: Re: How to subclass correctly?
Post by: rrr314159 on June 13, 2015, 12:16:36 AM
Hi Corso,

the verification questions disappear soon.

Good idea to post complete code, that actually works, use a zip if convenient

Don't have time to look into this a whole lot at the moment, am hoping someone else here knows all about it already. But I can give some advice,

Quote from: CorsoSo my main goal was it not to handle anything in my main routine anymore to keep it clean

- When dealing with Windows routines like this my main goal is just to get it to work, make it nice and clean later - if possible

Quote from: CorsoProblem two is that with your method I also need to log all handles & uIdSubclass IDs of each created Listview what makes again much work

- often find myself doing this sort of thing, keeping list of all handles, and running thru it in the main routine ... seems messy but not that bad, once it's done it's done, and it works. I don't trust subclassing, or anything fancy with Windows, personally. Do it the simple obvious way, turns out easier in long run.

- But then I don't trust OOP in general, so my advice might not be worth much
Title: Re: How to subclass correctly?
Post by: Corso on June 13, 2015, 02:07:00 AM
Hi again guys,

and thank you again for your answers so far so I tried already since weeks to get any help with that problem I got without success but its nice to see to get any answers on this source so it seems to be a good idea to register on this board. :)

Ok so back to my problem.So as I told before I wanna try to subclass some of my dynamic classes to make the work also a lot easier for me so before I wrote anything almost at once and got a messed up source and wrote much stuff more or less in a freestyle way and I also thought the main thing is to get all working anyhow and anyway how it looks. :) But now I am at the point where I wanna write everthing correctly if possible and to prevent possible trouble by exceptions etc you know.

So lets talk again about the subclassing issues via SetWindowLong API.So I wanna create / edit / remove dynamic listviews which can be only one or endless depending on the tabs and of course I don't really need to subclass the tabcontrol too at the moment but maybe later.So the first I got if I NOT subclass the LVs then I will also not get all messages in my main routine as WM_CHAR / WM_KEYDOWN which are a must have for my LVs later.Now I can catch these messages in my SC for all actually shown LVs and also without to check the handles what is very good so far.The only problem in that case is that I can't catch other messages & NMHDR in this SC which also do belong in this SC as the WM_NOTIFY / NM_CLICK for example what is really very bad.Also if I try to send the same main routine paramters in my SC routine then it works but I got them such other problems as you can see on my postet pictures above.So to subclass via SetWindowLong API is more like a 50 of 100 success and is limited.Almost the same results in the other direction I get with the method by fearless so with that I can't get WM_CHAR / WM_KEYDOWN and also need to handle the handles extra.

The only thing what I can do is to work almost on the same way as I did before already. :( I need to SC to get WM_CHAR / WM_KEYDOWN etc + must handle NM_CLICK from my main routine.Hhmmm!

@ jj2007

Thanks for the info but I debugged it and I don't get the messages I want.I postet above already a short simple code snippet you can use (just a single LV in a dialog) where you get the same problem as you can see on my postet pics above.

@ rrr314159

Nice to hear that the captcha will disappear soon so this is really wiry to fill it each time. :) So I really have to say that cleaning a source after it was written is not easy anymore so I got already lost to keep a overview in thousands of written lines and using many extra labels and my intention was it now to write on a clean way directly from the beginning more or less.

greetz
Title: Re: How to subclass correctly?
Post by: fearless on June 13, 2015, 02:59:36 AM
1 possible solution to this is to create your own window (a container control) that hosts the listview (and possibly the tab control if required). Handle all the code in this. Internally you can hold onto the handles for the listview and/or tab control. Externally you just create this new window and let it do its thing.

for example when you create a window with CreateWindowEx you can use the WNDCLASSEX.cbWndExtra as storage for handles etc. I use a couple of macros that are just GetWindowLong, SetWindowLong calls which read/write to this area of memory at whichever offset is required for what i have stored there. If you declare say 8 bytes in this area, you can store to handles and reference them like so

@hListView EQU 0
@hTab EQU 4

_GetHandleListview MACRO hControl:REQ
    Invoke GetWindowLong, hControl, @hListView       
ENDM

_SetHandleListview MACRO hControl:REQ, ptrControlData:REQ
    Invoke SetWindowLong, hControl, @hListView, ptrControlData
ENDM

_GetHandleTab MACRO hControl:REQ
    Invoke GetWindowLong, hControl, @hTab       
ENDM

_SetHandleTab MACRO hControl:REQ, ptrControlData:REQ
    Invoke SetWindowLong, hControl, @hTab, ptrControlData
ENDM


somewhere in code when you need to get the handle for the listview you can use the macro:

_GetListviewHandle hWin
mov hLV, eax


Prob best if i upload an example to give you idea. Ive a propertygrid control, which is work in progress that is comprised of a number of windows or controls:

The first main window is the PropertyGrid class control, this is the container for all other controls, then i create another window which is the scollpane, which allows me to handle moving the windows inside up/down as the scrollbar is moved/clicked.
I then create the section label part, as another window which is a child of the Scrollpane window, along with a section header button.
Then i create the section grid (a listview control) which is also a child of the main Scrollpane window
and then there is a scrollbar which shows up when required and hides when isnt.
The code is a bit messy, comments are all over the place, i use subclassing for some stuff where it might be easier for me to segment the whole project into rough areas relating to each control - however the wm_notify stuff for the listview is handled by its parent - which in this case is the scrollpane window.

Have a look through it and the test program to see how it 'works' - a lot of stuff isnt quite finished, or documented, but it might give you some ideas on how to go about creating your own container window/control for your other controls

The attachment contains the main propertygrid control which is compiled as a lib and this (propertygrid.lib) with the propertygrid.inc are used in the PGTest program (i use radasm for the projects)

Took a lot of ideas and inspiration for this from a codeproject example and a similar control on the pellesc forum.
Title: Re: How to subclass correctly?
Post by: jj2007 on June 13, 2015, 03:35:18 AM
Quote from: Corso on June 13, 2015, 02:07:00 AMThanks for the info but I debugged it and I don't get the messages I want.

I use Olly a lot, but debugging inside a WndProc is almost impossible (and I have tried...). The deb macro (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1019) is much more helpful in such situations. It preserves all registers and the flags, and a simple usedeb=0 on top of the code switches off any code generation.
Title: Re: How to subclass correctly?
Post by: dedndave on June 13, 2015, 10:03:41 AM
it doesn't necessarily require a "middle" window class

you just have to understand what's happening with WM_NOTIFY messages
and - the construction of your if/then/else/endif code

if you do this...
    .if uMsg==WM_NOTIFY
        ;some code
    .else
        INVOKE  CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
        ret
    .endif   
    xor     eax,eax
    ret

all messages except WM_NOTIFY are passed to the original WndProc for the system defined list view class
all WM_NOTIFY messages return without the original list view code being able to process the message
that's why it doesn't move the divider   :P

you merely have to re-think your code design
allow most, if not all, WM_NOTIFY messages to pass on to the list view class WndProc   :t
Title: Re: How to subclass correctly?
Post by: Corso on June 14, 2015, 02:39:25 AM
Hi again guys,

thank you for your codes fearless but this is more too complex for me just to handle the messages I want.

So I tried it today again and you do remember I always did used SendMessage API to send the same datas from main routine in my subclass routine and also if I do exit WM_NOTIFY from my subclass with same CallWindowProc call it does crash by stackoverflow.Today I tried the same but this time I used the PostMessage API instead of SendMessage API and wonder oh wonder now it works!?! :) Not really sure why or whether I can really use this method without to get any troubel later but it works.Maybe one of you guys could check this again.

;;; main routine
.elseif uMsg == WM_NOTIFY
        ;invoke SendMessage,LISTVIEW,uMsg,wParam,lParam
        invoke PostMessage,LISTVIEW,uMsg,wParam,lParam



LISTVIEWPROC proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    .if uMsg == WM_NOTIFY
        mov edx,lParam
        mov eax, (NM_LISTVIEW ptr [edx]).hdr.code
          .if eax == NM_DBLCLK
            nop
          .endif           
   .elseif uMsg == WM_CHAR
           nop             

    .else
out1:     
    invoke CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
    ret 
   .endif   
    cmp uMsg,WM_NOTIFY   ; <-- adding check
    je out1          ; <-- jump CallWindowProc if WM_NOTIFY
    xor eax,eax
    Ret
LISTVIEWPROC endp

end start

As I said I am not sure whether I can trust this method now also if it looks a bit strange but moving the divider is working now and it dosen't crash too.Hhhmm so what do you think?So on the other hand if I really can use this method then all is fine now and I can catch both messages WM_CHAR & NM_DBLCLK in same routine where it also does belong to my LVs if one of these messages get triggered.Nice. :)

greetz
Title: Re: How to subclass correctly?
Post by: dedndave on June 14, 2015, 11:55:20 PM
quite often, if you send a message to a window, in the WndProc for that same window, it's best to use PostMessage
usually, using SendMessage will cause it to freeze   :P
that's because WndProc is single-threaded - and it's waiting for the return of SendMessage that isn't going to happen
Title: Re: How to subclass correctly?
Post by: Corso on June 23, 2015, 04:59:18 AM
Hi again guys,

sorry for waiting.So I did test the subclass isuues again and again and found some other strange problems which I don't understand.One strange problem I found out is if I use a manifest in my resources then I get trouble...below again my little short example code..
.586
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include     \masm32\include\All.inc

DlgProc   PROTO :DWORD,:DWORD,:DWORD,:DWORD
LISTVIEWPROC  PROTO :DWORD,:DWORD,:DWORD,:DWORD

.const
IDD_MAIN equ 1000
IDB_EXIT equ 1001

.data
Header1 db "No.",0h
Header2 db "Name",0h
Header3 db "Link",0h

.data?
hInstance       dd ?
hWnd_Main         dd ?
LISTVIEW          dd ?
OLDTABPROC        dd ?
OLDLISTVIEWPROC   dd ?

lvc LV_COLUMN <>
TabCtrlItem TC_ITEM <>

.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke InitCommonControls
invoke DialogBoxParam, hInstance, IDD_MAIN, 0, addr DlgProc, TRUE
invoke ExitProcess, eax

DlgProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,200
invoke SendMessage, hWnd, WM_SETICON, 1, eax
push hWnd
pop  hWnd_Main
invoke CreateWindowEx,WS_EX_CLIENTEDGE,chr$("SysListView32"),NULL,WS_CHILD or LVS_REPORT or WS_VISIBLE or  WS_TABSTOP or LVS_SHOWSELALWAYS \
                                               ,10,10,550,450,hWnd_Main,0,hInstance,NULL

mov LISTVIEW, eax
    invoke SetWindowLong,LISTVIEW,GWL_WNDPROC, addr LISTVIEWPROC    
    mov OLDLISTVIEWPROC, eax
   
mov lvc.imask,LVCF_TEXT+LVCF_WIDTH
mov lvc.pszText,offset Header1
mov lvc.lx,50
invoke SendMessage,LISTVIEW, LVM_INSERTCOLUMN,0,addr lvc
or lvc.imask,LVCF_FMT
mov lvc.fmt,LVCFMT_LEFT
mov lvc.pszText,offset Header2
mov lvc.lx,300
invoke SendMessage,LISTVIEW, LVM_INSERTCOLUMN, 1 ,addr lvc
or lvc.imask,LVCF_FMT
mov lvc.fmt,LVCFMT_LEFT
mov lvc.pszText,offset Header3
mov lvc.lx,150
invoke SendMessage,LISTVIEW, LVM_INSERTCOLUMN, 2 ,addr lvc      
mov eax, LVS_EX_FULLROWSELECT or LVS_EX_HEADERDRAGDROP or LVS_EX_GRIDLINES
invoke SendMessage, LISTVIEW, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, eax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.elseif uMsg == WM_NOTIFY
        invoke SendMessage,LISTVIEW,uMsg,wParam,lParam
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.elseif uMsg == WM_COMMAND
.if wParam == IDB_EXIT
invoke SendMessage, hWnd, WM_CLOSE, 0, 0
.endif
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd, 0
.endif

xor eax,eax
ret
DlgProc endp

LISTVIEWPROC proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM


    .if uMsg == WM_NOTIFY
        mov edx,lParam
        mov eax, (NM_LISTVIEW ptr [edx]).hdr.code
          .if eax == NM_CLICK
            nop           
          .endif
    .endif
    invoke CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
    xor eax,eax
    ret
     
LISTVIEWPROC endp

end start

So if I do compile this without to use a manifest file then the executable starts but if I add a manifest in my resources then it starts / closed straight.The question is why?Below my res code..
;This Resource Script was generated by WinAsm Studio.

#define IDD_MAIN 1000
#define IDB_EXIT 1001

;1 24 DISCARDABLE "manifest.xml"
200 ICON DISCARDABLE "bones.ico"

IDD_MAIN DIALOGEX 10,10,446,287
CAPTION "Form1"
FONT 8,"Tahoma"
STYLE 0x10cf0800
EXSTYLE 0x00000000
BEGIN
CONTROL "&Exit",IDB_EXIT,"Button",0x10010000,387,268,52,15,0x00000000
END

That one strange thing so it seems that adding manifest makes trouble but what is the problem?Normaly I always add a manifest file to get the XP style which looks better.Ok so that was one problem.The next problem I found out is if I don't use a manifest then the file runs and all seems to working well but then I do just press on the Listview Header with the right mouse button and now the file does crash on a stackoverflow exception.The funny thing is that I didn't use / check / handle NM_RCLICK in my code.Now I checked again what the problem is and its same stackoverflow.Now I added a NM_RCLICK check in my subclass and do retrun it after without to call CallWindowProc after and now it works again!?!The question now again is why I need to handle & return the NM_RCLICK message and not also then the NM_CLICK too?What is the different now?So my SC code does looking so now...
LISTVIEWPROC proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM


    .if uMsg == WM_NOTIFY
        mov edx,lParam
        mov eax, (NM_LISTVIEW ptr [edx]).hdr.code
          .if eax == NM_CLICK
            nop           
          .elseif eax == NM_RCLICK
            nop
            xor eax,eax
            ret
          .endif                                       
    .endif
    invoke CallWindowProc,OLDLISTVIEWPROC,hWnd,uMsg,wParam,lParam
    xor eax,eax
    ret
     
LISTVIEWPROC endp

end start

So I really don't understand this way of handling between NM_CLICK & NM_RCLICK but now it works again so far......but if I now again add my manifest file...
1 24 DISCARDABLE "manifest.xml"
...then it dosen't work anymore and the file starts / closed again.Really strange matter.So what to do now?How to fix that problem with the manifest and how to find out which messages I have to return without the CallWindowProc API?Normaly I wanna prevent such kind of problems before and don't wanna later debug the file in Olly to find out the exception reasons you know.Maybe the whole notify sending to a SC is really no good idea. :(

PS: Found also before other problems using a manifest file in resources so I also get trouble with some baloon tips options (not all is working with manifest just without).Hhhmmm.So its really pitty.One info,I still use WinASM only and no radasm or any other IDE but I don't think that this could be a problem or?Oh and a another problem I found is that some controls also get handled on a different way if I create them by API or adding by resources.Also a strange matter I don't understand.

greetz
Title: Re: How to subclass correctly?
Post by: jj2007 on June 23, 2015, 06:07:11 AM
I've shortened your code slightly to compensate the lack of All.inc:
include \masm32\include\masm32rt.inc

DlgProc              PROTO :DWORD,:DWORD,:DWORD,:DWORD
LISTVIEWPROC  PROTO :DWORD,:DWORD,:DWORD,:DWORD

IDD_MAIN      equ      1000
...


It works, but I can confirm the problem with the manifest (on Win7-64). It's not the first time, see Weird tooltips behaviour when manifest is included (http://masm32.com/board/index.php?topic=4239.0). Unfortunately, I've not yet been able to google anybody with a similar problem.

Do you have an East Asian language pack installed (http://forum.pellesc.de/index.php?topic=6737.msg25398#msg25398)? It's a known Windows bug related to an XP manifest.
Title: Re: How to subclass correctly?
Post by: Corso on June 23, 2015, 09:21:03 AM
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
Title: Re: How to subclass correctly?
Post by: jj2007 on June 23, 2015, 12:05:06 PM
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 (http://www.vbforums.com/showthread.php?628956-RESOLVED-Big-problem-with-manifest-UserControl-combination&p=3890148), but it's not exactly the same problem.

Not tested: CreateActCtx is NOT equivalent to having a manifest file (https://social.msdn.microsoft.com/Forums/vstudio/en-US/8a495bd5-5ce5-4454-b738-a2269a6be4b1/createactctx-is-not-equivalent-to-having-a-manifest-file-imagelists-with-32-bit-alpha-dont-work?forum=vcgeneral)
Title: Re: How to subclass correctly?
Post by: Corso on June 24, 2015, 04:57:14 AM
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
Title: Re: How to subclass correctly?
Post by: jj2007 on June 24, 2015, 05:15:26 AM
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 (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1019) 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.
Title: Re: How to subclass correctly?
Post by: Corso on June 24, 2015, 06:06:09 AM
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
Title: Re: How to subclass correctly?
Post by: dedndave on June 24, 2015, 10:06:48 AM
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
Title: Re: How to subclass correctly?
Post by: Corso on June 25, 2015, 04:54:24 AM
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
Title: Re: How to subclass correctly?
Post by: Corso on June 26, 2015, 04:15:56 AM
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
Title: Re: How to subclass correctly?
Post by: ragdog on June 27, 2015, 02:50:46 AM
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,
Title: Re: How to subclass correctly?
Post by: Corso on June 27, 2015, 03:47:13 AM
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
Title: Re: How to subclass correctly?
Post by: ragdog on June 27, 2015, 04:35:32 AM
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,
Title: Re: How to subclass correctly?
Post by: Corso on June 27, 2015, 09:07:45 AM
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
Title: Re: How to subclass correctly?
Post by: Corso on August 22, 2015, 07:37:16 AM
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
Title: Re: How to subclass correctly?
Post by: dedndave on August 22, 2015, 08:31:03 AM
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 (https://msdn.microsoft.com/en-us/library/windows/desktop/bb760769%28v=vs.85%29.aspx)
Title: Re: How to subclass correctly?
Post by: Corso on August 25, 2015, 09:23:15 AM
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
Title: Re: How to subclass correctly?
Post by: dedndave on August 27, 2015, 08:45:42 AM
usually, to display toolbar icons, i don't actually use icons, per se
what i use is a bmp strip, with different icons

see the attached BMP file, renamed to ZIP for forum compatibility
also notice that the "enabled" and "disabled" versions of different buttons are seperate images in the strip
and - notice the "pinkish" color, which is used as a transparent color

the BMP file is stored as a resource in the EXE file
in this case, i think i used 256 color images
Title: Re: How to subclass correctly?
Post by: dedndave on August 27, 2015, 08:50:23 AM
i used my own custom button code (not required) to make fancy buttons, like those provided by .NET   :P
Title: Re: How to subclass correctly?
Post by: TouEnMasm on August 27, 2015, 05:00:02 PM
Hello,
You are using the Windows.inc of the masm32 package.
This one had made the bad choice to modify the structure instead of align them correctly.
Many problems on various usage come with this choice,not only with the controls.
But the controls are very diffcult to use with those headers
Here is a listview sample who don't use those include file.
http://masm32.com/board/index.php?topic=4528.msg48489#msg48489
The resizing of the column works without any code.
it is in 64 bits but the code isn't really different from the 32.
Title: Re: How to subclass correctly?
Post by: Corso on August 28, 2015, 01:00:28 AM
Hi again,

so till now I didn't play with any image strips so far instead to use icons. :)
So I got a question to WinASM + Windows.inc file.So I have seen that WinASM dosen't show me all options of Styles / ExStyles in my controls which I could enable & disable.Is that a bug of WinASM?

PS: Is there any method to fix my WM_GETTEXT problem (I did post before) at WM_CHAR check or have I to write any custom code for that?

Thanks again