News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How to create Multi Window application?

Started by CoR, February 06, 2007, 03:01:15 PM

Previous topic - Next topic

CoR

  I want to make something that looks like winamp with playlist or equalizer.
One window will be used as input window, other could handle display of some results third will show a BMP.
This is my way of doing it:

invoke RegisterClassEx, wc

invoke CreateWindowEx, param, param1,...
mov hwndWindow1,eax
invoke ShowWindow,hwnWindow1,SW_SHOWNORMAL
invokel UpdateWindow, hwnWindow1

invoke CreateWindowEx, param2, param3...
mov hwndWindow2,eax
invoke ShowWindow,hwndWindiow2,SW_SHOWNORMAL
invokel UpdateWindow, hwndWindow2

And this works! I had little trouble understanding that hWnd in MSG structure will carry hwndWindow1 or hwndWindow2 messages. But now I have it (sort of) under control in message pump.

Problem is that I have two application names on taskbar. Is there better or cleaner way to make MWA (multi window application)?

TNick

Hello, CoR!

Create one window with CreateWindowEx.hWndParent set to NULL => hWND_Main
Create other windows with CreateWindowEx.hWndParent set to hWND_Main, but don't use WM_CHILD if you don't want other windows to appear in client area of your main window.

Regards,
Nick

hutch--

CoR,

You will only get that problem if you use the same WndProc for more than one window. If you arew creating each window with CreateWindowEx() you are better to create a seperate WndProc for each window. It can be done the other way but the result is a bit complicated and a lot easier to make a mess with.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

CoR

     10x guys!

CreateWindowEx set on 0 for main and others filled with hwndMain did the trick  :toothy
Btw, can I register a more than one  wc classes and later choose which one to use in CreateWindowEx?

Though I still can not filter WM_CREATE well enough in WndProc! 
WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
LOCAL param, param1, ...
mov eax,hWnd
cmp hwndInputWindow1,eax
je Input1
cmp hwndFlagWindow1,eax
je Flag1
cmp hwndMainWindow,eax
  je MainWindow

Input1:
cmp uMsg, WM_CREATE ...
...
jmp DestrpyMainCheck

What's wrong with it? Especially if it handles WM_CLOSE correctly! Is there some special behavior of WM_CREATE?
Problem is that Edit control made with hWnd makes edit controls on EVERY window.
But Edit control made with hwndInputWindow1 makes Econtrol on desired window.

I already see that one WndProc for multi window app is really messy. But I would like to understand my errors. If anyone would like to look at code, troubled hWnd is in line 363.

hutch,
how to create separate WndProc for each window? Would that be multi-threading? if it is, I'll look at Icz tute tomorrow.

p.s. good night everybody. I am going to sleep. was 15 hrs in front of comp. too tired to think straight. yet my mind is still glued to WndProc.

[attachment deleted by admin]

hutch--


Quote
hutch,
how to create separate WndProc for each window?

Same way as you make a singe WndProc for a single window. It is the WNDCLASSEX structure that determines where a window sends its messages, for each new window, create a seperate class, register it, create the window and point its messages at the individual WndProc. Note that each WndProc must have a unique name.

LATER: Here is a quick example. A normal CreateWindowEx() app creating another Window that has a seperate WndProc.

