Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs have moved to the Altera Community. Existing Intel Community members can sign in with their current credentials.

Statusbar in IVF

marshallc
Beginner
1,610 Views
Has anyone created a customized statusbar in Compaq Visual Fortran (CVF) and migrated it "successfully" to Intel Visual Fortran (IVF)? At first, I thought it was a definition program considering I was getting warning that some of the variables were not set correctly, but this has been fixed. There has to be something else that is causing the statusbar to not work in IVF when it worked great in CVF. I'm attaching a snippet of code from the MainWndProc. If anyone has any ideas, please let me know. Thanks!
Code:
    integer(SINT)    iret
    character(30)    szStatusText
    integer(SINT)    iSBheight
    integer(SINT)    cxClient, cyClient
    integer(SINT)    x, y
    integer(SINT)    ihWndstatus
    integer(SINT)    iParts
    integer(SINT)    cxWidth, iStep, i
    character(SIZEOFAPPNAME)  lpszName, lpszHelpFileName, lpszContents, lpszMessage
    character(SIZEOFAPPNAME)  lpszHeader

    integer(BOOL) :: redraw = TRUE
    integer(SINT), dimension(0:3) :: lpParts
    type (T_RECT) RectStatus
    type (T_RECT) rcClient

    select case ( mesg )

      case (WM_CREATE)
        ihWndstatus = CreateStatusWindow (IOR(WS_CHILD, &
          WS_VISIBLE), " "C, hWnd, IDC_StatusBar)
        
        iParts = 3
        MainWndProc = 0

      return
      
      case (WM_SIZE)
	      
        cxClient = loword(lParam)
	    cyClient = hiword(lParam) 
		    
        iret = GetWindowRect(ihWndStatus,RectStatus)
		iSBheight = Abs(RectStatus%bottom-RectStatus%top)
		iret = GetClientRect(hWnd,rcClient)
		cxWidth = rcClient%right/iParts
		iStep = cxWidth
		    
        do i = 0,iParts-1
            lpParts(i) = cxWidth
		    cxWidth = cxWidth + iStep
		end do
        
        iret = SendMessage(ihWndStatus, SB_SETPARTS, iParts,&
		      loc(lpParts))    
		         
        iret = MoveWindow(ihWndStatus ,0,cyClient-iSBheight,&
		      cxClient,cyClient,redraw)        
		    
        szStatusText ='Popout 		Style'C
		    
        iret = SendMessage(ihWndStatus, SB_SETTEXTA,&
		      ior(1,SBT_POPOUT), loc(szStatusText))

        iret = SendMessage(ihWndStatus, SB_SETTEXTA,1, &
		      loc(szStatusText))

		    
        szStatusText =' Ready'C
		    
        iret = SendMessage(ihWndStatus, SB_SETTEXTA,0, &
		      loc(szStatusText))
        
      return

    ! WM_DESTROY: PostQuitMessage() is called 
      case (WM_DESTROY)
          call PostQuitMessage( 0 )
          MainWndProc = 0
          return


0 Kudos
12 Replies
Paul_Curtis
Valued Contributor I
1,610 Views
Here is an example of a status bar being created, as a child window to the program's main window:
        ! Register the status window class
        wc%lpszClassName	= LOC(statusWndClassName)
        wc%lpfnWndProc	= LOC(StatusWndProc)
        wc%style		= IOR(CS_OWNDC, IOR(CS_HREDRAW, CS_VREDRAW))
        wc%hInstance		= ghInstance
        wc%hIcon		= NULL
        wc%hCursor		= LoadCursor(NULL, IDC_ARROW)
        wc%hbrBackground	= COLOR_BTNFACE + 1
        wc%lpszMenuName	= 0
        wc%cbClsExtra	= 0
        wc%cbWndExtra	= 4
        IF (RegisterClass(wc) == 0) THEN
		CALL winclass_error (statusWndClassName)
            PVWindowCreate = .FALSE.
            RETURN
        END IF
        
        hwndStatus = CreateWindow (statusWndClassName, "", &
            IOR(WS_CHILD, IOR(WS_VISIBLE, WS_CLIPCHILDREN)), &
             30, 30, 60, 60, ghwndMain, 0, ghInstance, 0)

This window has its own Proc function, which only contains code to redraw a set of child windows which are on top of the status bar (ie, a clock display, various buttons, status markers, etc.)

Once created, the status window is drawn along the bottom of the main window, which fills the screen; the Windows status bar has previously been disabled & hidden:

   ! Resize the status bar to occupy the bottom of the main window.
   rval = SetWindowPos (hwndStatus, NULL, 0, parentHeight - swHeight,	&
	  	           parentWidth, swHeight, SWP_NOZORDER)


