PowerBASIC Forums
  PowerBASIC for Windows
  Relationships among messages, controls, and dialogs

Post New Topic  Post A Reply
profile | register | preferences | faq | search

UBBFriend: Email This Page to Someone! next newest topic | next oldest topic
Author Topic:   Relationships among messages, controls, and dialogs
Jamal Mazrui
Member
posted May 16, 2005 01:10 PM     Click Here to See the Profile for Jamal Mazrui     Edit/Delete Message   Reply w/Quote
Although I have read and re-read explanations of this topic, I am still having trouble getting a firm conceptual grasp of the relationships among messages, controls, and dialogs. For example, which messages go to the callback procedure of the control, and which to the call back procedure of the dialog? Do some messages initially go to the control procedure, and then go on to the dialog procedure? Do some messages automatically go in the reverse direction: from the dialog to the control?

I interpreted some MSDN documentation to say that a window has an internal procedure that is in addition to the procedure one accesses via subclassing. This confused me because I thought subclassing was a means of getting to the message processing done by a control that is not otherwise exposed. How many layers of message-processing procedures are associated with the same window?

I have also been confused about when to return True or nonzero after processing a message with custom code, and when to return the opposite. I thought True should be returned if no additional, automatic processing by Windows was desired. I recall reading something about the WM_INIT dialog message, however, that said the opposite, that is, False should be returned by custom code if the initialization tasks are to continue.

Related to all this, I wonder when it is best to think of a control as the source of a message, when to think of its parent dialog as the source, when to think of the operating system generally as the source, and when to think of a user action as the source.

I realize that I have asked a lot of questions, and that this may be a broad topic. Any conceptual distinctions that can help me categorize and understand the various relationships would be appreciated.

Jamal

IP: Logged

Michael Mattias
Member
posted May 16, 2005 01:32 PM     Click Here to See the Profile for Michael Mattias     Edit/Delete Message   Reply w/Quote
DDT-style or SDK-style programming?

There can be some very signficant differences.

IP: Logged

Jamal Mazrui
Member
posted May 16, 2005 02:09 PM     Click Here to See the Profile for Jamal Mazrui     Edit/Delete Message   Reply w/Quote
  I prefer DDT-style coding, though hope to gain a conceptual framework that incorporates what DDT is doing differently. Certainly though, I would gladly learn a simplified DDT explanation before additional SDK complexities.

[This message has been edited by Jamal Mazrui (edited May 16, 2005).]

IP: Logged

Chris Boss
Member
posted May 16, 2005 02:42 PM     Click Here to See the Profile for Chris Boss     Edit/Delete Message   Reply w/Quote
Jamal,

Windows messages 101:

Let's start with how things really work with Windows under the hood !

Windows works basically with just one type of callback procedure
for Windows event messages. It is called a Window procedure.

Every window class (a specific window type, such as a Button or
ComboBox) has its own Window procedure.

A Window procedure looks like this:


FUNCTION MyWindowProc(BYVAL hWnd&, BYVAL Msg&, BYVAL wParam&, BYVAL lParam&)
SELECT CASE Msg&
CASE %WM_CREATE ' example of a message
END SELECT
FUNCTION=DEFWINDOWPROC(hWnd&, Msg&, wParam&, lParam&)
END FUNCTION

All Windows work this way, no matter what programming language or
style you use. Some programming languages may shield you from this,
but they are there none the less.

If a Window created is of a predefined class, the Window procedure
will exist within the operating system itself. This is why with controls
you have to subclass them if you want access to their Window procedure.

Even Dialogs (aka. DDT or the Windows Dialog engine) have their
actual Window procedure in the operating system itself.

The only window type that you do have direct access to the window
procedure are window classes you create yourself in your program.

If Dialogs have their Window procedure in the operating system,
then how to do access their messages in a Dialog procedure, you
may ask ?

Easy, the Dialog class has a built in form of subclassing (or better
called rerouting of messages) called a Dialog procedure.

When the Dialog is created it is passed an address to a Dialog
procedure. The Window procedure (in Windows OS) for the Dialog
will reroute all messages to the Dialog procedure provided, before
processing them itself.

This is how Dialogs get a Dialog procedure !

