talwyn has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to write a program utilizing win32::Gui.At one point I Psuedocoded the following:
tfTapeName_Click (Type:Event){ Read text from textfield_Tapename; QueryDB (Tapename) If Tapename isn't in the Database then GetMFGDate() from user ELSE Tapename Is in Database Get MFGDATE() from QueryDB(Tapename) If MFGDATE too old then GetMFGDATE() from user until user acknowledges over-ride or enters a good MFGDATE GetDestination() from Textfield_Destination Until Destination is entered and is valid per TapePolicy GetDestination() from User Write Tapename, MFGDATE, Destination, Current time and date to Listview_Entered_Data. }
So I went my merry way to implement this and started setting up a dialog box and then realized 'hey, wait a sec how do I write a function that handles an event but is called? I looked through the Win32::Gui examples but I didn't see anything.

The goal here is

$somevariable = Dialogx();

Where Dialogx()creates a new dialog window asking for the relevant information and then returns the information heretofore placed in the dialog's textfield and transmitted by its ok button. The problem being that all user input is interpreted through events that occur outside the the sub and not neatly available like $somevariable = <STDIN> is. Can I do this with win32::gui? I could only think of how to do this if I used global variables and took that as a sign I may be off course here. Is there a better approach? I think I am getting hung up on my procedural based experience and maybe not seeing how to write this properly.

Pointers to relevant reference material, tips, code, examples eagerly sought.

Thanks, Talwyn

  • Comment on win32::Gui -- Paradigm problem...How do you get info back from a dialog?
  • Download Code

Replies are listed 'Best First'.
Re: win32::Gui -- Paradigm problem...How do you get info back from a dialog?
by BrowserUk (Patriarch) on Jul 05, 2002 at 04:20 UTC

    Talwyn,

    I am not sure if this will help any and I haven't had much luck in understanding the Win32:GUI docs on the matter either, but in the absence of any other reply it might help.

    In the underlying api's communication between the dialog proc and the calling program is through so-called "window words". When the Dialog is created a number of "extra" window words (32-bit values if I remember correctly) are requested. Inside the dialog procedure, these values can be modified. Once the call to ShowDlg() or its variants return, the main window proc can then access these window words to retrieve the "answers" from the dialog. Often, a single 'extra' 32-bit word is requested, and a pointer to a data structure allocated in the main proc is placed in there before calling. The dialog proc reteives the pointer, fills in the values accordingly. Once the ShowDlg returns, the main proc can use the pointer to retreive the information.

    How faithful the Win32::GUI is to the method of working I can only speculate, but the description (which shouldn't be relied upon for accuracy. Its been a while!) may help you understand the docs and what is going on.

    Good luck.

    Update:After I submitted, I went to check something and came across this which you have probably seen and isn't very helpful as it refers you to the 'underlying API docs', but the Get/SetWindowLong() calls are the ones you need. You'll see from the calls you can have multiple, indexed WindowLongs. It also strikes me that if your main window proc and the dialog proc (or its controls callbacks) are in the same file, the Perlish way maybe to simply use package globals for this.

      BrowserUk,

      there is a difficult in what you say here: Win32::GUI itself makes heavy usage of that "extra" window words for its own business. they're used to store pointers to Perl callbacks, window properties that are not directly related to the underlying API (eg. which event model to use), and lot of other stuff that just makes Win32::GUI works. so it's not advisable at all to use Get/SetWindowLong() unless you have a very, very deep knowledge of the module's guts.

      the functions are there because I think if someone wants to hack deeply, he should be able to do it. but they're not for everyone (or "for the faint of heart", as they say :-). this should've been made clearer in the docs, but you all know what a mess the docs are at this point, don't you?

      so I would suggest to talwyn: go the Perlish way, store the results somewhere in Perl (one global hash would be my best bet).

      cheers,
      Aldo

      __END__ $_=q,just perl,,s, , another ,,s,$, hacker,,print;

        Makes sense Aldo, glad you where around to intervene before I sent Talwyn on a short-wavelength visible-light Clupea Pallasii pursuit.

        As a minor suggestion if you ever get around to re-writing any of the code:

        With the Get/SetWindowLong() calls you could inspect the index parameter and adjust it internally to allow users to add their own window words without colliding with yours. Say for example you are using 10 words internally, you could add ten to the user supplied index on the way through to calling the native API's and if anyone needs to access YOUR window words, they could use the negative offset convention in the same way as these are used by the underlying API's for their internal stuff.

        In that way, you still provide access to the full API but protect your internals from fools like me:)

        Hey Aldo,

        I tried the Global hash approach and it works ...sort of...

        I think I need some pointers on how to tune DoEvents(). When I entered data in the dialog box I got ~880 key repetitions. I was able to get those 880 letters back to the originating function though... so I'm making progress.

        Snippet Follows

        #Events----------------------------------------------- sub ::Dialog1_Terminate { defined(my $win = $Win32::GUI::Loft::window{winMain}) or return(1); print_dbg(" I am now enabling the window!"); $win->Enable(); return(1); } sub ::btnDialog1_Click{ defined(my $win = $Win32::GUI::Loft::window{Dialog1}) or return(1); our %MSG = %main::MSG; my $text = $win->tfDialog1->Text(); $MSG{"Dialogue"}{"Text"}= $text; return -1; } #App---------------------------------------------- sub GetDestination{ #( $combobox ) #This function returns the drive library or other Destination #Selected in the Combobox object passed to it. my $combobox = shift; local %::MSG = %main::MSG; defined(my $win = $Win32::GUI::Loft::window{winMain}) or return(1); #Ensure $combobox is infact a combobox object abort if not. unless ( "ComboBox" eq $combobox->GetClassName() ){ print_dbg ($combobox->GetClassName()); die "REcieved a bad object!"; } my $destination = $combobox->Text(); print_dbg ("Selected:".$destination); $destination =~s/\s//; if ($destination eq ''){ print_dbg ("No Destination!"); $win->Disable(); # disable main window until we get info we ne +ed. my $dlg = configure_window ('dialog.gld'); $dlg = build_window($dlg, "Dialog1"); $dlg->lblPrompt->Text( "You must enter a destination. \n". 'Type one in the box below.'); $dlg->Show(); do{ Win32::GUI::DoEvents(); } until ($::MSG{"Dialogue"}{"Text"} ne ''); print_dbg ("The user entered: ".$::MSG{"Dialogue"}{"Text"}); } print_dbg ("I AM A STUB FIX ME!"); return ($destination); }
Re: win32::Gui -- Paradigm problem...How do you get info back from a dialog?
by fglock (Vicar) on Jul 05, 2002 at 13:42 UTC
      Pretty cool links to my own posts :) Thanks though :)

      Talwyn