HTH

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,610 Views
Basically, you're missing SAVE attribute for ihWndStatus and iParts (and maybe a few more, but these were crucial). AFAICT, IVF 9 does not save variables by default anymore (although I admit I didn't check the release notes :-) ).

Side tip: To force status bar to redraw itself, you can simply forward the WM_SIZE message to the ihWndStatus (MoveWindow(0,0,0,0) will also do). Status bars and toolbars "automagically" adjust themselves to the "right" place because they override WM_WINDOWPOSCHANGING, just have to be "reminded" to do so. In other words, they ignore any position you want to set using MoveWindow/SetWindowPos and place themselves in the bottom (top) of the parent's client area, unless they have an appropriate style (CCS_something, see "Common Control Styles".)


Xeffort library can handle this stuff far more elegantly; see e.g. XZoom sample (just fix the obvious error -- I didn't update it yet to be compatible with IVF9 either :-)).


Jugoslav
0 Kudos
marshallc
Beginner
1,610 Views

Hi Guys,

Thanks for the responses. Yugoslav, I had to do some research on what you meant by the SAVE attribute. I confess I have never used it before, but I think this is what you were talking about:

Code:

integer(4), SAVE :: ihWndstatus
integer(4), SAVE :: iParts


I'm not sure if that was right, but I rebuilt the code, and the statusbar hasn't changed. When I was in CVF, the statusbar would be nicely divided into 3 parts, and I had one part of the status bar showing the X and Y coordinates. Also when I minimized or maximized the window, the status bar would resize with it. For whatever reason, the same program in IVF does not work that way.

Paul-Curtis, I'm looking at what you wrote and trying to figure out how to put that into my code. I have some ideas. CVF's wizardcreated the base code that I'm using. There is a section that looks like itcreates the main window:

Code:

    if (hPrevInstance .eq. 0) then
        !  Main window
         wc%lpszClassName = LOC(lpszClassName)
         wc%lpfnWndProc = LOC(MainWndProc)
         wc%style = IOR(CS_VREDRAW , CS_HREDRAW)
         wc%hInstance = hInstance
         wc%hIcon = LoadIcon( hInstance, LOC(lpszIconName))
         wc%hCursor = LoadCursor( NULL, IDC_ARROW )
         wc%hbrBackground = ( COLOR_WINDOW+2 )
         wc%lpszMenuName = NULL
         wc%cbClsExtra = 0
         wc%cbWndExtra = 0
         if (RegisterClass(wc) == 0) goto 99999
    end if


This is in WinMain. I can place the first part of what you wrote in WinMain. The section part starting with "hwndStatus" could go into case (WM_CREATE), and the third part starting with "rval =" could go into case (WM_SIZE). Does this sound right?

Sorry, I'm a newbie. In fact, I created a new post with respect to that.

I know someone might say why do I need a status bar or can you do without it. Answer, because the customer wants it. It's a little frustrating for me, because it feels like I'm missing some critical info in all this... kind of like that missing piece in a puzzle that you try like crazy to find :)

Thanks for all the help!

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,610 Views
Marshallc,

I pasted your exact code in an AppWizard-generated application, and added missing bits & pieces. I debugged it and I saw that ihWndStatus and iParts lose they value due to lack of SAVE attribute, and after I added them it worked (and still works) just fine.

If it helps, I attached the complete solution.

Maybe there are some undefined variables lurking around that I don't see and that could cause the difference. Does the attached code work for you?

Jugoslav
0 Kudos
jim_dempsey
Beginner
1,610 Views

Might your problem be cleverly hidden in the interpretation of BOOL? From MSDN

In Visual C++4.2, the Standard C++ header files contained a typedef that equated bool with int. In Visual C++ 5.0 and later, bool is implemented as a built-in type with a size of 1 byte. That means that for Visual C++ 4.2, a call of sizeof(bool) yields 4, while in Visual C++ 5.0 and later, the same call yields 1. This can cause memory corruption problems if you have defined structure members of type bool in Visual C++ 4.2 and are mixing object files (OBJ) and/or DLLs built with the 4.2 and 5.0 or later compilers.

Also, on a different thread in this forum see Steve Lionel's comment on bool/LOGICAL
You gave no indication of which call errored out.
Jim Dempsey
0 Kudos
marshallc
Beginner
1,610 Views

OK... this is going to sound really strange. I looked at the code the Jugoslav provided (thank you) and compared it to mine. They were basically identical. I did notice that in my header files that there was some duplication in the reference numbers. After I fixed this, it still didn't resolve the problem. I kept looking and looking, but I couldn't find anything wrong. The other strange thing I noticed was that the cursor would jump around on the lines and the watches would show some really strange numbers when I was stepping through in debug mode.