A Dialog procedure does have limits and it is not exactly
the same as a Window procedure.

For one, a Dialog procedure tells the Window procedure whether
to process a message or not, by its return value to the function.
Non-Zero means don't process it, since the Dialog procedure has.

The problem is that the Dialog procedure can't always return a value
(directly anyway) for a message. Some messages work fine, but others
can't simply return a value , in particular a zero value, since
a zero tells the window procedure to process the message. This is
a little complex here and can be explained better later. Let is
suffice that the Dialog procedure has limitations or may at least
require special processing to make sure windows gets the proper
retur value for a message.

For most instances though, the Dialog procedure can handle easily
most common messages.

Please note that some messages never get sent to a Dialog procedure,
such as WM_NCCREATE or WM_CREATE. The Dialog procedure does send a psuedo
message to replace the WM_CREATE message called WM_INITDIALOG.
Window procedures never get this message. It is a message generated
by the Dialog class Window procedure to a Dialog procedure.

With that said,

DDT is based on the Windows Dialog engine, so the rules associated
with using a Dialog procedure apply to DDT.

The Dialog procedure is some times refered to as a callback procedure.

I am not sure of the original of the term callback, but I think it
is associated with the C programming language.

From my perspective, I have always viewed the term callback as simply
a procedure (function actually) which is called dynamically using a
provided address. Rather than the address being fixed in stone
(such as at compile time), the address can also be provided dynamically
a runtime as well. This is how subclassing works, since you dynamically
change an address of a windows window procedure to a different one
and the subclass procedure simply has to call back to the original
one. Its kind of like being rerouted on a detour when driving a
car. The original destination is the same, but how you get there
changes.

Now what DDT refers to as callback functions for controls are
in reality not window procedures or even a dialog procedure at all.

They are not even subclass procedures.

They are simply functions which the DDT engine callbacks to when it
processes one particular window message for a Dialog:

WM_COMMAND

Some Controls send this message to the window procedure of their
parent (aka. Dialog). DDT traps this message and sends it to a
callback procedure (simply a function you provide) if one was
available (meaning defined via code in the DDT control create
command). This means that DDT must track the controls ID and its
callback procedure address, set some internal variables (the CB...
stuff provided in DDT like CBHNDL) and when the Dialog receives
the WM_COMMAND message, reroute the messages to the callback
you provided via code.

The control callbacks do not have an API counterpart. They are
unique to DDT. It is simply a matter of the compiler handling
some message rerouting within its runtime code.

Actually DDT has two levels of rerouting.

One is the dialog procedure. In true Windows terms, there is
only one dialog procedure for a Dialog. In DDT there are two.
One is internal to DDT, where is can preprocess messages before
your code provided dialog procedure can. (as far as I can tell,
DDT uses the Windows dialog engine and does not have access to
the Window procedure. a Superclass of the Dialog class would though.)

We don't know for sure how DDT works internally, but it is
either subclassing the dialogs window procedure and then let's the
Dialog class handle your dialog procedure or DDT uses its own
internal Dialog procedure and then simply reroutes messages to
your dialog procedure. No matter how they do it, it requires
redirection twice. A Dialog procedure for a Windows generated
Dialog (calling API directly) would have only one redirection.
A Window procedure for a Window class you created (calling the
API) would have no redirection. You would process the messages
directly in the window procedure.

As far as Controls Callback routines, don't think of them like any
of the above. They are not a Window procedure and they are not
part of windows normal window message processing. They are not
a dialog procedure in any form. They are simply a function which
DDT calls in response to the WM_COMMAND message (generated by the
control) to code you provide in your callback routine.

It would be no different if you wrote your app using CreateWindowEX
(API directly) and processed the WM_COMMAND message for your parent
window and redirected the WM_COMMAND messages to a separate function
for each control.

View the control callback as a form of message redirection !

Yes, you get messages, but the function is not a window procedure
or the like.

It is simply a mechanism to simplify coding for you and thats it.

Actually the DDT implimentation is quite efficient and simple.


------------------
Chris Boss
Computer Workshop
Developer of "EZGUI"
http://ezgui.com

[This message has been edited by Chris Boss (edited May 16, 2005).]

