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

Understanding Win32 API

marshallc
Beginner
4,217 Views
Hi,
I'm trying to get a better understanding of Win32 API. I'm working on a dialog box that has several controls on it. One of these is a group of radio buttons. I've noticed that there are a couple of ways to select a radio button and deselect the others. The Win32 API CheckRadioButton is able to do this, but I'm not understanding the function syntax enough to be able to include it in my code:
Code:
BOOL CheckRadioButton(HWND hDlg,
    int nIDFirstButton,
    int nIDLastButton,
    int nIDCheckButton
);
Does anyone have an example of how this is used in code or could provide some insight on how this is read? I understand the first parameter of the function requires the handle of the dialog box, but I'm not sure how to retrieve the ID of the radio buttons.
Chad
0 Kudos
21 Replies
onkelhotte
New Contributor II
3,665 Views

An easy way is that you have several radio button inside a group box. You only have to select "auto" on the radio buttons styles properties page (which should be checked automaticaly) and there you go.

The id of a radio button (or any other control) isIDC_RADIO1 (or IDC_BUTTON1, IDC_LIST1...) etc.

0 Kudos
marshallc
Beginner
3,665 Views

OK... maybe I'm not using the right thing for what I need to do. Although, I'm still interested in learning how to "read" the information presented in the Platform SDK on function and the like.

I need to initialize/activate a radio button when the dialog box first appears. This doesn't happen right now. I think this API does this function, but I need to understand how to use it.

Once the controls on the dialog box are initialized, I need to be able to pick-up what happens when any of them are clicked. In particular, the radio buttons, there are four of them, change the text in a text box depending on which button is selected.

I was reading the info on buttons and noticed that there is a notification codethat is sent in the form ofBN_CLICKED through the WM_COMMAND message. I know there would be some type of statement under the WM_COMMAND case for the dialog box, but any more than that, and I'm lost. In general terms, there has to be a IF...THEN to determine whether the BN_CLICKED code was sent, but I'm not sure how to read the syntax on BN_CLICKED or how to implement that in my code.

By the way, I still need to figure out how to use CheckRadioButton to initialize the radio buttons. I know there are probably other ways of doing this, but I'm trying to get a better understanding of Win32 APIs and would appreciate the assist.

Side question... would having my radio buttons named IDC_Radio_Front, IDC_Radio_Side, IDC_Radio_Back, and IDC_Radio_Under cause a problem?

Thanks,

Chad

0 Kudos
anthonyrichards
New Contributor III
3,665 Views
If you have written callback routines to handle messages from MODAL dialog box controls (dialog created using retint=DLGINIT(IDD_WHATEVER, dlg)
retint=DLGMODAL(dlg) ), then their template will be
SUBROUTINE callback ( dlg, control_name, callbacktype) Where:
dlg
Refers to the dialog box and allows the callback to change values of the dialog controls.

control_name
Is the name of the control that caused the callback.

callbacktype
Indicates what callback is occurring (for example, DLG_CLICKED, DLG_CHANGE, DLG_DBLCLICK).

All you need is to test control_name to see which control ID (IDC_RADIO1, IDC_BUTTON1, etc) it matches and execute conditional code.

If you are creating MODELESS dialogs, which must have their own message loop and dialog procedure to handle the messages, then the dialog procedure will have the template

integer*4 function WhateverDlgProc( hDlg, message, wParam, lParam )

and 'message' will be one of the control ID's (IDC_RADIO1, etc)

0 Kudos
marshallc
Beginner
3,665 Views

I'm pretty sure I am using Modaless because the value of Modal Frame for the dialog box is False.

Any ideas on CheckRadioButton?

I'm a little confused on something (actually many things). I'm trying to monitor the actions of the radio buttons on my dialog box. I've found examples using DlgSetSub, but is this the Quickwin version of doing it? Is there a better way of identifying what radio button was selected and performing an action from that selection?

