Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Windows 7 - need more debug

davidgraham
Beginner
2,211 Views
When I run my program within Microsoft Visual Studio it works fine but when I run the compiled version it hangs.
It is difficult to track where the problem is occuring.
I have been opening & writing and closing a text file so I can create a log of where I have been.
I think I have tracked where the problem is occurring, it's in a routine that gets mouse key presses and keyboard characters.
Do you have any suggestions on to how I can add more debugging or run it in a mode where I can get more debug.

The program worked in Windows XP, the problem occurs when running in Windows 7.

Thanks
0 Kudos
30 Replies
davidgraham
Beginner
551 Views
Ian,
Thanks for your comments.
This is program I inhereted from the previous developer and some of the fundimental message handling I don't understand. I have been adding functionality but never tinkered with how the basics work.

Your suggestion on the Get/Translate/Dispatch message loop may be easier to implement. Is there an example somewhere of how it works so I can give it a try?

David
0 Kudos
IanH
Honored Contributor III
551 Views
I don't know of any example. The concept is that you would have another message loop similar to your main loop (around line 177 of Grade.f90) that filtered out messages of interest and passed everything else on. Some sort of trigger (mouse button up, keypress) terminates this second loop and it passes coordinates or whatever back to the calling procedure. As a sketch (this won't compile, it isn't complete, I'm not really sure what your original code was trying to achieve in the first place, etc):

[fortran]    
    LOGICAL :: ok  ! true on success, false on failure
    TYPE(T_MSG) :: msg
    TYPE(T_POINT) :: pt
    INTEGER(BOOL) :: bRet
    INTEGER(LRESULT) :: lRet
    !****
    DO
      bRet = GetMessage(msg, NULL, 0, 0)
      IF (bRet == 0) THEN
        ! Post another copy of the quit message so that our "parent" loop will
        ! also exit.
        bRet = PostMessage(msg%hwnd, msg%message, msg%wParam, msg%lParam)
        ok = .FALSE.
        RETURN
      ELSE IF (bRet < 0) THEN
        ! Some sort of error.
        ok = .FALSE.
        RETURN
      END IF
      
      bRet = TranslateMessage(msg)
      
      IF (msg%hwnd /= hWndMain) THEN
        lRet = DispatchMessage(msg)
      ELSE
        ! Filter out messages of interest, process them specially, pass
        ! everything else on.
        SELECT CASE(msg%message)
        CASE (WM_CHAR)
          SELECT CASE(wParam) ! Character code
          CASE (VK_ESC)
            ok = .FALSE.
            RETURN
          CASE (...other keys of interest...)
            ....
         CASE DEFAULT
            ! Ignore keypress
          END SELECT
        CASE (WM_MOUSEMOVE)
          ...draw cursor?...
        CASE (WM_LBUTTONUP)
          ...set x, y, ok = .TRUE. return?
        CASE (other messages of interest)
          ...
        CASE DEFAULT ! mesage that we dont want special processing of...
          lRet = DispatchMessage(msg)
        END SELECT
      END IF
    END DO
[/fortran]
(Your MainWndProc should be marked RECURSIVE too).
0 Kudos
davidgraham
Beginner
551 Views
Ian,
Thanks for that code sample. I think I have got is working now on the 'cut down version'. I have to move onto another project for a week. I will then hope get it working in the full version.
It looks as if the peekmessage was causing the problem.
Thanks again.
David
0 Kudos
davidgraham
Beginner
551 Views
I have tried updating my full project and found there is a problem. This problem also occurs on the cut down project - I hadn't realised as the data was just small.
The grapics lines are only being drawn on the screen when you move the mouser around. If you keep the mouse still the screen is blank but as soon as I move my mouse it starts to draw, the more I move the mouse more is drawn.
Can you suggest where the problem occurs.
I could submit the updated code.

Thanks.
0 Kudos
IanH
Honored Contributor III
551 Views
I suspect that there's a problem with the window invalidation/repainting logic. There are a couple of ways of setting things up and I don't know what your application implements.