[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

CoR

I tried to use BitBlt in flag window in code above. It simply does not work. Something is happening with that WndProc and WM_CREATE that I can not understand. I would love to know WHY it's not working.
*time is passing*
Now I understand half of problem! If I make only one cmp uMsg,WM_CREATE and use separate window handles everything looks ok.  EditBox, Flag bmp, main window... It works  :clap:
So, why is WM_CREATE so different from other WM_'s?

Anyway I'll rewrite code to use Hutch's multiple WndProc. But now it's official! I have no clue WHY Hutch's application works  :(

How's possible to register wc class as LOCAL in procedure, end that same procedure and after all that call CreateWindowEx? Why it works? Are functions in asm different from functions in C/C++ and somehow preserve LOCAL var?
Or there's something going on with wc I do not know?

Which brings my next question:
How does RegisterClassEx and CreateWindowEx work? If I got it correctly I have to use both simultaneously!

First RegisterClassEx with WndProc123 and than call CreateWindowEx to produce Window123.

CreateWindowEx does not have pointer to wc because it somehow get last registered wc... I'm I right? How?
What happens later? Are those wc parameters stored in Window123 somewhere, somehow...

If I am asking too much just link me somewhere to read something. Trouble is that I do not have enough knowledge even to ask right questions :(




hutch--

CoR,

It has been mentioned before why the WM_CREATE message is different from the rest. It is only ever called once and this is by the CreateWindowEx() function BEFORE it returns. When processing the WM_CREATE message you MUST use the handle in the WndProc as the return value from CreateWindowEx() does not yet exist.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

TNick

Hello, CoR!

About that RegisterClass(Ex) and CreateWindow(Ex) ...

Registering a class means that you create a template with certain characteristics:
- a style (have the client and/or window area being aligned at byte boundary or not, have a unique Device Context for all windows that are created using this template, send double clicks to windows procedure or  not, ...)
- a procedure.Useful when you have two or more windows that you want to behave same way on all events. All events (windows messages) for a window which was created using this template (class) will end up in a call to this procedure.
- extra bytes for this class or for each window
- an icon to be shown in top left corner and, for RegisterClassEx, an icon to be shown in the task bar
- a cursor, a background color and a menu
- ...

After you have this template, you can start creating windows using it, by using CreateWindow(Ex).

Hope this gives a better understanding about those two.


About BitBlt now (and any other function that involves a DC):
for any given window, you may have it's DC in two ways:
- by processing the WM_PAINT message (use BeginPaint and EndPaint) and using the DC provided in PAINTSTRUCT structure
- by using the GetDC and ReleaseDC anywhere outside WM_Paint
(If you have used CS_OWNDC style for the class that this window belongs, you just have to use GetDC once)

To have a memory DC, you may use CreateCompatibleDC or CreateDC

Regards,
Nick


CoR

 So are you saying that WM_CREATE is send ONLY once to WndProc!? Even if I created multiple window!
That would explain why I had to put invoke LoadBitmap,hInstance,100   mov hBitmapF,eax at line 366-367 because it kind of never was executed at line 417-420!  If that's true it's excellent!  Though it does not explain why hWnd is not working in editbox but hwndInputWindow1 is in line 372... But every window handles it's own exit msg.  :eek And I do not know why  :(
Anyway, thank you Hutch. I am giving up from my approach. It does not work correctly anyway. It's just my neurotic behavior that I want to understand as much as I can to be able to move on.  :wink

Nonono Nick, I understand how I put parameters in wc.class template and what they do. But relationship between RegisterClass(Ex) and CreateWindow(Ex) is still mystery to me. I am puzzled because there is no pointer to wc class in CreateWindow(Ex). It surely relates on sequence.
If I got it right I have to do this:
  RegisterClass(Ex) wc1
CreateWindow(Ex) handleWindow1

  RegisterClass(Ex) wc2
CreateWindow(Ex) handleWindow2
... so on...

To have two separate windows with two different WndProc. Right?

And what happens if I do something like this:
RegisterClass(Ex) wc1

...code and some more code...

CreateWindow(Ex) handleWindow1.

Will it work? What's the real link between RegisterClass(Ex) and CreateWindow(Ex) ? Is sequence only relevant in it?


Thanks for BitBlt. If I understand correctly GetDC and ReleaseDC are for my drawings and with WM_PAINT I collect resizing, moving, overlapping etc of window.



[attachment deleted by admin]

TNick

Hi again!

Don't have too much time but here is a brief answer:
- When you call RegisterClass(Ex) the name that you provide for that class is stored internally in a table, along with a pointer to class structure (also stored internally).
- when you call UnregisterClass, this entry in the table and the structure are removed
- when you call CreateWindow, the name that you provide is searched in the internal list. If it is found, the pointer to the structure that holds informations about that class is stored in that windows's memory.
- when an event occurs, using that pointer, Windows finds the procedure like this, I supose:
window handle -> pointer to window's structure -> pointer to it's class -> pointer to the function to call

Doesn't matter if you call CreateWindow after you call RegisterClass or some time latter, as long as between those 2 calls was no UnregisterClass for that class.

Regards,
Nick

CoR

10x a lot!
Things are starting to become clearer and almost understandable in single window app. But I still have no clue how it works in multiwindow application.
So is this way OK?
RegisterClass(Ex) wc1
CreateWindow(Ex) handleWindow1

  RegisterClass(Ex) wc2
CreateWindow(Ex) handleWindow2

  RegisterClass(Ex) wc3
CreateWindow(Ex) handleWindow3


Or I can somehow use this way for multiwindow?
RegisterClass(Ex) wc1
  RegisterClass(Ex) wc2
  RegisterClass(Ex) wc3

CreateWindow(Ex) handleWindow1
CreateWindow(Ex) handleWindow2
CreateWindow(Ex) handleWindow3
Which looks kind of awkward  :eek Because I do not understand how those register and create functions works.

Do I have to use separate ClassName for each wc.class? As I can see, that's only way to differentiate wc.class in multivindow app.

CoR

#11
Ok, now I'm going to rest. In the mean time you all revoke my license to use brain!
It's all in ClassName! WC.Class names HAS to be different! It's even in Hutchs example. But I didn't see the forest of all the trees.

Sorry guys. I am little  :red right now.