dmurdoch@watstat.waterloo.edu (Duncan Murdoch) (05/16/91)
I'm porting a DOS program to Windows (using TP for Windows), and am having trouble getting it to be civilized. It has some long loops where it occasionally writes to one window; the original never gives up control, so in Windows everything else comes to a halt until it's done. I'm trying to civilize it by putting occasional calls to Yield into the loop, but it's ignoring mouse events.. If other windows have been invalidated, the Yield works, they get redrawn, and mouse actions get processed. However, if all other windows are idle, the Yield doesn't seem to do anything, even if I've clicked the mouse outside the current application. Is there some way to configure what sort of behaviour Yield has? It's not even mentioned in Petzold, and the TPW documentation is minimal. I don't have the SDK manual. Duncan Murdoch
ebergman@isis.cs.du.edu (Eric Bergman-Terrell) (05/16/91)
About Yield(): "This function halts the current task and starts any waiting task... Applications that contain windows should use a DispatchMessage, PeekMessage, or TranslateMessage loop rather than calling the Yield function directly. The PeekMessage loop handles message synchronization properly and yeilds at the appropraite times". Prog. Ref., 4-469 BTW consider getting the Prog. Ref. at a bookstore. IMHO it's worth the money. Terrell
press@venice.SEDD.TRW.COM (Barry Press) (05/16/91)
In article <1991May16.121553.3876@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes: > >I'm porting a DOS program to Windows (using TP for Windows), and am having >trouble getting it to be civilized. It has some long loops where it >occasionally writes to one window; the original never gives up control, >so in Windows everything else comes to a halt until it's done. > >I'm trying to civilize it by putting occasional calls to Yield into the >loop, but it's ignoring mouse events.. If other windows have One of your problems may be that while Yield lets other programs process messages, it doesn't let YOUR program do so. The problem this presents is this: Assume your program has the focus. When some other program is to get the focus, you get sent a message (WM_KILLFOCUS, WM_FOCUS, WM_SETFOCUS, or something along those lines) that tells you you're losing it. If I recall correctly, the other program won't get the focus (and, therefore, process user input) until you process this message. One way to fix this is to put a call not to Yield, but to Peek Message in your loop, where the PeekMessage parameters are set to restrict things to the focus change message. -- Barry Press Internet: press@venice.sedd.trw.com
srw@cci632.cci.com (Steve Windsor) (05/17/91)
In article <1991May16.121553.3876@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes: > >Is there some way to configure what sort of behaviour Yield has? It's not >even mentioned in Petzold, and the TPW documentation is minimal. I don't >have the SDK manual. > >Duncan Murdoch Windows 3.0 is a non-preemptive multitasker. As such, when a process has control, no one else can gain access to the processor. This is why windows is messaged-based, to process a message and then get out, allowing the scheduler to service another process. Yield() is supposed to relenquish the processor inside a process. However, it does not work. This comes straight from Paul Yao in an Advanced Windows class, Microsoft University. In testing, Yield() does not appear to do a damn thing... Instead, look at PeekMessage(). If there is a message waiting in the process queue, you can service that message. If there is no message waiting to be serviced, you can relenquish control...the code is an if (PeekMessage(...))...else construct. I even think it's mentioned in Petzold. I can email you the sample if you wish. stephen windsor srw@op632.cci.com
dmurdoch@watstat.waterloo.edu (Duncan Murdoch) (05/17/91)
In article <1095@venice.SEDD.TRW.COM> press@venice.sedd.trw.com (Barry Press) writes: >In article <1991May16.121553.3876@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes: >> >>I'm trying to civilize it by putting occasional calls to Yield into the >>loop, but it's ignoring mouse events.. If other windows have > >One of your problems may be that while Yield lets other programs process >messages, it doesn't let YOUR program do so. > >The problem this presents is this: Assume your program has the focus. >When some other program is to get the focus, you get sent a message >(WM_KILLFOCUS, WM_FOCUS, WM_SETFOCUS, or something along those lines) >that tells you you're losing it. Thanks for the help (and thanks to Terrell for the SDK manual quote). Yes, that looks like what's happening. What I've done, which seems to work, is to write my own Yield that does one cycle through a standard message processing loop: procedure yield; var msg : TMsg; begin if Getmessage(msg,0,0,0) then begin Translatemessage(msg); Dispatchmessage(msg); end; end; As long as I call this frequently enough, things are fine. (I have a window procedure that handles all the focus messages by passing them on to the default handler.) Duncan Murdoch
jciccare@adobe.COM (John Ciccarelli) (05/17/91)
In article <1991May16.121553.3876@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes: > I'm porting a DOS program to Windows [which] has some long loops where it > occasionally writes to one window... so everything else comes to a > halt.... I'm trying to civilize it by putting occasional calls to Yield... Don't use Yield. The docs say Yield isn't for windowed apps. Use PeekMessage instead. The basic idea is: while ( something that takes a long time ) { <one iteration of stuff that takes a long time> MyYield(); } /* end while */ /* "Yield to other apps" function */ void MyYield() { while ( PeekMessage( lpMsg, hWndApp, 0, 0, PM_NOREMOVE ) ) { ProcessMessage( lpMsg ); /* Get/Translate/Dispatch logic of WinMain */ } /* end while */ } /* end function */ Your ProcessMessage function should contain the Get/Translate/Dispatch body of your WinMain message loop. WinMain's message loop and MyYield's while loop both call it, guaranteeing that messages always get processed the same way. Since the GetMessage contained in ProcessMessage will remove the message, PeekMessage is called with PM_NOREMOVE. Even if there are no messages in the queue, PeekMessage will allow other apps to run, which is what you want. The interface to ProcessMessage must handle the WM_QUIT properly, of course. /John -- John Ciccarelli (jciccare@adobe.com, {sun|decwrl}!adobe!jciccare, 415-962-6677) Adobe Systems, 1585 Charleston Road, Mountain View, California USA 94039-7900
press@venice.SEDD.TRW.COM (Barry Press) (05/17/91)
In article <1991May16.190243.27809@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes: > ... >begin > if Getmessage(msg,0,0,0) then > begin > Translatemessage(msg); > Dispatchmessage(msg); > end; >end; > >As long as I call this frequently enough, things are fine. (I have a Unless I misunderstand what you've done, you're processing any and all messages here. What this implies is that you've got this loop that runs, effectively, as a background process WHILE ALL FUNCTIONS OF YOUR PROGRAM ARE OPERATIONAL AND ACCESSIBLE TO USERS -- i.e., you can (recursively) call any function within your software. Did you really intend that? What you desribed led me to believe that you just wanted to let other Windows programs (not yours) run while you finished this loop. I concluded that your program itself was "busy" during that time. If that's really what you wanted, then you'd best not allow any message at all, just the ones related to focus. -- Barry Press Internet: press@venice.sedd.trw.com
press@venice.SEDD.TRW.COM (Barry Press) (05/17/91)
Also, the loop you put in yield should contain PeekMessage, should it not? -- Barry Press Internet: press@venice.sedd.trw.com
ebergman@isis.cs.du.edu (Eric Bergman-Terrell) (05/17/91)
Rather than processing only one entry in the message queue, you might want to "empty it out" and process them all. Can't say what difference that it would make, but it might make switching to another program happen faster. Just change your "if" to a while, and your "then" to a do... General question: How is programming Windows in T. Pascal? What's easier than using C? What's more difficult? How do you get statically bound variables? Terrell
dmurdoch@watstat.waterloo.edu (Duncan Murdoch) (05/17/91)
In article <1097@venice.SEDD.TRW.COM> press@venice.sedd.trw.com (Barry Press) writes: >In article <1991May16.190243.27809@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes: >> ... >>begin >> if Getmessage(msg,0,0,0) then >> begin >> Translatemessage(msg); >> Dispatchmessage(msg); >> end; >>end; >> >>As long as I call this frequently enough, things are fine. (I have a > >Unless I misunderstand what you've done, you're processing any and all >messages here. > >What this implies is that you've got this loop that runs, effectively, as >a background process WHILE ALL FUNCTIONS OF YOUR PROGRAM ARE OPERATIONAL >AND ACCESSIBLE TO USERS -- i.e., you can (recursively) call any function >within your software. > >Did you really intend that? What you desribed led me to believe that >you just wanted to let other Windows programs (not yours) run while >you finished this loop. I concluded that your program itself was "busy" >during that time. If that's really what you wanted, then you'd best not >allow any message at all, just the ones related to focus. First of all, further testing showed that I really needed a Peekmessage loop, not a single Getmessage call. The current version of my Yield function has first line while Peekmessage(msg,0,0,0,pm_remove) do and works better than the above. (I'm new at Windows programming. Or could you tell that already? :-). That one happened to work because I always had a paint message waiting. As to whether it does what I want or not: I'll have to give more background. As a first project in TPW, I decided to port a little DOS program I've got that just does a scatterplot of data read from a file. It was written in TP, and used the BGI graphics there. Since TPW doesn't come with anything remotely resembling the BGI Graph unit that my program used, and it was written using a toolkit that relied on BGI, I decided to get ambitious and write a Graph unit replacement. Ideally it would just be a drop in replacement to let DOS graphics programs run under Windows and produce nicer output that could be resized, moved, etc. The way BGI graphics works is quite a bit different from Windows GDI. For one thing, it expects to own the output device exclusively, and to be able to paint an image a little bit at a time. Since the programs that call it also think they're single-tasking, they'll never voluntarily give up time slices: hence the need for some sort of Yield function, which I decided to put in the graphics output routines, hoping that they'd be called often enough for it to work. (The scatterplot application satisfies this: it does almost nothing but build the image.) Since the programs that are going to be using this are warmed over DOS programs rather than Windows programs, they don't really need to know anything about events coming in, other than the command to close the window, which halts the program. Thus it's fine to process any and all messages that come along: in fact it's necessary to process more than just messages about the focus, because I want the output window to be resizable. One outstanding problem: I'd love to use a metafile to save the graphics commands (right now I'm maintaining my own list of them, and running into trouble when there are too many of them). The problem is that it doesn't seem possible to write some stuff to a metafile, play it to the screen, and reopen it to write some more. Am I missing something? Duncan Murdoch dmurdoch@watstat.waterloo.edu
ronb@burklabs (Ron Burk ) (05/21/91)
ebergman@isis.cs.du.edu (Eric Bergman-Terrell) writes: > General question: How is programming Windows in T. Pascal? What's easier > than using C? What's more difficult? How do you get statically bound > variables? Having just written the same program in TPW, C++, and C, I can give my preliminary opinion. I prefer the TPW development environment to any of my C/C++ compilers because it is a fast and it is a real Windows app (no shelling to DOS). The debugger is still character-mode, however. TPW gives me more compile-time checking than C, but (surprisingly) less than C++. There are several object-oriented-related things that C++ detects at compile time, whereas TPW detects it only at runtime. For example, you make a TPW class "abstract" (in the C++ sense) by defining a virtual func that calls the proc "Abstract". Unfortunately, that just causes a runtime error if the user fails to replace the virtual func. In C++, of course, the compiler detects attempts to instantiate a virtual class. Other than the standard complaints when switching to Pascal from C (no break/return statements, etc.), the main hassle for my 1000-line program was null-terminated strings. TPW adds some functions for switching between C-style strings and Pascal-style strings, but converting back and forth is a pain. Windows, of course, wants null- terminated strings. I guess another hassle was the way constructors and destructors work in TPW. You have to call the dang things explicitly! First you declare (or allocate) a variable, then call it's constructor. If you forget to call the constructor, well, you must've had some good reason to not want it initialized. A more inconvenient example occurs with inheritance. Suppose I want to inherit from a TPW class called TWindow and override it's constructor (assume TWindow has a constructor that you pass a string containing the window title): type MyWindow = object(TWindow) constructor Init(Title:AString); {...} end; Well, if you want the TWindow constructor to still get called, you have to remember to do it yourself, like this: constructor MyWindow.Init(Title:AString); begin TWindow.Init( AString ); { my added initialization } end; It is also possible to end up with a constructor that assigns the parent's virtual function table to the object by mistake. This took me several hours to track down. Of course, once you learn where the major pitfalls are in a language, you avoid them without thinking. C++ has it's problems, too, but it does catch more problems at compile-time than TPW does, in my opinion. I'm not sure what you mean by "statically bound variables". The TPW combination of units and objects gives you the most-used facilities of C++ classes. For example, the static data members of my C++ class became global variables in the implementation of the unit containing the corresponding TPW object. Pretty much the same effect (only functions in the unit's implementation can access them). C++ still has finer-grain facilities than any OO language I know of. In TPW you get private or public object members, no protected. Inheritance is public, no other options. I was pleasantly surprised by TPW. > > Terrell