Hi,
Am trying to create a child window in a MDI using CreateWindowEx but i get a '1400' error 'invalid window handle'.
The handle supplied to the child window is the client win handle, & I've tested the return on the clientwindow & it seems to return a valid handle
the code displays the client win handle & the error code after the childwin creation call
Thanks.
~
http://msdn.microsoft.com/en-us/library/ms644923%28v=vs.85%29.aspx
i think the problem may be related to using MDIS_ALLCHILDSTYLES with CreateWindowEx
you should be able to create it with CreateWindowEx
but, you have to thoroughly review the docs for WNDCLASSEX and CreateWindowEx :P
you may be missing a flag somewhere
if you google around a bit, you can find a zip called "xxControls"
lots of cool stuff in there
they have an example of an MDI...
main window
invoke CreateWindowEx, NULL, ADDR szClassMain,
ADDR szDisplayName,
WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,
NULL,hMenu,
hInstance,NULL
child...
invoke CreateWindowEx,WS_EX_CLIENTEDGE,
ADDR szClassMDI,NULL,
WS_CHILD or WS_CLIPCHILDREN or WS_VISIBLE,
0, 0, 0, 0,
hWin,0,
hInstance,ADDR ccs
Multiple Document Interface, MSDN (http://msdn.microsoft.com/en-us/library/ms632591(v=VS.85).aspx)
Here is the MSDN documentation: About the Multiple Document Interface (http://msdn.microsoft.com/en-us/library/ms644908(v=vs.85).aspx)
hi.
Quotehttp://msdn.microsoft.com/en-us/library/ms644923%28v=vs.85%29.aspx
i think the problem may be related to using MDIS_ALLCHILDSTYLES with CreateWindowEx
you should be able to create it with CreateWindowEx
but, you have to thoroughly review the docs for WNDCLASSEX and CreateWindowEx Tongue
you may be missing a flag somewhere
just tried it without MDIS_ALLCHILDSTYLES, still the same thing. its not like its a hack either, since the SDK mentions using CreateWindowEx
microsoft says to use the WS_EX_MDICHILD when creating the child window with CreateWindowEx. and in the code you posted they use WS_EX_CLIENTEDGE.
I tried it though with WS_EX_CLIENTEDGE (& without WS_EX_MDICHILD).. but still the same problem. error code 1400 ....invalid windowhandle
also the code you posted as being the child win creation is probably the client window, cause in the last argument the pointer should be to a MDICREATESTRUCT & ccs seems to be the CLIENTCREATESTRUCT
Thanks~
RAINSTORM,
I was looking through an old MDI project that I did in C++, which I ran on Windows XP.
Much of the code is similar, except that when I called CreateWindowEx to create my Client Window (as you did), I didn't use the MDIS_ALLCHILDSTYLES flag in my Window Styles, I or'd together: WS_CHILD, WS_CLIPCHILDREN, and WS_VISIBLE flags instead. Also, I zeroed out all the fields of the CLIENTCREATESTRUCT before setting the Menu ID and First Child ID. I don't know how MDIS_ALLCHILDSTYLES is defined. Where did you find the definition ???
UPDATE:
I had several different types of child windows: a Listbox and a DirectX device display. When I called CreateWindowEx for the Listbox, I passed the Window Handle of the Frame Window (NOT the Client Window, and I didn't use a MDICREATESTRUCT at all),...and, the Listbox displays OK in the client area of the Frame Window when the user makes a menu selection from the Client Window (the original Frame Window does not have a menu). The situation with the DirectX display was very different,...I passed the Window handle of the CLIENT Window to the initialiization routine (but, didn't use a MDICREATESTRUCT here either,...DirectX uses the CreateDevice call, to which I passed the Window Handle for the Client Window).
From WinUser.h in the PSDK:
/*
* MDI client style bits
*/
#define MDIS_ALLCHILDSTYLES 0x0001
And there is an explanation of what it does here:
http://msdn.microsoft.com/en-us/library/ms644910(VS.85).aspx
\masm32\examples\exampl02\mdidemo
i'll be damned :bg
invoke CreateWindowEx,WS_EX_MDICHILD,
ADDR cName,
ADDR mdiTitle,
MDIS_ALLCHILDSTYLES,
10,10,Rct.right,Rct.bottom,
hClient,NULL,hInstance,NULL
it looks like you're missing WS_EX_MDICHILD
from my original post....
Quoteyou should be able to create it with CreateWindowEx
but, you have to thoroughly review the docs for WNDCLASSEX and CreateWindowEx :P
you may be missing a flag somewhere
the class must be registered
Quote
;Frame FRAME_DATA <>
invoke Register_Frame ;
; -----------------------
mov Frame.extstyles,WS_EX_LEFT
mov Frame.styles,WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN
invoke CreateWindowEx,Frame.extstyles, ADDR Frame.Class, ADDR Frame.Titre, \
Frame.styles , CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,\
NULL,Frame.Hmenu,hInstance,NULL
invoke GetWindow,Frame.Hwnd, GW_CHILD
mov Frame.Hcliente,eax
dedndave...
Quoteit looks like you're missing WS_EX_MDICHILD..
No, the WS_EX_MDICHILD style is in my code too.
QuoteI don't know how MDIS_ALLCHILDSTYLES is defined. Where did you find the definition ???
baltoro, the MDIS_ALLCHILDSTYLES, is supposed to enable additional window styles so that they can be used in a MDI
ToutenAsm, just dloadd'ed your code & looking through it, it runs properly..... am looking to create the first child window on startup though.
can yuo say whats wrong with my code ?.. why its not working ?
ty
ps: nice demo : )
I have made this code with an old sample that i have updated with the new method given by MSDN.
I have just seen in your code that you haven't call the register_mdi,what is a new thing.
There is other new things in the source,study it and you will find what is wrong.
ToutenAsm,
i've been mainly reading from the sdk on my hard disk.. which is not the latest..
i've registered these two classes in my code
invoke RegisterClassEx, addr frame_wcl ; register the frame class
invoke RegisterClassEx, addr defchild_wcl ; register the default child window class
thx
EDIT:: just looked through the online docs too & it seems, stillgotta register just the frame & child classes, (the client class is a system class)
Rainsrorm,
maybe you missed this one.....
click on the left button to create new mdi children
looking through your code, not sure what am missing
are you able to create it on startup ?.. like without a button
ty
first - it isn't mine :P
i think Hutch wrote that one :U
with Hutch's code, always have a quick look at the include file(s) :bg
may be something in there of interest
after that...
in the mdidemo.asm file, look at the 3 procs at the end of the file
in the WndProc function, the left button calls MakeMDIWin
if you want to create more than one child, you will need an array for the handles
he uses the same variable over and over for the demo (mdihWnd)
he registers and creates the main window in WinMain
RAINSTORM,
Hutch's example passes no MDICREATESTRUCT to CreateWindowEx. The last parameter is NULL. Which is weird because the MSDN documentation suggests passing the MDICREATESTRUCT when creating a child window. :eek
a pointer to the MDICREATESTRUCT structure is passed to MDI child windows WndProc upon WM_CREATE
lParam, i think, points to the structure
during create, you may alter values in the structure before returning
i dunno - may be you can pass one to CreateWindowEx, as well
but it is easier just to modify the one it sends to you :P
it's all filled in - you just make any necessary changes
maybe i read the docs wrong, too :P
here we go...
QuoteWhen the MDI client window creates an MDI child window by calling CreateWindow, the system sends a WM_CREATE message to the created window. The lParam member of the WM_CREATE message contains a pointer to a CREATESTRUCT structure. The lpCreateParams member of this structure contains a pointer to the MDICREATESTRUCT structure passed with the WM_MDICREATE message that created the MDI child window
sounds a little confusing - lol
it hardly makes sense that you would...
create the structure
wait for the pointer to be passed
dereference it twice
then, modify it
a little experimentation should be easy enough
DAVE !!! I think you're onto something here,...
I was reading the documentation for CreateWindowEx,...and it says: " If an MDI client window calls CreateWindow to create an MDI child window, lpParam (the last parameter) should point to a MDICREATESTRUCT structure. lpParam may be NULL if no additional data is needed."
In my MDI application that I mentioned, above, I call CreateWindowEx to create the MDI child window in the handler for WM_CREATE message in the Windows Procedure for the Frame Window just after creating the Client Window,...and I had to pass the window handle for the Frame Window (instead of the handle for the Client Windows as the documentation directs) to get it to work. This is what RAINSTORM does in his code (calling CreateWindowEx from the Frame Window's Window Procedure), except that he passes the window handle of the Client window.
right - 3 "levels" of windows, eh ?
Frame - Client - Child
more stuff to learn :P
you only have to register 2 classes, though
MDICLIENT is a pre-registered system class
the Frame class is similar to a regular window
then, the Child class is a bit different
i guess you can create the Frame window in Winmain and the Client window in WM_CREATE
i am also noticing that they have special DefWindowProc's
DefFrameProc
DefMDIChildProc
sooooo, i guess the Client window still uses DefWindowProc :red
That's the mysterious part,...I have no idea what the Window Peocedure is for the Client Window,...but. it has one, because an alternate technique for creating a child window is to send a WM_MDICREATE Message (http://msdn.microsoft.com/en-us/library/ms644913(v=VS.85).aspx) to the Client Window. The documentatation for CreateWindowEx says this about the MDICLIENT Window Class: "Designates an MDI client window. This window receives messages that control the MDI application's child windows."
And, Child Window Procedure is: DefMDIChildProc Function
(http://msdn.microsoft.com/en-us/library/ms644925(v=VS.85).aspx)
My best guess at this point is just to move the MDI Child Window creation code out of the WM_CREATE message handler in the Window procedure for the Frame Window. This is what hutch does in his example that you mentioned previously. In my MDI application. the MDI Child Window creation code resides elsewhere (however, DirectX is a special case).
doesn't sound too bad :P
i have the RegisterClassEx stuff written and WndProc for the Frame started
after my nap - i will play some more
i think the hardest part is keeping track of ID's and handles for the children
oh
it says we should allow extra bytes for each child window
wc.cbWndExtra = CBWNDEXTRA
i haven't found how big that is, yet :P
baltoro wrote..
QuoteHutch's example passes no MDICREATESTRUCT to CreateWindowEx. The last parameter is NULL. Which is weird because the MSDN documentation suggests passing the MDICREATESTRUCT when creating a child window...
I think its kind of optional depending on what you are doing & if you want to pass some info, moreso with CreateWindowEx than the other methods.. since CreatewindowEx already passes a lot of info.
I just tried with the last param '0' instead of' addr mdics'.... still the same thing
QuoteIn my MDI application that I mentioned, above, I call CreateWindowEx to create the MDI child window in the handler for WM_CREATE message in the Windows Procedure for the Frame Window just after creating the Client Window,...and I had to pass the window handle for the Frame Window (instead of the handle for the Client Windows as the documentation directs) to get it to work.
baltoro the sdk says, that the client window handle has to be passed while creating a child window - I use the hwnd from the frame Proc, WM_CREATE to create the client window, & then the hwndclient to create the child win [I've tried with the frame handle too though cause yuo suggested it earlier on & it didn't work]
QuoteThat's the mysterious part,...I have no idea what the Window Peocedure is for the Client Window,...but. it has one, because ...
The client procedure is managed by the system, cause its a system class 'MDICLIENT'
Quotei think the hardest part is keeping track of ID's and handles for the children..
windows takes care of that for you, ID's (not sure in the case where you use the CreateWindowEX method to create the child though)
===========================
This part is off topic but am posting it in case someone else has teh same prob.
I couldn't get a rebar control to display a week back, & it seems (google) that, it was because of a problem/bug with some versions of commctrl.h - its fixed in later versions though
thx!
Interesting.
Do you think the Client Window has for some inexplicable reason been destroyed ???
You could try calling GetWindowLong Function (http://msdn.microsoft.com/en-us/library/ms633584(v=vs.85).aspx) (which takes a window handle), using, for the Index, GWL_WNDPROC to retrieve the address of the window procedure. I'll bet you get the same 1400 error.
the grey part ias the client window so its being displayed...
EDIT : tried what you said though & GetWindowLong returns nonzero
Damn !!! I'm stumped. The code is well-written, and, looks like it should work,...
The documentation says the the usual reason for CreateWindowEx failing is an invalid parameter,...you undoubtedly read this,...
hi baltoro,
I'll go through it again in a little while, might be some flag or something in the class, like dave said - though the sdk usually mentions if something will explicityly cause a prob
..appreciate all the feedback
Rainstorm.
ok - i figured out why you are getting the creation error
when you create a window, the WndProc function is called during creation (before CreateWindow returns)
i believe this applies to pretty much all windows
at that time, the global variable where you store the handle has not been initialized
your MDI child WndProc function looks like this...
DefChildWindowProc proc HWnddefchild:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
default_processing:
invoke DefMDIChildProc, hwnddefchild, uMsg, wParam, lParam ; default processing
ret
DefChildWindowProc endp
notice the handle name in the invoke :P
using the local value fixes that problem
invoke DefMDIChildProc, HWnddefchild, uMsg, wParam, lParam ; default processing
still, no child window, yet :'(
ok - got it going
1) i had to uncomment .586 for masm - not sure if it is needed for JwAsm
2) i made the change mentioned in my previous post
invoke DefMDIChildProc, HWnddefchild, uMsg, wParam, lParam ; default processing
3) the chr$() macro creates zero-terminated strings - no need to add ("",0) - not a problem, but i took them out
4) uncommented the MDICREATESTRUCTURE fill code
5) commented out the message box ;fn MessageBox,0,str$(hwndclient),"hwndclient",MB_OK
6) made 3 changes to CreateWindowEx for the child:
a) added WS_OVERLAPPEDWINDOW to the style bits - not sure why this is needed in this case :P
b) changed the X position from CW_USEDEFAULT to 50
c) replaced ID_FIRSTDEFCHILD with NULL - this value goes in the CREATESTRUCT for the client window
those changes get us a child window
however, the upper corners are not painted properly
what i did to fix that was....
i removed the CreateWindowEx call for the child from the WM_CREATE handler
i made a routine out of it, then called it just before the message loop
this "corner paint" issue and the need for WS_OVERLAPPEDWINDOW are probably related
there may be some other bit we are not twiddling correctly :P
i also cleaned up the class register code a little, and changed the icon to IDI_APPLICATION
mov ebx, hInstance ; handle to the current instance of the application
invoke LoadIcon,ebx, IDI_APPLICATION
mov frame_wcl.hIcon, eax ; ALT+TAB icon etc
mov frame_wcl.hIconSm, eax ; window's title bar icon etc
mov defchild_wcl.hIcon, eax ; ALT+TAB icon etc
mov defchild_wcl.hIconSm, eax ; window's title bar icon etc
invoke LoadCursor, NULL, IDC_ARROW ; predefined cursor (could use LoadImage)
mov frame_wcl.hCursor, eax
mov defchild_wcl.hCursor, eax
mov frame_wcl.cbSize, sizeof WNDCLASSEX
mov frame_wcl.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov frame_wcl.lpfnWndProc, offset FrameWindowProc
mov frame_wcl.cbClsExtra, 0 ; 0 = extra memory not used, 40bytes max
mov frame_wcl.cbWndExtra, 0
mov frame_wcl.hInstance, ebx
mov frame_wcl.hbrBackground, COLOR_BTNFACE+1
mov frame_wcl.lpszMenuName, offset menu_name ; automatically assigns the menu to the window when its created
mov frame_wcl.lpszClassName, offset wclassname
invoke RegisterClassEx, addr frame_wcl ; register the frame class
mov defchild_wcl.cbSize, sizeof WNDCLASSEX
mov defchild_wcl.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov defchild_wcl.lpfnWndProc, offset DefChildWindowProc
mov defchild_wcl.cbClsExtra, 0 ; 0 = extra memory not used, 40bytes max
mov defchild_wcl.cbWndExtra, 32
mov defchild_wcl.hInstance, ebx
mov defchild_wcl.hbrBackground, COLOR_BTNFACE+1
mov defchild_wcl.lpszMenuName, 0 ; NULL since a child window can't have its own menu
mov defchild_wcl.lpszClassName, offset defchildwin_classname
invoke RegisterClassEx, addr defchild_wcl ; register the default child window class
it still needs work
the window is not added to the window menu for some reason - we may need to put stuff in the menu
anyways, here is the modified source...
I made the change to default child handle in the windproc..After that i too was trying stuff.. some of the things you mentioned in your last post, like 'replaced ID_FIRSTDEFCHILD with NULL '...... but individually.
>> i had to uncomment .586 for masm - not sure if it is needed for JwAsm
am using jwasm & i specify that on the command line,(-9) so i had commented it off.
Thx!
dedndave,
of all the the changes you mentioned in your last post, i tried just one, just now.... adding WS_OVERLAPPED to the window style in the Chhild window creation, and the window displayed (left everything else the same as before)
so just that one change displays the window, .....not sure what you meant about the corner painting issue but the window seems to display okay here. its not added to the window menu though.
thx
DAMN !!! Mystery solved. I was so tense,... :eek
...And, yet, the original error returned from CreateWindowEx was: 1400,...ERROR_INVALID_WINDOW_HANDLE,...and, not,...ERROR_INVALID_PARAMETER,...
DAVE !!!
Thanks for the investigative work. And, HEY,...I've noticed that you do that alot (solving everyone's problems),...It's vaguely annoying, actually,... :bg
...On a lighter note,...it's nice to know that everything I suggested was WRONG. Even though it's still early morning,...I'm going out to get drunk,... :eek
QuoteI've noticed that you do that alot (solving everyone's problems),...It's vaguely annoying, actually
:lol
i am just learning, myself
i wouldn't play with MDI unless someone else had trouble with it
i am still playing with it, too :P
as for the ERROR_INVALID_HANDLE....
that error makes sense, now that i see what caused it
it wasn't a handle we were passing to CreateWindowEx
it was the handle passed to DefMDIChildProc that was invalid :P
Quoteof all the the changes you mentioned in your last post, i tried just one, just now....
adding WS_OVERLAPPED to the window style in the Chhild window creation,
and the window displayed (left everything else the same as before)
that may be an OS thing
i am running XP MCE 2005 SP3
to get a proper child, i had to do at least these
1) fill in the MDICREATESTRUCT
2) add WS_OVERLAPPED
3) change CW_USEDEFAULT to 50 (you could probably use CW_USEDEFAULT if you also used it for X)
4) change ID_FIRSTDEFCHILD to NULL
5) remove the child create code from WM_CREATE
after i was done, i tried changing each of those items back individually and there was a problem with each
Well,...all kidding aside,...you'd think the MSDN documentation would be clearer. The information about the Multiple Document Interface says nothing about how to structure your code, or system updating of handle values, valid values for the first child window, or the WS_OVERLAPPED flag,...or any of that.
I noticed. when I was searching for code examples, that almost all the current approaches to MDI (in C++) use either MFC or .NET Framework Forms.
baltoro wrote..
Quote...On a lighter note,...it's nice to know that everything I suggested was WRONG. Even though it's still early morning,...I'm going out to get drunk,...
have fun baltoro,
dedndave,
I just removed the WS_OVERLAPPED style again
& changed this line in the orginal code of the child win CreateWindowEx..
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT
to this...
50, 50, 100, 100,
so, all the rest of the code is the same as it was in the beginning........ & the window was displayed/shown all the time..just not visible because of the dimensions set with CW_USEDEFAULT (i think)
this win doesn't have a title bar, sizing borders etc..but it now displays properly & but those styles can be added
WS_overlapped is suuposed to be used as a main window, but the sdk doesn't completely stop one from using it with the ws_child style either, just WS_POPUP isn't supposed to be used with teh child style
WS_OVERLAPPED is a top level window.. & i've wondered why that name was chosen.
some links..
http://msdn.microsoft.com/en-us/library/ms632600(v=vs.85).aspx
http://en.wikipedia.org/wiki/Window_function#Overlapping_windows
thats from signal processing
thx!
yah - WS_OVERLAPPEDWINDOW is a collection of several bits OR'ed together
you can probably select the correct ones individually
WS_OVERLAPPEDWINDOW =
WS_BORDER or WS_DLGFRAME or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX
0CF0000h =
800000h or 400000h or 80000h or 40000h or 20000h or 10000h
WS_CHILD cannot be used with WS_POPUP
If you need many different styles and you're not exactly sure which one you need, it can be a good thing to use Resource Editor by ketil olsen, set the styles you want, then copy the or'ed hex value from the style edit field and paste the raw hex value into your code. It will reduce overview a tad, but you can easily change the styles again by using the same editor.
Personally, I set the hex values in constants. For example:
RIGHT_ALIGNED_BUTTON = 56473827h
CENTER_ALIGNED_BUTTON = 34534523h
You can have template styles in constants using raw hex values.
i might add....
some of the example code that i have looked at did not use WS_OVERLAPPEDWINDOW for MDI children
with this code, i had to use it to get the child window
that probably means we don't have the right formula, yet :wink
...Oops,...Nevermind,... :eek
ok - got it.....
for the client window, remove MDIS_ALLCHILDSTYLES
then, WS_OVERLAPPEDWINDOW is not required for the children
it appears that MDIS_ALLCHILDSTYLES is intended for the MDI children only
DAVE !!!
Congratulations !!! You are unstoppable.
Now that you have gotten the MDI application working correctly,...let's look at an assembly language implementation of an Active Template Library (ATL) (http://msdn.microsoft.com/en-us/library/3ax346b7(v=vs.80).aspx) version of the traditional Multiple Document Interface (MDI),...
...Wait,...I think there's blood streaming out of my ears,... :eek
When people are eager to help one shouldn't try to oppress him, the post button will still be available for anyone to post to the thread.
Experience from other forums however, it CAN become somewhat "irritating" when someone is always at your service, 24 hours a day and that he always has an answer, it can easily become a reminder of a butler in a tv show. But in the end, helping others is a good thing. Dave is helping people. His help is good and should be appreciated.
The problem of learning problems from the same person all the time is that you also inherit his habits, both good and bad, you don't get mixed influence from a wide variety of experienced programmers. It's important that all people get a chance to teach away, you learn a great deal yourself by teaching others, the more you teach away the more you learn yourself also.
The good part of it is that you always get help when needed :U
that is really true
and - i have a certain "style" of writing code - almost noone in here appreciates it :lol
so, don't use me as the "Do-Bee" example
(http://tinalangley.com/wp-content/uploads/2011/05/do-bee.jpg)
there are many members that have already figured this stuff out, too
they know the material far better than i do
but, they don't seem to have the time to jump in here
they are probably professional coders - and can get paid for it
but, i saw Rainstorm in here, asking for help, and not really getting anywhere, so i got involved
i don't know this stuff, but - hey - let's figure it out together - i want to learn it also :U
i got the menu thingy working
before creating the frame (main) window...
INVOKE LoadMenu,IDM_MAINMENU
store the value returned in EAX as hMenu and use it as the hMenu parameter in CreateWindowEx
remove the hMenu parameter from the CreateWindowEx call for the client window
set the lpszMenuName of the frame window WNDCLASSEX structure to 0
you can set the menu by passing the ID number that way, but then you have to call GetMenu to get the handle
may as well use LoadMenu and get the handle at the same time
in the resource file...
#define IDM_MAINMENU 1000
IDM_MAINMENU MENU DISCARDABLE
and add the EQU to the asm source...
IDM_MAINMENU EQU 1000
actually, i made a more involved menu
i want to make it fully funtional before posting :P
in order for the automatic menu updates to occur, the menu has to be associated with the frame window
even though the "Window" submenu handle is passed to the client in the CREATESTRUCT
I have a mental block when it comes to MDI because I have a strong dislike of the interface. I place MDI in the same category as Microsoft's idiotic ribbon interface.
MICHAEL,
I don't think anybody likes it,...which is why MFC introduced the Document/View Architecture (http://msdn.microsoft.com/en-us/library/4x1xy43a(v=vs.80).aspx). Frankly, this is why I've never liked MFC. If you've ever seen somebody's code in which they are using a MFC class and then create a collision by then calling the underlying Win32 API Window function using a MFC window handle or identifier, you know what I'm talking about.
When I searched for information about the MDI over at Raymond Chen's The Old New Thing (http://blogs.msdn.com/b/oldnewthing/), I discovered that he had absolutely no posts on the subject.
When I was first trying to understand the .NET Framework (because I had a Visual C++ .NET version of Visual Studio), I got a book about programming .NET Forms by Chris Sells: Windows Forms Programming (http://www.sellsbrothers.com/writing/wfbook). The book is excellent,...but, Sells gets into this incredibly long, convoluted discussion about MFC and Document View Architecture. This he contrasts to the .NET version which is the Form Class. Both versions try to reduce the complexity of the concept by building classes that integrate most of the techniques and data structures involved with Window management into simple event handlers, properties and attributes. This they did because so many programmers got caught in an abstract situation that they didn't understand, and their applications would hang, for no apparant reason.
....Rant,...continued,...next post,...
... Rant,...Continued,...
I always avoided the MDI interface, because the various message loops are so easy code so that they are completely dysfunctional.
So, I would go to great lengths in my programs to display data on the screen with simple graphics functions, like the TextOut Function (http://msdn.microsoft.com/en-us/library/dd145133(v=vs.85).aspx). It's tedious to code, but, very reliable. Or, write a bunch of diagnostic data to a text file.
With interdependent message queues, you don't really know what is occurring, unless you have some sort of visible graphic event being fired for every message (and, this is completely impractical). And, I'm assuming that the whole reason Windows has the MDICLIENT window class is just to manage the message loops without programmer interference.
well - i got almost everything working
window menu - accelerators - cascade/tile - all that
i am stumped, for the moment on one last item
that is....
when i select a different window in the window list, it does not activate and the list is not updated
i notice that Hutch's example is the same way
the xxControls example works correctly, but i can't figure out why
that thing has owner-drawn menus and a lot of the code is in a LIB
a little more reading should get it going :P
...Welll,...I was wrong about everything else, but,... :eek
I'm absolutely certain that you send a WM_MDIACTIVATE Message (http://msdn.microsoft.com/en-us/library/ms644911(v=VS.85).aspx) to the Client Window.
Once, you've got the structure correct,...the whole MDI thing is message driven.
Here is a list of the standard MDI messages: MDI Messages, MSDN (http://msdn.microsoft.com/en-us/library/ff468892(v=VS.85).aspx)
From the MSDN documentation for Using the Multiple Document Interface (http://msdn.microsoft.com/en-us/library/ms644909(v=VS.85).aspx):
"When a child window's title is added to the window menu, the system assigns an identifier to the child window. When the user clicks a child window's title, the frame window receives a WM_COMMAND message with the identifier in the wParam parameter. You should specify a value for the idFirstChild member that does not conflict with menu-item identifiers in the frame window's menu."
Hutch's example handles the WM_COMMAND message with a message box instead of activating the child window.
i wish i could tell you how right you are :(
but - alas - the automatic window list works all by itself
the problem was disguised by the nature of IF/ELSEIF/ENDIF blocks
i hate those things - and i kept them in there where i thought it was appropriate
that is a real stretch for me - lol
anyways - when processing the WM_COMMAND message, i always return 0
it's like - if it isn't in my list, it's done
for the MDI frame WndProc, you have to use the default proc for unhandled commands or it won't do the child windows/window list
at any rate, here we go
i added a manifest file, version control block, an icon - all the goodies
with a little scroll and size code (and something to open and paint documents - lol), you have a full-blown app :U
oh - i did a lot of cleanup - hope i didn't toss out something you liked - lol
by the way - Hutch's MDI example has the same problem i had
i bet it would work right with a simple change :U
OOPS - left out a couple members of MDICREATESTRUCT
got Hutch's example to work :U
i updated Mdi.zip in the post above
i left out a couple members of MDICREATESTRUCT :red
i got this one down to 4.5 Kb :8)
i could probably get it down to 4.0 Kb by creating the menu in code and reducing the version control block
it's good enough :P
Good job, Dave :U
thanks, Jochen
that was a fun one :P
Yeah,...Dave !!!
Impressive analytical skills,...
I noticed when reading xandaz's Device Contex thread,...that he and QWORD have a working example of a MDI graphics application here: xandaz_paint (http://www.masm32.com/board/index.php?action=dlattach;topic=17109.0;id=9522)
yah - xandaz has been working on that for a while
i suppose we could have used it as an example :P
the one that i finally did learn from was..........
Iczelion #32 :U
but, it could have been anyone's
i just happened to notice the WndProc exit strategy
Hey... can i post my mdi example. Works very well. Thx
very nice :U
i like the buttons :8)
hey... has anyone ever done menus in MDI Child windows? I just can't figure it out. I've tried set Menu, WM_MDISETMENU but doesn't show the menu bar. Can it be done? Thanks
I think it may not be doable. I read somewhere that windows only supports one menu per application.
http://bytes.com/topic/c-sharp/answers/234060-mdi-child-menu (http://bytes.com/topic/c-sharp/answers/234060-mdi-child-menu)
it should be doable
well - it doesn't seem to work using LoadMenu/SetMenu or by setting the WNDCLASSEX lpszMenuName member
after googling around a bit - it appears some have done it - perhaps they used CreateMenu, rather than loading it from resource
but - there are other related problems
when the child is maximized, the child menu gets merged into the parent menu
at any rate - why not put the menu items for the child in the parent menu
this makes sense because they will all share the same menu functions
Well....i'm kinda having some problems also with SetWindowLong,hWnd,GWL_USERDATA for MdiChild windows. Does this work? Man what a drag.
The thing is that i wanted it to have different menu rather than the frame window's. I guess it can't be done, so,... i'll just leave it alone.