Re: MORE Lyle Blake Info......

From: J French (erewhon_at_nowhere.com)
Date: 08/17/04


Date: Tue, 17 Aug 2004 06:30:58 +0000 (UTC)

On Mon, 16 Aug 2004 17:50:20 -0400, L D Blake <not@any.adr> wrote:

>On Sun, 15 Aug 2004 07:14:32 +0000 (UTC), erewhon@nowhere.com (J French)
>wrote:
>>>A standard progress bar control, subclassed to put in the percentage... a
>>>standard button control to send a message to the parent window to quit.
>>
>>I prefer to paint my own things - and have got that going fine
>>Essentially that is what I have

>If you're looking for "featherweight" (I think you called it) then use the
>standard control and subclass it to add the percentage. I'm not certain right
>off the top of my head but I believe there's even a style that will do it all.

>Painting your own may be fun, but it's really just duplicating what windows
>already does for you. From a performance standpoint it might even make some
>sense to use the flat standard (unsubclassed) version of the progress bar
>control with a static window beside it to show the percentage. Since the
>progress bar will most likely be other than exactly 100 pixels wide you can
>avoid a lot of calculation time this way. You could then update the progress
>bar and static control with simple SendMessage calls.

Yes, I've considered that

>>>>The parent App might even be Console mode (?)
>>>
>>>Yes console mode programs can create windows.
>>
>>It figures - MessageBox is an example

>Correct... but it can't do message dispatching.

>(I may be wrong but I believe this is a Delphi limitation, not a Windows one)

I don't think it is down to Delphi

>>>Why not use the standard windows Progress Bar control?
>>
>>Peversity - I just prefer my own stuff

>[smile] Self defeating ... why duplicate windows functionality?

Sometimes I find it makes sense
- in this case it does not matter much

>>It does, but these DLLs may be called from many languages
>>- or more specifically, they are currently called from many languages

>Hmmm... not the best way to learn this... but...

>To be honest I've not made enough DLLs (3, all drivers) to claim any special
>skill at this at all. (Remember me... the one who avoids such complexities?
>[wink])

I do quite a lot of DLLs for use with both Delphi and other languages,
they are extremely useful - and I find Delphi a very good tool for
writing them.

The ones that I want the Lightweight controls for are DLLs for sorting
large files on disk. I'm simply embarrassed by the footprint, just for
a progress line.

>Now if we're talking units and appys... maybe I have more to offer.

The lightweight controls will be part of the DLL
- in one included Unit

>>>>The thing that I'm really uncertain about is the destruction of the
>>>>Window(s) as the DLL will terminate, but not the main App.
>>
>>>To get everything to quit at once... you will need to use SendMessage to send
>>>a WM_Quit message to the main app's main window.
>>
>>However, under no circumstances do I want the progress Window in the
>>DLL to make the main App quit
>>- although I /do/ want the main App (not mine) to keep alive, and
>>possibly tell the DLL to shut down

>You will want to make this mimic a windows control, then.
 
>(From a coding standpoint, you would probably put multiple controls in a
>single DLL with each control in it's own .PAS unit for the sake of keeping
>things organized.)

>Each control is it's own class within a Dll instance.

>When you load the dll windows calls DllProc which does all your class
>registrations and starts the message dispatcher loop (which will keep the DLL
>loaded)

>Each class in the Dll has it's own wndproc etc.

>You would then create the window itself *from the main appy* using
>createwindow or createwindowex naming your control's class (eg..
>"JProgBarCancel")... just like a windows control.

>Inside the DLL a WM_Create message is sent by windows to the class's wndproc
>to trigger creation of your own child windows inside the one created by the
>appy. (iow... the Parent comes from the appy, the DLL supplies the children)
>This will even let you imbed the control into another window using (wm_child),
>just like any other windows control.

That would be a later development, something I am quite interested in,
but (fortunately) not the current objective

