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

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..

...now on this picture you can see that it works correctly without subclassing and if I handle all just in my main procedere.

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

dedndave

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

Corso

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

fearless

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.

Corso

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

jj2007

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 macro, either below the main WndProc or under the subclass:

include \masm32\MasmBasic\MasmBasic.inc      ; download
...
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.

rrr314159

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
I am NaN ;)

Corso

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

fearless

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.

jj2007

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 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.

dedndave

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

Corso

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

dedndave

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

Corso

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

jj2007

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. Unfortunately, I've not yet been able to google anybody with a similar problem.

Do you have an East Asian language pack installed? It's a known Windows bug related to an XP manifest.