0 Kudos
anthonyrichards
New Contributor III
3,665 Views

This has nothing to do with QuickWin. If you use DLGMODAL(dlg) to display the dialog, then you can use DlgSetSub to assign a seperate callback routine toeach of the radio buttons and you can program each callback to take the selective action you want to take depending on what button it is activated by.
It is quite straightforward, just like C++ in fact. The radio buttons are identified by the unique identifier (IDC_RADIO1, etc.) that you enter into the property page of each control as you build the dialog in the resource editor. These identifiers turn up in a C-language style header called RESOURCE.H containing #DEFINE statements such as

#define IDC_RADIO1 1000

which, in CVF, is automatically translated into a FORTRAN-compatible header called RESOURCE.FD (FDcould short for Fortran Definitions, I think) containing parameter definition statements such as

integer, parameter :: IDC_RADIO1 = 1000

This fileMUST be included using

INCLUDE 'RESOURCE.FD'

into any and all routines where the control identifiers are required (such as your callback routines). Hope this helps.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,665 Views
Let me try to clarify few issues:

1) CVF docs incorrectly related DFLOGM routines with QuickWin (as I see, it's reorganized and better stated in IVF9). That was a frequent source of confusion. In fact, DFLOGM is a wrapper module around Win32 API calls, so e.g. DlgModal calls DialogBox, and DlgModeless CreateDialog. As such, it can be used from any type of application (Win32 API, QuickWin, even Console).

2) In DFLOGM, you check radio button using
ret = DlgSet(Dlg, IDC_RADIO2, .TRUE., DLG_STATE)
That call evaluates to SendDlgItemMessage(IDC_RADIO2, BM_SETCHECK) which you can use from DialogProc if you don't use DFLOGM.

3) I've never used CheckRadioGroup because simpler BM_SETCHECK always worked for me.