(One that is typical is that all drawing on the window is only ever done in response to a WM_PAINT message. When events happen (such as mouse movement) that require a change in the window's visuals, the code handling those events invalidates the areas that require updating. The actual drawing happens "later" in response to the paint message (though "later" might be right away if UpdateWindow is called by the event handling procedure. Perhaps your application does something different - whatever it is you need to be able to describe it in a similar manner.)

If you post the code I'll have a look, but this is more to do with the Window's api than Intel Fortran per-se.
0 Kudos
davidgraham
Beginner
551 Views
Ian,
Thanks for your help.
Here is the project and the data. It is similar to that before.
Unzip both files. Use File Open to open the file 'Example.gbf'. The full graphics is drawn (see example.jpg). If you use the wheel mouse to zoom in or out, the graphics disappears. As you move the mouse around the graphics is drawn bit by bit.
Thanks again.
David
0 Kudos
davidgraham
Beginner
551 Views
Ian,
Have you been able to look at my project?
I am stuck, do you have any suggestions on where I could get further help?
Thanks,
David
0 Kudos
IanH
Honored Contributor III
551 Views
I had a look when you first posted it and couldn't work out then what was going wrong. My notes from then:

  • This code is very difficult to follow. There are cryptic variable and procedure names, a large number of global variables, a limited number of comments and too much use of unstructured execution control (goto, etc - I also think I stumbled on a computed goto at one stage, but then my head compiler ICE'd). By being difficult to follow this code would be a nightmare to maintain and difficult to debug. The code would benefit greatly from a progressive rewrite (or perhaps a total rewrite) using language features introduced with Fortran 90 and beyond.
  • The application isn't calling BeginPaint/EndPaint in response to WM_PAINT messages. These API's are what Windows uses to keep track of the update region for each window, amongst other things. The application should never send WM_PAINT messages, that's a job for the system (areas that need re-painting should be invalidated - the system will then arrange for WM_PAINT to turn up in the message queue). The whole way the application handes painting is a bit bizarre - perhaps this was some way that painting could appear to be being done in the background???
  • The main window message procedure needs to be recursive - many API calls result in messages being sent to the window (and hence you get an immediate call of the window proc if it is a single threaded application).
  • There are code paths through the window procedure that never set the return value of the function. The return value is significant for some messages and that significance can change from windows version to version.
  • There is the potential for a GDI resource leak in a few places - handles being destroyed before being selected out of a DC, etc.
I looked at the code again this morning and I now can see a problem - there is a subsidiary message loop/filter that was discussed a few posts previous in subroutine CHKCH (API.f90 line 348 on) that hasn't been implemented correctly - there's no filtering and subsequent processing of messages going on! I don't follow what the program is trying to do here (why check for a keyboard press in the middle of drawing the screen?).

Previously the subsidiary message loop/filter was discussed in the context of the application entering a selection mode - this is a quite a different context!

If the idea is to allow the user to cancel the drawing then you need to go back to the PeekMessage approach (there's no loop - just look for WM_KEYDOWN for that window alone), but if your window's client area is that complicated that the user actually has time to reach over and hit a key to cancel the drawing then your whole approach to drawing needs to be re-thought.

Anyway, a message sent to any window owned by the thread other than the main terminates this loop (there's a return on line 350), and if the message is sent to the main window then the wparam parameter appears to be interpreted as a keyboard character regardless of the type of message and every message is processed in the same way (there's no "select case (msg%message)" bit to actually filter out messages of interest, there's no handling of paint messages, no default message processing, nada).

I don't know what is supposed to be happening here (I think that's your first job - document in comments in the code what the code is trying to do (and "why" it is the way it is too)) - so I won't try and "correct" things, but...

Typically, an application responding to the scroll wheel on a mouse would determine a new scale factor for the display (if "zooming" is what the mouse wheel does in the app) and then just invalidate the relevant part of the client area of the window (often zooming requires the entire area to be redrawn). That's it.

When it feels like it (which with modern CPU's and graphics cards, etc, will be before the user's brain has realised that it has finished moving the scroll wheel) the system then sends the window procedure a WM_PAINT message for the invalidated area, and all drawing is handled there.

That pattern typically applies to every event that might require the screen to be changed - the code handling the event works out what part of the screen needs to be redrawn, invalidates it and WM_PAINT handling then does the actual drawing. Exceptions to this pattern exist (often as useful optimisations when specific parts of the screen are being updated constantly), but they require careful consideration and design.
0 Kudos
davidgraham
Beginner
551 Views
Ian,
Thanks for looking at my problem. I agree it is not good programing, it was writtem about 15 years ago by a previous employee who I thought did a good job getting the windows user interface to work. As you say it's difficult to understand and I don't understand all about how it work - but it has been working and am reluctant to change fundimental parts of the software.
I have now made a few changes to the lines you suggested but am still having trouble with the graphics being drawn - I will investigate it more.

Looking back at my original problem I found http://msdn.microsoft.com/en-us/library/dd744765%28v=vs.85%29.aspx 'Preventing Hangs in Window Applications'. My hang doesn't occur when doing a long process but it gives the same effect. The solution is generally to write better code which I expect is the same as your suggestion to replace the PeekMessage statements.

David
0 Kudos
davidgraham
Beginner
551 Views
Thanks to all those that helped with this problem - especially Ian & Steve.

I eventually got the solution - I just needed to add one line of code.
The PeekMessage commands I was using causes the message buffer to get filled and the computer cannot process them all so Window7/Vista thinks the computer has hung.

The solution is to add an other PeekMessage to flush the buffer.

bret=PeekMessage (msg,NULL,0,0,PM_NOREMOVE) ! flush messages or it thinks it has hung.

David
0 Kudos
Reply