IP: Logged

Jamal Mazrui
Member
posted May 16, 2005 03:30 PM     Click Here to See the Profile for Jamal Mazrui     Edit/Delete Message   Reply w/Quote
Thanks for your response, Chris.

I guess I had mistakenly thought that a call back procedure is a window procedure. It still seems to have a similar purpose and operation, even though Cb variables are available inside the procedure without having being passed as message parameters.

You said that every window has a single window procedure of the form:
FUNCTION MyWindowProc(BYVAL hWnd&, BYVAL Msg&, BYVAL wParam&, BYVAL lParam&)

Your example function seemed to call another function in the line:
FUNCTION=DEFWINDOWPROC(hWnd&, Msg&, wParam&, lParam&)

Aren't these two message-processing procedures for a single window?

I understood you to say that if a DDT dialog has a call back procedure, it is not the true "dialog procedure," which is also not the "window procedure." In what order do these procedures process messages? Is a DDT call back the first to receive a message, followed by the dialog procedure, followed by the window procedure?

Which messages go to control call back rather than dialog call back procedures? Does this depend on a WS_NOTIFY style for some controls?

As you can tell, my understanding still has a way to go .... <grin>

Jamal

IP: Logged

Simon Morgan
Member
posted May 16, 2005 07:10 PM     Click Here to See the Profile for Simon Morgan     Edit/Delete Message   Reply w/Quote
Jamal

For DDT programming, things are somewhat simpler. Messages for all controls go first to the callback procedure for that control (if there is one). Unless that procedure returns FUNCTION=1, the same message then gets passed to the callback procedure for the dialog.

Returning FUNCTION=1 tells the DDT engine that you don't want it to do any further processing of the message. This is the opposite of what you need to return in most SDK style callbacks. In most cases it makes no difference what value you return when using DDT.

The call to DEFWINDOWPROC in Chris's very thorough response above is never needed in a DDT callback procedure. It simply tells Windows to do its normal thing with this message.

A DDT callback is similar in many ways to an SDK-style callback using the Windows Dialog engine, but there are differences because it is being contolled by PB runtime procedures included in the resulting executable file. A DDT callback is also treated differently at compile time, for example by dealing with the CB... functions that are not available to SDK programmers.

IP: Logged

Chris Boss
Member
posted May 16, 2005 07:54 PM     Click Here to See the Profile for Chris Boss     Edit/Delete Message   Reply w/Quote
Jamal,

I didn't say "every window" has a window procedure, but ...

"every window class" has a window procedure !

There is a difference.

If I create a window class called "MyClass32" (using RegisterClass)
a single window procedure would need to be defined.

Once the class exists , I could then create ten different windows
of the same class, and they all use the same window procedure.

Most of the examples of window procedures you may see posted in
this forum, use only one instance of the window so you see only
one window procedure for one window.

If a second window was created using that window class though, it
would not have its own window procedure.

Now Dialog procedures are different. Since the Dialog class reroutes
the window messages to the defined dialog procedure, every dialog can
have its own separate dialog procedure. All the dialogs use the
same window procedure (built in the OS), but that window procedure
will reroute messages to each dialogs dialog procedure.

The dialog class is the only built in window class that does this !

All other window classes (ie. buttons, combobox, listview) have just
one window procedure (built into the OS) which handles all of the
windows of that class. If you had 20 buttons, still only one window
procedure. If you had 100 buttons, still only one window procedure
for the buttons. There is not a window procedure to match each
button.

Knowing this helps one to understand why there is such a thing as
a Dialog procedure using the Dialog window class. The Dialog class
was designed for reuseability of the window class, while still
offer individualization for each instance of the Dialog class
(one dialog procedure per dialog).

As I stated above, the callbacks for controls are simply routines
called by the Dialog engine in DDT to pass them the WM_COMMAND
messages. They are not window procedures ! They are not dialog procedures !

------------------
Chris Boss
Computer Workshop
Developer of "EZGUI"
http://ezgui.com

IP: Logged

All times are EasternTime (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | PowerBASIC BASIC Compilers

Copyright © 1999-2007 PowerBASIC, Inc. All Rights Reserved.


Ultimate Bulletin Board 5.45c