>A WM_Destroy message sent to *the window created in the appy* would ditch the
>control and each child window gets it's own WM_Destroy message from that,
>again, just like a windows control.

Right - so WM_Destroy will zap the window

>It's a little more work than that and I'm sure the SDK does a better job of
>explaining than I will... but that's the jist of it.

>>>There are differences in the way WM_Destroy and WM_Quit work. You will have
>>>to choose between them according to your needs. WM_Quit signals the end of the
>>>application and allows you the chance to close files, save registry settings
>>>etc. WM_Destroy only nukes the window (and it's children) that it's sent to.
>>
>>So if I PostMessage a WM_Destroy to a Window, that will kill it, and
>>remove all traces from memory ?

>Yes... The class registration would remain so you can recreate the window any
>time, unless you completely unload the DLL.

Yes, I've noticed that the class registration stays, I believe it is
for the duration of the parent EXE
- a good point about manually unregistering it, when the DLL is
unloaded - the DLL might be unloaded without the App terminating

>>>>- should I unsubclass the 'progress line' window first
>>
>>>It's good practice, but not needed if the app is shutting down.
>>
>>In my case the App will not be shutting down, just that Window
>
>Then you have your answer [grin]

Well if that Window is zapped then it should not need to be
unsubclassed

>>I think these two example illustrate my dilemma

<snip>

>>
>>==========================================

>Rather than using a completion flag you should look into doing it entirely
>from messages... When you get a WM_destroy, undo your subclass, clean up any
>variables or data that needs saving, send a WM_quit to exit the dispatcher.

>A fully capable message dispatcher need be no more complex than this...
>
>
> While getmessage ...
> if not translateaccelerators.. // handle keyboard
> if not isdialogmessage... // handle menus
> begin
> translatemessage... // make WM_Vkey into WM_Char
> dispatchmessage... // Send to appropriate control
> end;
                                

>WM_Quit causes getmessage to return False, exiting the loop. You don't need
>to flag it or mess with more difficult methods. Just do your cleanup after
>the loop is broken.

So basically when my routine has finished, send a WM_Quit to the
window - makes sense

>I'm guessing you've been looking at the rather complicated dispatcher I posted
>some time back. I wrote this because I wanted a universal dispatcher that I
>could use in multiple places in a single app, with consistent behaviour (as a
>means of keeping things alive during long processes or inside high-repetition
>loops). I went with the APPQuit flag because PeekMessage doesn't respond to
>WM_Quit and the whole thing is wrapped in a subroutine anyway so exiting would
>not quit the app. Using Halt is not an option as this would bypass any
>cleanup needed after the loop exits. So my own usage is somewhat unique and,
>I'm told, rather unlike most WinApi programs.

Actually I think I'm going to run into the same problem, as the
Message Loop routine will need to be called from a number of places in
a long sequential routine
- just as one would call Application.ProcessMessages

That PeekMessage not responding may be tricky, because GetMessage
appears to /wait/ until there is a message in the queue, and I most
certainly don't want (need) that

>Below, as an example is "Hello World" modified to use messaging to create and
>destroy it's own windows. Note that in a DLL the "BEGIN" entry point would
>actually be a DllProc and the entire MakeParentWindow mechanism would be in
>the parent app.

<snip>

Hmm - that is an interesting variation on the earlier version

Of course the Parent App will almost certainly not be one of my own

I can see a little problem with PeekMessage, it only works on a known
HWND and I am pretty sure that GetMessage is 'blocking' if there are
no messages to process

The DLL does not actually know anything about its parents HWND, the
System.MainInstance is actually zero, although the GetMessage loop
keeps the main App alive very nicely as it is thread based.

I think that this might be a little more complicated than I first
thought - a bit of digging inside Delphi is needed to see how they
handle that problem.

Yesterday I got stuck when I had multiple instances of the 'Progress
Window' - but I've some ideas for handling that
GWL_USERDATA looks the provided candidate....

Very interesting stuff this, thanks ...