I decided to look at the properties of the project (or I guess it's called a solution in IVF). There were a couple differences between the properties of my solution and the properties of Jugoslav. The biggest one is the external dependencies property under Fortran that handles calling conventions. Mine was set to CVF. Jugoslav's was set to Default. I changed mine and clicked on apply. Now, it is working fine. I went back into properties and clicked on CVF to see if this is what caused it. My application still worked. I haven't a clue as to what was happening.

Thanks for the help! The status bar is working great!

Message Edited by marshallc on 10-21-2005 11:55 AM

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,610 Views
For a correct program, the calling convention shouldn't matter (except where it does :-), but this shouldn't be one of the cases). For example, missing save attribute was a flaw from the start, but it just happened to work as expected on CVF; maybe there still are some similar subtle flaws.

If you still have the original source/solution where it failed, I'd appreciate if you could attach it so I could take a look; maybe there still are some hidden bugs which could cause problems in the future. If not, well, we'll put it in "don't fix if ain't broken" or "we will never find out what happened" drawer :-).

Jugoslav

Message Edited by JugoslavDujic on 10-24-2005 10:27 AM

0 Kudos
jim_dempsey
Beginner
1,610 Views
RE: missing save attribute was a flaw from the start
The missingSAVE attribute will bite you at times (e.g. Statusbar)as well as
The implicit SAVE attribute whereby local vars are on stack but local arrays are placed into one instance in name mangled space off stack. The implicit SAVE bites when you expect (require) separate instances. e.g. subroutine called from multiple threads. Implicit SAVE should produce a compiler warning excepting when preceeded by !DEC$ or by compiler switch (who's default is to issue warning).
Jim Dempsey
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,610 Views
For reentrant code, one should use RECURSIVE for the start. However, that's not a panacea, merely a prerequisite.

Although I am careful about it, I've been bitten by "implicit save" in another manner, by implicit inheritance. Challenge: spot the error:
!======================
subroutine host()

implicit none

integer:: i

...
call mvCount(...
!======================
contains
!======================
recursive subroutine mvCount(iNode, nCount)
use somemodules

integer, intent(in):: iNode
integer, intent(out):: nCount
!some declarations of locals
...
nCount = nCount+1
do i = iCum(iNode), iCum(iNode+1)-1
someNode = ...
if (somecondition)
call mvCount(someNode, nCount)
end if
end do

end subroutine mvCount
end subroutine host
!======================
Jugoslav
0 Kudos
jim_dempsey
Beginner
1,610 Views
One problem is in your inner loop you are passing the reference of nCount
to yourself. Then resetting inside the next recursion. Consider using
nCountCopy = nCount
call mvCount(someNode, nCount)
A second potential for problems is if in your "use somemodules" you have global context variables that are used as working storage by mvCount.
A third potential for problems is
iCum(iNode+1)
when/if iNode contains the last index in iCum.
Without seeing the rest of the code it is difficult to determine if the second and third potentials for error are actual errors.
Jim Dempsey
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,610 Views
Well, none of the stuff you mentioned was the problem :-).

The problem was that do-loop variable i was inherited from outer scope, meaning that in effect it was SAVEd (during recursive execution of mvCount). And having a saved variable as a loop counter in recursive/reentrant invocation was not very healthy :-). No run-time errors occured, merely a misbehavior, since i never got outside the valid ranges.

A simple solution was to redeclare i in mvCount, making it local and automatic (as implied by RECURSIVE attribute), but that was a simple omission and I had no errors or warnings to warn me.

Jugoslav
0 Kudos
marshallc
Beginner
1,610 Views

Jugoslav, I was trying to send you a copy of the code that was in error, but I cannot seem to find code that will not work. For whatever reason, when I take the CVF code and convert it to IVF, it works fine the first time. I think there was something "weird" with my IDE setup for IVF. When I was stepping through the code, it would start with the first line and then jump to the second line and then one line up... when there wasn't a do...while or if...then to make it do that. I'm not sure if it was "fixed" when I went in to set the properties of the project or how it was actually "fixed", but the code is working like it should now. I'll keep my fingers crossed that it stays that way. It's a headache when looking at code and things like right but it doesn't work right.... if that makes sense.

By the way, I'm trying to follow the discussion on SAVE and RECURSIVE. You two definitely talk on a totally different level. It's like listening to two rocket scientists talking about the chemical composition of fuel :-) I need to get a Fortran 90 book or something to help fill in the gaps on my understanding of Fortran (any suggestions?). The Compaq Visual Fortan book I have doesn't go into the basics of the language. My background ispre-Windows Basic and a little C. I think there was some talk of SAVE and RECURSIVE, but people rarely used it since they could globally declare a variable and not have to keep track of where the variables were located and whether the values would be retained once leaving a procedure.

0 Kudos
Reply