4) The rules of what constitutes a "radio button group" are not so obvious. Usually, you will get it right naturally when you design the dialog, but if you add a 4th radio button later it probably won't behave. The rules are (hopefully I got it right):
  • all radio buttons must be consecutive in "tab order" (z-order)
  • the first button should have "Group" (BS_GROUP style) and others not
  • the last button in tab order is followed by a non-radio control or any control with BS_GROUP style
    You can set up the tab order in the editor by Format/Tab Order, then click in order. Ctrl+click um... does something, IIRC it allows you to start reordering "from the middle".

    Jugoslav
  • 0 Kudos
    marshallc
    Beginner
    3,665 Views

    That's exactly it! I'm reading through this documentation, and the way in which it is laid out makes me think that there is a particular way in which you program for QuickWin and a particular way in which you program for Win32. From my understanding of the documentation, I didn't think you could use commands that were utilized in the QuickWin section and vice versa. I've been banging my head against all the code samples and documentation trying to find answers to code questions on how to program in Win32 when it has been right there in front of me the whole time.

    With this in mind, I wonder why there is a QuickWin? It seems like something like this would be phased out eventually since everything is moving towards a Win32 architecture, but that is for another discussion ;)

    Thanks guys for all the help! This has definitely changed my outlook on understanding the language... there's hope!

    Chad

    0 Kudos
    onkelhotte
    New Contributor II
    3,665 Views


    marshallc wrote:

    With this in mind, I wonder why there is a QuickWin? It seems like something like this would be phased out eventually since everything is moving towards a Win32 architecture, but that is for another discussion ;)


    Thats exactly what Im asking my boss since I started in my company :smileyvery-happy:

    Good luck with your project/learning Win32!


    Message Edited by OnkelHotte on 11-10-2005 06:30 AM

    0 Kudos
    Jugoslav_Dujic
    Valued Contributor II
    3,665 Views
    That's exactly it!

    Well, which "that"?

    Here are my 2c...

    The rationale behind QuickWin back in 80s was that the scientist takes his old code and simply builds it as QuickWin application without changes, obtaining basic GUI. Then, he can gradually add graphic elements. Two decades later, it's old-fashioned, outdated, and barely improved. (Today, the idea in such situation is that the scientist builds his code as a Dll and develops the GUI using a more suitable tool).

    Note, however, that pure Win32 API can be really complicated. Even when not, the code you write becomes unnecessarily verbose because you have to spend too much time on trivial tasks (the most famous example is CreatePen / CreateBrush / SelectObject / SelectObject / Rectangle / SelectObject / SelectObject / DeleteObject / DeleteObject just to draw a colored and edged rectangle), (and the rest of the time on studying the documentation :-) ).

    Thus, there are many wrapper libraries around Win32 API whose goal is to simplify the task -- MFC, WTL, wxWindows for C++, Winteracter, GINO and Xeffort for Fortran, to name some. The idea is to speed up programming and make the code more clear and maintainable.

    Also, you can use Win32 APIs from a QuickWin application (starting e.g. by GETHWNDQQ, GetModuleHandle etc.) when you need to "tweak" QW behavior (see e.g. QWToolbar sample on my home page). But, not the other way round (and generally not with other similar libraries).
    (Xeffort can be tied with any kind of existing GUI application. )

    Jugoslav
    0 Kudos
    marshallc
    Beginner
    3,665 Views
    Jugoslav, sorry... the "that's it" is in relation to your statement "CVF docs incorrectly related DFLOGM routines with QuickWin (as I see, it's reorganized and better stated in IVF9). That was a frequent source of confusion." That's exactly what was happening... I was getting confused by the CVF docs. The way the functions were presented in the documentation made me believe that the functions used in QuickWin could not be used in Win32.
    Are there other docs for IVF besides those provided online? Has anyone seen samples for IVF? I've been using the docs and samples provided by CVF.
    Chad
    0 Kudos
    Steven_L_Intel1
    Employee
    3,665 Views
    We have not yet published samples for IVF - I have a dozen or more and we're figuring out the best way to make them available. For Win32 programming, Norman Lawrence's book is still applicable and very good.
    0 Kudos
    marshallc
    Beginner
    3,665 Views
    I thought I had it... and I have some blanks that need to be filled in...
    If my dialog box is being created by using the following form:
    Code:
    INTEGER(4) FUNCTION SetupDlgProc( hDlg, message, uParam, lParam )
    !DEC$ IF DEFINED(_X86_)
    !DEC$ ATTRIBUTES STDCALL, ALIAS : '_SetupDlgProc@16' :: SetupDlgProc
    !DEC$ ELSE
    !DEC$ ATTRIBUTES STDCALL, ALIAS : 'SetupDlgProc' :: SetupDlgProc
    !DEC$ ENDIF
    
      use ifwin
      use comctl32
    
      implicit none
    
      integer     hDlg        ! window handle of the dialog box
      integer     message     ! type of message
      integer     uParam      ! message-specific information
      integer     lParam
    
      include 'resource.fd'
      
      .
      .
      .
    
      select case (message)
    		case (WM_INITDIALOG)         
    	              .
                          .
                          .   
                          return
    			
    		case (WM_COMMAND)
    			select case (uParam)
    			  case (IDOK)
    				  SetupDlgProc = 1
    				case (IDCANCEL)
    				  SetupDlgProc = 1
    			end select		
     
      end select
    
    	SetupDlgProc = 0 ! Didn't process the message	
    	return		
    
    END FUNCTION SetupDlgProc


    What is this called? I'm looking at so many different examples and documents that I don't even know what I'm coding. I know... probably shouldn't admit that... but I don't, and I'm getting lost in the jargon... DFLOGM, QuickWin, Win32, etc.
    I'm trying to take control of the radio buttons. I need to monitor when each is selected and change the value in the textbox according to that.
    I thought that if I put DlgSetSub in my code and populated it with what I thought were the right parameters that it would work... wrong! Here is what I have:
    iret = DlgSetSub (hDlg, IDC_Radio1, UpdateTextBox)
    I do have the "USE DFLOGM" at the top... that means that I have included DFLOGM libraries, right?
    Anyhow, the compiler throws errors because it says that hDlg differs from the dummy argument, and it doesn't understand UpdateTextBox (which is a subroutine). I thought when looking at the syntax for DlgSetSub that it was looking for the dialog box handle. I guess not. Help!
    0 Kudos
    jim_dempsey
    Beginner
    3,665 Views

    If you look at the interfaces in the header files you will find that hDlg is not an integer. Instead it is

    integer(int_ptr_kind()) :: hDlg

    Jim

    0 Kudos
    jim_dempsey
    Beginner
    3,665 Views

    Sorry make that

    type(dialog) :: hDlg

    Jim

    0 Kudos
    marshallc
    Beginner
    3,665 Views
    I think I follow you...
    The DlgSetSub function requires a dialog type as the first parameter vs. a handle for a dialog box which is what I'm trying to pass it. I thought this was the same thing initially, but I guess not.
    I think there was a part that I left out... how the dialog box was called...
    Code:
    iret = DialogBoxParam(ghInstance,IDD_Setup,hWnd,&
            LOC(SetupDlgProc), 0)


    When I actually have the SetupDlgProc, I need to have hDlg defined as an integer per the examples I've seen. Is there a way to use what I have and be able to use the DlgSetSub function? Is there a way to take the handle of the dialog box and "convert" it to be what is needed by the function?
    0 Kudos
    Jugoslav_Dujic
    Valued Contributor II
    3,665 Views
    Again, if you use DFLOGM, you can get the handle (TYPE(Dialog)%hWnd) but if you use Win32 API (which you do), you can't get the TYPE(Dialog) out of hWnd.

    In your case, you need to handle WM_COMMAND message from the radio buttons:
    case (WM_COMMAND)
    select case (LOWORD(uParam))
    case (IDOK, IDCANCEL)
    !you probably want to exit the dialog on OK and Cancel buttons:
    ret = EndDialog(hWnd, uParam)
    case (IDC_RADIO1, IDC_RADIO2, IDC_RADIO3)
    if (HIWORD(uParam)==BN_CLICKED)
    !Do something
    end if
    end select
    SetupDlgProc = 1

    to initialize a radio buttion, SendDlgItemMessage(hDlg, IDC_RADIOx, BM_SETCHECK, BST_CHECKED, 0) on WM_INITDIALOG.

    Jugoslav
    0 Kudos
    jim_dempsey
    Beginner
    3,665 Views

    My application is a consol app which launches a seperate thread to create and interface with a modless dialog box. In this way I have added a GUI-like control pannel to my console app.One of thereasons for doing it this way was I wanted the control pannel to remain persistant (I found it annoying to have it blank between button pokes), the second reason was I did not want to suspend the computations that power the energizer bunny. (it keeps running and running). Maybe you can glean some useful information from it. Below are snips of the code

    Code:

    module GlobalData
    ...
    ! handle = CreateThread (security, stack, thread_func, argument, flags, thread_id) 
          integer(INT_PTR_KIND()) :: ControlPanelHandle = 0
          integer(INT_PTR_KIND()) :: ControlPanelSecurity = 0   ! inherit
          integer(INT_PTR_KIND()) :: ControlPanelStack = 0      ! inherit
          ! use ControlPanel as thread_func
          integer(INT_PTR_KIND()) :: ControlPanelArg = 0
          integer(4) :: ControlPanelFlags = 0
          integer(INT_PTR_KIND()) :: ControlPanelThread_ID = 0
          character (len=14) ControlPanelTitle ! = 'GTOSS - XXXXnn'
          character (len=80) ControlPanelCommentLine1
          character (len=80) ControlPanelCommentLine2
    ...
    end module GlobalData
    
    ----
    
    subroutine SomeInitSub
        use GlobalData
    ...
        ! Create seperate thread to run the Modal Dialog control pannel
        ControlPanelHandle = CreateThread( &
            & NULL, &
            & ControlPanelStack, &
            & loc(ControlPanel), &
            & loc(ControlPanelArg), &
            & ControlPanelFlags, &
            & ControlPanelThread_ID)
    ...
    end subroutine SomeInitSub
     ----
    
    
    integer(4) FUNCTION ControlPanel(arg)
    !DEC$ ATTRIBUTES STDCALL, ALIAS:"_controlpanel" :: ControlPanel
        USE IFLOGM
        use   GlobalData
        implicit none
        INCLUDE 'RESOURCE.FD'
        integer(4),POINTER :: arg
        integer(4) returnVal, ms
        CHARACTER(256) text
        LOGICAL retlog
        external ControlPanelCallBack
        retlog = DLGINIT( IDD_DIALOG1, ControlPanelDlg )
        call DlgSetTitle( ControlPanelDlg, ControlPanelTitle )
        retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO1, ControlPanelCallBack )
        retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO_STOP, ControlPanelCallBack )
        ....
        retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE,  1, DLG_RANGEMIN)
        retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE,  1, DLG_SMALLSTEP)
        retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE,  10, DLG_BIGSTEP)
        retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE,  10000, DLG_RANGEMAX)
        retlog = DlgSetSub( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, ControlPanelCallBack )
        
        ! *** Now start the Dialog Box
        returnVal = DlgModal( ControlPanelDlg )
        ! returns on cancled (or IDC_event not specified)
    
        ControlPanelExit = .TRUE.
        ControlPanelPause = .FALSE.
        ControlPanel = returnVal
    end FUNCTION ControlPanel
    
    
    SUBROUTINE ControlPanelCallBack( dlg, id, callbacktype )
    !DEC$ ATTRIBUTES DEFAULT :: ControlPanelCallBack
      USE IFLOGM
      INCLUDE 'DEC_AVFRT.FI'    ! !dec$ define ...
        use GlobalData
        implicit none
        INCLUDE 'RESOURCE.FD'
      TYPE (dialog) dlg
      INTEGER id, callbacktype, iStat
      CHARACTER(256) text
      LOGICAL retlog
      INTEGER cel, far, retint
      real(8) :: xyz(3)
      text = 'undefined'
      ControlPanelPauseRefresh =
     .true.
      NextDisplayTime = 0 ! update now
    
      SELECT CASE (id)
        CASE (IDC_RADIO1)
        ! Radio button 1 selected by user so
        ! change display accordingly
          vIavDisplayFrame = 0   ! vIavDisplayFrame = 0 Inertial Frame
          ! vIavDisplayFrame = 1 Orbital Frame
    ...
        CASE(IDC_RADIO_STOP)
            vElevatorActionState = 0
    ...
        CASE (IDC_CHECK_DAMPER)
            retlog = DLGGETLOG (dlg, IDC_CHECK_DAMPER, vCheckDamper)
    ...
      END SELECT
    END SUBROUTINE ControlPanelCallBack
    


    Jim Dempsey


    0 Kudos
    jim_dempsey
    Beginner
    3,665 Views

    Add to GlobalData



    type (dialog) :: ControlPanelDlg

    0 Kudos
    marshallc
    Beginner
    3,665 Views

    Awesome! Thanks for the assist.

    By the way, is DFLOGM the same thing as QuickWin? I'm not sure if that might be a stupid question, but I just need to clarify this terminology in my head, and I don't want to misuse the wording in the future.

    0 Kudos
    Jugoslav_Dujic
    Valued Contributor II
    3,503 Views
    By the way, is DFLOGM the same thing as QuickWin?

    NO. (emphatically)

    Although don't be surprised if some people associate these two things in the future.

    Jugoslav
    0 Kudos
    Reply