Intro to Windows Programming
From CometWiki
(New page: == A Brief History of the Windows API == The Windows API for Internet Basic programmers is now in its second generation. Originally introduced in 1996, the API consisted of the following...) |
|||
Line 1: | Line 1: | ||
- | |||
== A Brief History of the Windows API == | == A Brief History of the Windows API == | ||
The Windows API for Internet Basic programmers is now in its second generation. Originally introduced in 1996, | The Windows API for Internet Basic programmers is now in its second generation. Originally introduced in 1996, | ||
- | the API consisted of the following files, each of which was “included” in your program: | + | the API consisted of the following files, each of which was “included” in your program: <br> |
- | + | * CosWin.ibs – The Driver Library. This file contains IB functions and support code necessary to perform | |
various Windows functions. Your program will call subroutines from this library. The names of the | various Windows functions. Your program will call subroutines from this library. The names of the | ||
subroutines begin with “COS.”, such as COS.CreateButton. | subroutines begin with “COS.”, such as COS.CreateButton. | ||
- | + | * CosWin.inc - Declaratives for constants, variables, and formats that are used by the code contained in | |
CosWin.ibs | CosWin.ibs | ||
- | + | * Windows.inc – Definition of constants used to represent all the possible styles, messages, and event | |
notifications for each control available through the API. The constants have been derived from the C/C++ | notifications for each control available through the API. The constants have been derived from the C/C++ | ||
- | include file “windows.h” which is supplied as part of the C/C++ development platform. | + | include file “windows.h” which is supplied as part of the C/C++ development platform.<br> |
Because Windows programs are “event-driven”, the API had to include a method for notifying the IB program when | Because Windows programs are “event-driven”, the API had to include a method for notifying the IB program when | ||
an event occurred. This was accomplished through the use of “call back” subroutines. A call back subroutine is | an event occurred. This was accomplished through the use of “call back” subroutines. A call back subroutine is | ||
Line 18: | Line 17: | ||
this meant having to define a call back subroutine for each event type. While the API provided the IB programmer | this meant having to define a call back subroutine for each event type. While the API provided the IB programmer | ||
with the tools necessary to create true Windows programs for their Comet applications, its implementation was a | with the tools necessary to create true Windows programs for their Comet applications, its implementation was a | ||
- | little cumbersome. | + | little cumbersome.<br> |
Comet 2004 introduced the second generation of the API. The call back mechanism was replaced with the | Comet 2004 introduced the second generation of the API. The call back mechanism was replaced with the | ||
EventSub mechanism, which had proven itself in the implementation of hyperlinks. This greatly simplified event | EventSub mechanism, which had proven itself in the implementation of hyperlinks. This greatly simplified event | ||
Line 27: | Line 26: | ||
Subroutines in CometWin.inc are named beginning with “CW.”, such as CW.CreateAutoModeDialog. Because | Subroutines in CometWin.inc are named beginning with “CW.”, such as CW.CreateAutoModeDialog. Because | ||
CometWin.inc includes both declarative and executable code, you will include it twice in your IB program – once at | CometWin.inc includes both declarative and executable code, you will include it twice in your IB program – once at | ||
- | the top of your declarative section and once at the bottom of your executable section. | + | the top of your declarative section and once at the bottom of your executable section.<br> |
== Dialog or Direct? == | == Dialog or Direct? == | ||
The API accommodates two methods for creating the controls for your Windows program. The method you choose | The API accommodates two methods for creating the controls for your Windows program. The method you choose | ||
- | is a matter of personal preference. | + | is a matter of personal preference.<br> |
One method is to use a visual resource editor to design your dialog using “drag-and-drop” tools. We call this the | One method is to use a visual resource editor to design your dialog using “drag-and-drop” tools. We call this the | ||
dialog method. When you’re done with the design, the dialog is compiled to a .dll, which is loaded by your IB | dialog method. When you’re done with the design, the dialog is compiled to a .dll, which is loaded by your IB | ||
program. No coding is required to define the layout or style of the controls in the dialog. We support use of the | program. No coding is required to define the layout or style of the controls in the dialog. We support use of the | ||
- | resource editor included in Microsoft’s Visual Studio. | + | resource editor included in Microsoft’s Visual Studio.<br> |
The other method we call the “direct” method. In this case, the controls are created directly in your IB program by | The other method we call the “direct” method. In this case, the controls are created directly in your IB program by | ||
making calls to the API. We’ll take a look at examples of each, then compare and contrast the two methods. | making calls to the API. We’ll take a look at examples of each, then compare and contrast the two methods. | ||
- | |||
== A Discussion of WinTemp.ibs == | == A Discussion of WinTemp.ibs == | ||
Line 49: | Line 47: | ||
As you know, Windows programs are event-driven. Rather than dictating the flow of the process, the program | As you know, Windows programs are event-driven. Rather than dictating the flow of the process, the program | ||
responds to events initiated by the user. Thus it makes sense that the heart of any Windows program is the code | responds to events initiated by the user. Thus it makes sense that the heart of any Windows program is the code | ||
- | that intercepts these events. In WinTemp.ibs, this is a subroutine called EventHandler. | + | that intercepts these events. In WinTemp.ibs, this is a subroutine called EventHandler.<br> |
When you create your controls, you will tell Comet which events you want to be notified of. Then you tell it the | When you create your controls, you will tell Comet which events you want to be notified of. Then you tell it the | ||
- | name of the subroutine to call when an event occurs and you wait for your first event: | + | name of the subroutine to call when an event occurs and you wait for your first event:<br> |
- | EventSub EventHandler CW.Event$ CW.Source$ | + | EventSub EventHandler CW.Event$ CW.Source$<br> |
- | Eventwait | + | Eventwait<br> |
CW.Event$ and CW.Source$ are API variables that will receive information about what event has occurred. | CW.Event$ and CW.Source$ are API variables that will receive information about what event has occurred. | ||
Then, control will be passed to the subroutine referenced in the EventSub statement: | Then, control will be passed to the subroutine referenced in the EventSub statement: | ||
- | EventHandler: | + | EventHandler: |
- | gosub CW.ParseEvent ! Determine which type of event occurred | + | gosub CW.ParseEvent ! Determine which type of event occurred |
- | select case cosCtlId | + | select case cosCtlId |
- | case IDOK ! User pressed the OK button | + | case IDOK ! User pressed the OK button |
- | if cosCommand = BN.CLICKED | + | if cosCommand = BN.CLICKED |
- | ! To do: write code to process OK button | + | ! To do: write code to process OK button |
- | endif | + | endif |
- | case IDCANCEL ! User pressed the CANCEL button | + | case IDCANCEL ! User pressed the CANCEL button |
- | if cosCommand = BN.CLICKED | + | if cosCommand = BN.CLICKED |
- | CW.ExitEvents = TRUE ! Signal that we want to stop the event handler | + | CW.ExitEvents = TRUE ! Signal that we want to stop the event handler |
- | endif | + | endif |
- | ! To do: write code for any other cases we expect to process | + | ! To do: write code for any other cases we expect to process |
- | endselect | + | endselect |
- | if CW.ExitEvents = FALSE ! Either re-establish or cancel event handler | + | if CW.ExitEvents = FALSE ! Either re-establish or cancel event handler |
- | eventsub EventHandler CW.Event$ CW.Source$ | + | eventsub EventHandler CW.Event$ CW.Source$ |
- | else | + | else |
- | eventsub | + | eventsub |
- | endif | + | endif |
- | return | + | return |
+ | |||
The first thing your event handler should do is to determine which event occurred. You do this by calling | The first thing your event handler should do is to determine which event occurred. You do this by calling | ||
CW.ParseEvent. It loads API variables with information about the event. The two you will use the most are: | CW.ParseEvent. It loads API variables with information about the event. The two you will use the most are: | ||
cosCtlId The ID of the control that generated the event, ex. IDOK – the OK button | cosCtlId The ID of the control that generated the event, ex. IDOK – the OK button | ||
- | cosCommand The event, ex. BN.CLICKED – the button was clicked | + | cosCommand The event, ex. BN.CLICKED – the button was clicked<br> |
When we return from CW.ParseEvent, we use a SELECT clause to process our event. When we’ve finished | When we return from CW.ParseEvent, we use a SELECT clause to process our event. When we’ve finished | ||
processing the event, we need to either re-establish the event wait mechanism so we can get the next event or | processing the event, we need to either re-establish the event wait mechanism so we can get the next event or | ||
- | |||
signal to Comet that we are done. In the example above, the event handler is stopped when the IDCANCEL | signal to Comet that we are done. In the example above, the event handler is stopped when the IDCANCEL | ||
button is clicked. This causes program flow to continue just after the EventWait statement at the top of our | button is clicked. This causes program flow to continue just after the EventWait statement at the top of our | ||
- | program. | + | program.<br> |
So that’s all there is to an event handler. You will add a CASE statement for each control from which you expect | So that’s all there is to an event handler. You will add a CASE statement for each control from which you expect | ||
- | an event. Inside each CASE you’ll have code for each event’s cosCommand value. | + | an event. Inside each CASE you’ll have code for each event’s cosCommand value.<br> |
- | '''Initializing the API''' | + | '''Initializing the API'''<br> |
OK, so now that you understand how events are handled, there are a few other details you need to attend to. The | OK, so now that you understand how events are handled, there are a few other details you need to attend to. The | ||
very first thing your program should do is initialize the Comet Windows API (CosWin). You do this by calling | very first thing your program should do is initialize the Comet Windows API (CosWin). You do this by calling | ||
CW.Open. This will initialize required variables, hide the cursor, and establish the size of your screen, the default | CW.Open. This will initialize required variables, hide the cursor, and establish the size of your screen, the default | ||
- | font you will use, and the color of the wallpaper behind your controls: | + | font you will use, and the color of the wallpaper behind your controls:<br> |
- | !!!!!!!!!!! Initialize CosWin | + | !!!!!!!!!!! Initialize CosWin |
- | ! Set CW.Width and CW.Height to customize screen size. They are ignored if set to 0. | + | ! Set CW.Width and CW.Height to customize screen size. They are ignored if set to 0. |
- | CW.Width = 80 | + | CW.Width = 80 |
- | CW.Height = 30 | + | CW.Height = 30 |
- | ! Set CW.Font$ to change the view font. It is ignored if set to "" | + | ! Set CW.Font$ to change the view font. It is ignored if set to "" |
- | CW.Font$ = "Arial" | + | CW.Font$ = "Arial" |
- | ! To set your wallpaper color, define values for red, green, and blue. | + | ! To set your wallpaper color, define values for red, green, and blue. |
- | ! The values assigned here define a sort of parchment color. For white, set all to 255. | + | ! The values assigned here define a sort of parchment color. For white, set all to 255. |
- | cosRed = 255 & cosGreen = 254 & cosBlue = 236 | + | cosRed = 255 & cosGreen = 254 & cosBlue = 236 |
- | !! As an alternative, if you want the default dialog color, call COS.GetSysColor | + | !! As an alternative, if you want the default dialog color, call COS.GetSysColor |
- | !! gosub COS.GetSysColor ! Sets cosRed, cosGreen, and cosBlue | + | !! gosub COS.GetSysColor ! Sets cosRed, cosGreen, and cosBlue |
- | CW.Color = (cosBlue*65536) + (cosGreen*256) + cosRed | + | CW.Color = (cosBlue*65536) + (cosGreen*256) + cosRed |
- | gosub CW.Open | + | gosub CW.Open |
- | !!!!!!!!!!! Initialization complete | + | !!!!!!!!!!! Initialization complete |
+ | |||
Among the API variables that are initialized by CW.Open, one that you may find particularly handy is CW.Remote. | Among the API variables that are initialized by CW.Open, one that you may find particularly handy is CW.Remote. | ||
If your program is running on a Comet Anywhere client, CW.Remote will be set to TRUE. You will need to know | If your program is running on a Comet Anywhere client, CW.Remote will be set to TRUE. You will need to know | ||
this if you will be loading any bitmaps or launching any Windows files. In that case, you will need to first copy the | this if you will be loading any bitmaps or launching any Windows files. In that case, you will need to first copy the | ||
- | files from the host to the remote. | + | files from the host to the remote.<br> |
If you’re curious about the details of CW.Open and CW.ParseEvent, you’ll find the code in CometWin.Inc on | If you’re curious about the details of CW.Open and CW.ParseEvent, you’ll find the code in CometWin.Inc on | ||
- | WDL. | + | WDL.<br> |
- | '''Creating Your Controls''' | + | '''Creating Your Controls'''<br> |
Now the fun part! Once you’ve got CosWin initialized, you’ll create each of your controls. Each control is really | Now the fun part! Once you’ve got CosWin initialized, you’ll create each of your controls. Each control is really | ||
a small window. It is important to keep this in mind when reading about Windows programming. Your controls | a small window. It is important to keep this in mind when reading about Windows programming. Your controls | ||
- | will be child windows of your Comet window, which is called the parent window. | + | will be child windows of your Comet window, which is called the parent window.<br> |
The CtlDemo programs include an example of each control supported by the API. For most of them, the process | The CtlDemo programs include an example of each control supported by the API. For most of them, the process | ||
is pretty much the same. For each control you’ll assign an ID number, the height, width, and screen position, and | is pretty much the same. For each control you’ll assign an ID number, the height, width, and screen position, and | ||
- | any desired style characteristics. You’ll use the following API variables: | + | any desired style characteristics. You’ll use the following API variables:<br> |
- | cosCtlId - the numeric identifier for the control | + | cosCtlId - the numeric identifier for the control |
- | + | cosWidth - the width (in Centiunits) | |
- | cosWidth - the width (in Centiunits) | + | cosHeight - the height (in Centiunits) |
- | cosHeight - the height (in Centiunits) | + | cosRow - the screen row (in Centiunits) where the control is to be positioned |
- | cosRow - the screen row (in Centiunits) where the control is to be positioned | + | cosCol - the screen column (in Centiunits) |
- | cosCol - the screen column (in Centiunits) | + | cosStyle - the main style characteristics parameter |
- | cosStyle - the main style characteristics parameter | + | cosExStyle - the extended style parameter |
- | cosExStyle - the extended style parameter | + | |
For some controls, such as buttons and edit controls you’ll also assign some text to be displayed on the control. | For some controls, such as buttons and edit controls you’ll also assign some text to be displayed on the control. | ||
Use cosCtlText$ for this. And, for most controls you’ll need to set cosDlgFlags = 0. This is used to tell the API | Use cosCtlText$ for this. And, for most controls you’ll need to set cosDlgFlags = 0. This is used to tell the API | ||
- | when you’re using additional modifiers. | + | when you’re using additional modifiers.<br> |
Here’s an example that creates a “Next” button: | Here’s an example that creates a “Next” button: | ||
- | cosCtlId = IDC.NEXT ! IDC.NEXT is a symbolic constant set to 41001 | + | cosCtlId = IDC.NEXT ! IDC.NEXT is a symbolic constant set to 41001 |
- | cosWidth = 800 & cosHeight = 150 ! The button will be 8 chars wide and 1.5 chars high | + | cosWidth = 800 & cosHeight = 150 ! The button will be 8 chars wide and 1.5 chars high |
- | cosRow = 1400 & cosCol = 3600 ! Position button on row 14, column 36 | + | cosRow = 1400 & cosCol = 3600 ! Position button on row 14, column 36 |
- | cosStyle = WS.VISIBLE + WS.CHILD + WS.TABSTOP + WS.GROUP + BS.DEFPUSHBUTTON | + | cosStyle = WS.VISIBLE + WS.CHILD + WS.TABSTOP + WS.GROUP + BS.DEFPUSHBUTTON |
- | cosExStyle = 0 | + | cosExStyle = 0 |
- | cosCtlText$ = "Next" | + | cosCtlText$ = "Next" |
- | cosDlgFlags = 0 | + | cosDlgFlags = 0 |
- | cosCWnd$ = cosDlghDlg$ | + | cosCWnd$ = cosDlghDlg$ |
- | gosub COS.CreateButton | + | gosub COS.CreateButton |
One thing that might be puzzling in this code is the cosStyle assignment. This defines characteristics of the button. | One thing that might be puzzling in this code is the cosStyle assignment. This defines characteristics of the button. | ||
The style values that begin with “WS.” are generic “Window Styles” and apply to any control. So, for example any | The style values that begin with “WS.” are generic “Window Styles” and apply to any control. So, for example any | ||
Line 154: | Line 153: | ||
appending the control ID and event to the CosWin API command filter. So, to request that we be notified any time | appending the control ID and event to the CosWin API command filter. So, to request that we be notified any time | ||
our “Next” button is clicked, we code: | our “Next” button is clicked, we code: | ||
- | cosCWnd$ = cosDlghDlg$ ! Pass the handle of the parent window, as it owns the command filter | + | cosCWnd$ = cosDlghDlg$ ! Pass the handle of the parent window, as it owns the command filter |
- | cosCtlText$ = intel(IDC.NEXT) + intel(BN.CLICKED) | + | cosCtlText$ = intel(IDC.NEXT) + intel(BN.CLICKED) |
- | gosub COS.AppendCmdFilter | + | gosub COS.AppendCmdFilter<br> |
cosCtlText$ is a concatentation of word pairs. The first word is the control’s ID; the second word is the event ID. | cosCtlText$ is a concatentation of word pairs. The first word is the control’s ID; the second word is the event ID. | ||
As a matter of fact, you can send multiple pairs to the command filter in one call. For example, if you had a | As a matter of fact, you can send multiple pairs to the command filter in one call. For example, if you had a | ||
CANCEL button as well an a NEXT button, you could either call COS.AppendCmdFilter once for each button, or | CANCEL button as well an a NEXT button, you could either call COS.AppendCmdFilter once for each button, or | ||
make just one call: | make just one call: | ||
- | cosCWnd$ = cosDlghDlg$ ! Pass the handle of the parent window, as it owns the command filter | + | cosCWnd$ = cosDlghDlg$ ! Pass the handle of the parent window, as it owns the command filter |
- | cosCtlText$ = intel(IDC.NEXT) + intel(BN.CLICKED) + intel(IDCANCEL) + intel(BN.CLICKED) | + | cosCtlText$ = intel(IDC.NEXT) + intel(BN.CLICKED) + intel(IDCANCEL) + intel(BN.CLICKED) |
- | gosub COS.AppendCmdFilter | + | gosub COS.AppendCmdFilter |
This method of building the command filter is used for most of the controls. A few controls do it a little differently. | This method of building the command filter is used for most of the controls. A few controls do it a little differently. | ||
The List View control is one. Instead of calling COS.AppendCmdFilter, you will call COS.AppendNotifyFilter2. It | The List View control is one. Instead of calling COS.AppendCmdFilter, you will call COS.AppendNotifyFilter2. It | ||
- | |||
requires 3 parameters for each control event. You can see examples of how this is done in Ctl10.ibs for the List | requires 3 parameters for each control event. You can see examples of how this is done in Ctl10.ibs for the List | ||
- | View control. | + | View control.<br> |
'''Shutting down the API''' | '''Shutting down the API''' | ||
After you stop the event handler and are about to exit your program you need to shut down the API and restore | After you stop the event handler and are about to exit your program you need to shut down the API and restore | ||
your environment. This is done with a simple call to CW.Close: | your environment. This is done with a simple call to CW.Close: | ||
- | !!!!!!!!!!! Program Exit | + | !!!!!!!!!!! Program Exit |
- | ProgExit: | + | ProgExit: |
- | eventsub ! Cancel the event handler in case F3 or fatal error occurred | + | eventsub ! Cancel the event handler in case F3 or fatal error occurred |
- | gosub CW.Close ! Restore environment | + | gosub CW.Close ! Restore environment |
- | if RUNSTATE = 6 exit | + | if RUNSTATE = 6 exit |
- | stop | + | stop |
CW.Close destroys all of the controls you created, removes your wallpaper, and restores the cursor. | CW.Close destroys all of the controls you created, removes your wallpaper, and restores the cursor. | ||
- | |||
== A Discussion of DlgTemp.ibs == | == A Discussion of DlgTemp.ibs == | ||
Line 186: | Line 183: | ||
used a resource editor to create a .dll for your dialog. DlgTemp.ibs can be used to create either a modal or a | used a resource editor to create a .dll for your dialog. DlgTemp.ibs can be used to create either a modal or a | ||
modeless dialog with just OK and CANCEL buttons, but has all the hooks for you to process other controls in your | modeless dialog with just OK and CANCEL buttons, but has all the hooks for you to process other controls in your | ||
- | dialog. | + | dialog.<br> |
- | '''The Event Handler''' | + | '''The Event Handler'''<br> |
Like WinTemp.ibs, the Event Handler is the control center of the program. When using a dialog, however, there | Like WinTemp.ibs, the Event Handler is the control center of the program. When using a dialog, however, there | ||
are a couple of important differences. First, in addition to catching events for each control, you will also want to | are a couple of important differences. First, in addition to catching events for each control, you will also want to | ||
- | detect when the dialog is being loaded and when it is being closed. Look at the CASE ELSE below: | + | detect when the dialog is being loaded and when it is being closed. Look at the CASE ELSE below:<br> |
- | EventHandler: | + | EventHandler: |
- | gosub CW.ParseEvent ! Determine which type of event occurred | + | gosub CW.ParseEvent ! Determine which type of event occurred |
- | select case cosCtlId | + | select case cosCtlId |
- | case IDOK ! User pressed the OK button | + | case IDOK ! User pressed the OK button |
- | if cosCommand = BN.CLICKED | + | if cosCommand = BN.CLICKED |
- | ! To do: write code to process OK button | + | ! To do: write code to process OK button |
- | endif | + | endif |
- | ! To do: write code for any other control events we expect to process | + | ! To do: write code for any other control events we expect to process |
- | case else ! We got an event for something other than our controls | + | case else ! We got an event for something other than our controls |
- | gosub CW.IsWindowInitializing | + | gosub CW.IsWindowInitializing |
- | if cosState = TRUE ! Dialog is being loaded | + | if cosState = TRUE ! Dialog is being loaded |
- | gosub InitDialog | + | gosub InitDialog |
- | else | + | else |
- | gosub CW.CheckAutoModeClosing | + | gosub CW.CheckAutoModeClosing |
- | !!!! If the dialog is closing, CW.ExitEvents will be set to TRUE by the API | + | !!!! If the dialog is closing, CW.ExitEvents will be set to TRUE by the API |
- | endif | + | endif |
- | endselect | + | endselect |
- | if CW.ExitEvents = FALSE ! Either re-establish or cancel event handler | + | if CW.ExitEvents = FALSE ! Either re-establish or cancel event handler |
- | eventsub EventHandler CW.Event$ CW.Source$ | + | eventsub EventHandler CW.Event$ CW.Source$ |
- | else | + | else |
- | eventsub | + | eventsub |
- | endif | + | endif |
- | return | + | return |
When the dialog is being loaded, you’ll want to initialize the state of your controls such as populating a list box, or | When the dialog is being loaded, you’ll want to initialize the state of your controls such as populating a list box, or | ||
setting radio buttons or check boxes. It’s also a good time to establish your command filter. In WinTemp.ibs we | setting radio buttons or check boxes. It’s also a good time to establish your command filter. In WinTemp.ibs we | ||
- | did these things at the time we created the control. | + | did these things at the time we created the control.<br> |
- | InitDialog: | + | InitDialog: |
- | cosCWnd$ = cosDlghDlg$ | + | cosCWnd$ = cosDlghDlg$ |
- | cosCtlText$ = intel(IDOK) + intel(BN.CLICKED) | + | cosCtlText$ = intel(IDOK) + intel(BN.CLICKED) |
- | gosub COS.AppendCmdFilter ! Setup the command filter | + | gosub COS.AppendCmdFilter ! Setup the command filter |
- | ! This would be a good place to load any data you need into the dialog and to | + | ! This would be a good place to load any data you need into the dialog and to |
- | ! initialize the state of each control, ie check boxes, radio buttons,etc. | + | ! initialize the state of each control, ie check boxes, radio buttons,etc. |
- | + | cosState = true ! Tell the API to size the CosW window to our dialog | |
- | cosState = true ! Tell the API to size the CosW window to our dialog | + | gosub CW.AutoSizeDialog |
- | gosub CW.AutoSizeDialog | + | cosCWnd$ = cosDlghDlg$ |
- | cosCWnd$ = cosDlghDlg$ | + | cosState = SW.NORMAL |
- | cosState = SW.NORMAL | + | gosub COS.ShowWindow ! Make the dialog visible |
- | gosub COS.ShowWindow ! Make the dialog visible | + | return |
- | return | + | |
Another difference when using a dialog is that clicking either the OK button or CANCEL button will cause the | Another difference when using a dialog is that clicking either the OK button or CANCEL button will cause the | ||
dialog to close automatically. All you need to do is to detect that the dialog is closing by calling | dialog to close automatically. All you need to do is to detect that the dialog is closing by calling | ||
CW.CheckAutoModeClosing. If the dialog is closing, it will set CW.ExitEvents to true and your event handler will | CW.CheckAutoModeClosing. If the dialog is closing, it will set CW.ExitEvents to true and your event handler will | ||
not be re-established. When the dialog is closing, if you want to know which button was clicked, you can save its | not be re-established. When the dialog is closing, if you want to know which button was clicked, you can save its | ||
- | ID. It is set by CW.ParseEvent into coswParam. | + | ID. It is set by CW.ParseEvent into coswParam.<br> |
Note: If you want an event other than the clicking of OK or CANCEL to cause the dialog to close, you can call | Note: If you want an event other than the clicking of OK or CANCEL to cause the dialog to close, you can call | ||
CW.CloseAutoModeDialog when you get that event. Conversely, if you don’t want the dialog to close | CW.CloseAutoModeDialog when you get that event. Conversely, if you don’t want the dialog to close | ||
Line 240: | Line 236: | ||
explicitly. As a matter of fact, if you want to retrieve data from the dialog when OK is clicked you will have to | explicitly. As a matter of fact, if you want to retrieve data from the dialog when OK is clicked you will have to | ||
handle that button explicitly. Just tell the command filter you want to handle that button, and add your code to the | handle that button explicitly. Just tell the command filter you want to handle that button, and add your code to the | ||
- | event handler. This gives you total control. The DlgTemp.ibs example handles the OK button explicitly. | + | event handler. This gives you total control. The DlgTemp.ibs example handles the OK button explicitly.<br> |
'''Loading Your Dialog''' | '''Loading Your Dialog''' | ||
Getting your dialog loaded is really easy. All you need to do is to tell the API the name of your dialog and where | Getting your dialog loaded is really easy. All you need to do is to tell the API the name of your dialog and where | ||
to find your .dll. So, at the top of our program, you see: | to find your .dll. So, at the top of our program, you see: | ||
- | ! Establish BEFORE calling CW.CreateAutoModeDialog or else we'll miss the "dialog is initializing" event | + | ! Establish BEFORE calling CW.CreateAutoModeDialog or else we'll miss the "dialog is initializing" event |
- | eventsub EventHandler CW.Event$ CW.Source$ | + | eventsub EventHandler CW.Event$ CW.Source$ |
- | cosDllNames$ = "DlgTemp.dll" ! DLL filename | + | cosDllNames$ = "DlgTemp.dll" ! DLL filename |
- | cosDllDir$ = sub(pstat(PARTITION$),41,3) ! Same dir as this program | + | cosDllDir$ = sub(pstat(PARTITION$),41,3) ! Same dir as this program |
- | cosDlgId = IDD.DIALOG1 ! Dialog ID | + | cosDlgId = IDD.DIALOG1 ! Dialog ID |
- | ! If your dialog was designated as “child” it will be modeless. If “popup” it will be modal. | + | ! If your dialog was designated as “child” it will be modeless. If “popup” it will be modal. |
- | gosub CW.CreateAutoModeDialog | + | gosub CW.CreateAutoModeDialog |
- | if cosDlgOpen = FALSE | + | if cosDlgOpen = FALSE |
- | print "Dialog execution failed" | + | print "Dialog execution failed" |
- | go ProgExit | + | go ProgExit |
- | endif | + | endif |
- | eventwait | + | eventwait |
- | Note: If your program is running on a Comet Anywhere client, the call to CW.CreateAutoModeDialog will | + | '''Note:''' If your program is running on a Comet Anywhere client, the call to CW.CreateAutoModeDialog will |
- | automatically transfer the .dll from the host to the $(CATOOLS) folder on the remote. | + | automatically transfer the .dll from the host to the $(CATOOLS) folder on the remote.<br> |
- | '''In the Resource Editor''' | + | '''In the Resource Editor'''<br> |
The Resource Editor is where you design your dialog and create its controls. Running DPBuild.exe will quickly | The Resource Editor is where you design your dialog and create its controls. Running DPBuild.exe will quickly | ||
- | generate a template project for you. | + | generate a template project for you.<br> |
When you compile your project to generate the .dll, an ID will be assigned to each control and to the dialog itself. | When you compile your project to generate the .dll, an ID will be assigned to each control and to the dialog itself. | ||
A control’s ID is what’s assigned to cosCtlID; the dialog’s ID is what’s assigned to cosDlgId. We recommend | A control’s ID is what’s assigned to cosCtlID; the dialog’s ID is what’s assigned to cosDlgId. We recommend | ||
using SET statements to give a meaningful name to each ID. As an alternative to entering these IDs manually, | using SET statements to give a meaningful name to each ID. As an alternative to entering these IDs manually, | ||
- | |||
you'll find a program called Inc2Use.exe in the WDL release that will make an include file that declares the IDs for | you'll find a program called Inc2Use.exe in the WDL release that will make an include file that declares the IDs for | ||
your IB program. Setup Inc2Use to run as part of your "Post-Build Steps" in your project and your IB include file | your IB program. Setup Inc2Use to run as part of your "Post-Build Steps" in your project and your IB include file | ||
Line 276: | Line 271: | ||
preference. Here are a few thoughts about each method: | preference. Here are a few thoughts about each method: | ||
'''Dialog''' | '''Dialog''' | ||
- | + | * It is really convenient to be able to create your screens by dragging and dropping the | |
controls where you want them. | controls where you want them. | ||
- | + | * It's easy to select a group of controls and have them automatically sized and aligned the | |
same. | same. | ||
- | + | * Assigning attributes to a control is simple. A right click on the control pops up a window | |
with check boxes for the style choices, a place to enter your caption, etc. | with check boxes for the style choices, a place to enter your caption, etc. | ||
- | + | * Since the code for creating all the controls is encoded in the .dll, your companion IB | |
object will be smaller than a similar program written using the direct method. However, | object will be smaller than a similar program written using the direct method. However, | ||
the sum of the two pieces will be larger than the single IB object. | the sum of the two pieces will be larger than the single IB object. | ||
- | + | * Visual Studio will take care of assigning identifiers to each of your controls for you. | |
- | '''Direct''' | + | '''Direct'''<br> |
- | + | * You only need to deal with a single development environment. | |
- | + | * You don’t have to package the .dll along with your application. Your IB object contains | |
everything. | everything. | ||
- | + | * You can intersperse other GDI objects such as hyperlinks with your controls. | |
- | + | * You can always write debug messages directly to the window. | |
- | + | ||
- | A Beginner’s Guide to Events and Functions for Selected Windows Controls | + | |
+ | == A Beginner’s Guide to Events and Functions for Selected Windows Controls == | ||
+ | |||
A complete list of events for each control can be found in Windows.inc. They are called “notify” or | A complete list of events for each control can be found in Windows.inc. They are called “notify” or | ||
“notification” codes. A complete list of functions for each control can be found in CosWin.ibs. | “notification” codes. A complete list of functions for each control can be found in CosWin.ibs. | ||
The Demo programs, WinTemp.ibs, and DlgTemp.ibs are released as part of the “DLG” folder. | The Demo programs, WinTemp.ibs, and DlgTemp.ibs are released as part of the “DLG” folder. | ||
- | Control Events Functions Demo Sample | + | Control Events Functions Demo Sample |
- | Button BN.CLICKED COS.CreateButton any CtlDemo program | + | Button BN.CLICKED COS.CreateButton any CtlDemo program |
- | Check Box BN.CLICKED COS.CreateButton Ctl3.ibs, Dlg3.ibs | + | Check Box BN.CLICKED COS.CreateButton Ctl3.ibs, Dlg3.ibs |
- | COS.CheckDlgButton | + | COS.CheckDlgButton |
- | COS.IsDlgButtonChecked | + | COS.IsDlgButtonChecked |
- | Radio Button BN.CLICKED COS.CreateButton Ctl2.ibs, Dlg2.ibs | + | Radio Button BN.CLICKED COS.CreateButton Ctl2.ibs, Dlg2.ibs |
- | COS.CheckRadioBtn | + | COS.CheckRadioBtn |
- | COS.GetCheckedRadioBtn | + | COS.GetCheckedRadioBtn |
- | Static COS.CreateStatic Ctl1.ibs | + | Static COS.CreateStatic Ctl1.ibs |
- | Edit cosEN.LOSTFOCUS COS.CreateEdit Ctl5a.ibs, Dlg5a.ibs | + | Edit cosEN.LOSTFOCUS COS.CreateEdit Ctl5a.ibs, Dlg5a.ibs |
- | EN.SETFOCUS COS.EditLimitText | + | EN.SETFOCUS COS.EditLimitText |
- | List Box LBN.SELCHANGE COS.CreateListBox Ctl4.ibs, Dlg4.ibs | + | List Box LBN.SELCHANGE COS.CreateListBox Ctl4.ibs, Dlg4.ibs |
- | LBN.DBLCLK COS.ListAddString | + | LBN.DBLCLK COS.ListAddString |
- | COS.ListDelString | + | COS.ListDelString |
- | COS.ListInsertString | + | COS.ListInsertString |
- | COS.ListFindString | + | COS.ListFindString |
- | COS.ListGetCount | + | COS.ListGetCount |
- | COS.ListResetContent | + | COS.ListResetContent |
- | COS.ListSetCurSel | + | COS.ListSetCurSel |
- | COS.ListGetCurSel | + | COS.ListGetCurSel |
- | COS.ListGetText | + | COS.ListGetText |
- | + | Combo Box CBN.SELCHANGE COS.CreateComboBox Ctl14.ibs, Dlg14.ibs | |
- | Combo Box CBN.SELCHANGE COS.CreateComboBox Ctl14.ibs, Dlg14.ibs | + | CBN.DBLCLK COS.ComboAddString |
- | CBN.DBLCLK COS.ComboAddString | + | COS.ComboDeleteString |
- | COS.ComboDeleteString | + | COS.ComboInsertString |
- | COS.ComboInsertString | + | COS.ComboFindString |
- | COS.ComboFindString | + | COS.ComboFindStringExact |
- | COS.ComboFindStringExact | + | COS.ComboGetCount |
- | COS.ComboGetCount | + | COS.ComboResetContent |
- | COS.ComboResetContent | + | COS.ComboSetCurSel |
- | COS.ComboSetCurSel | + | COS.ComboGetCurSel |
- | COS.ComboGetCurSel | + | COS.ComboGetText |
- | COS.ComboGetText | + | COS.ComboLimitText |
- | COS.ComboLimitText | + | List View NM.CLICK COS.CreateListControl Ctl10.ibs, Dlg10.ibs |
- | List View NM.CLICK COS.CreateListControl Ctl10.ibs, Dlg10.ibs | + | NM.DBLCLK COS.ListView.InsertTextColumn |
- | NM.DBLCLK COS.ListView.InsertTextColumn | + | NM.RCLICK COS.ListView.SetColumnWidth |
- | NM.RCLICK COS.ListView.SetColumnWidth | + | LVN.COLUMNCLICK COS.ListView.InsertStringItem |
- | LVN.COLUMNCLICK COS.ListView.InsertStringItem | + | COS.ListView.SetFullRowSelect |
- | COS.ListView.SetFullRowSelect | + | COS.ListView.DeleteAllItems |
- | COS.ListView.DeleteAllItems | + | COS.ListView.GetNextItem |
- | COS.ListView.GetNextItem | + | COS.ListView.GetItemText |
- | COS.ListView.GetItemText | + | COS.ListView.SortItems |
- | COS.ListView.SortItems | + | All Controls COS.SetDlgItemFocus |
- | All Controls COS.SetDlgItemFocus | + | COS.EnableDlgItem<br> |
- | COS.EnableDlgItem | + | |
Each function requires setting of parameters before making the call. To determine how to do this for a given | Each function requires setting of parameters before making the call. To determine how to do this for a given | ||
function, either look at the sample code from the CtlDemo or DlgDemo program, or search CosWin.ibs for the | function, either look at the sample code from the CtlDemo or DlgDemo program, or search CosWin.ibs for the | ||
function name. Comments provided there explain what is required and what will be returned following the call. | function name. Comments provided there explain what is required and what will be returned following the call. |
Revision as of 09:53, 7 June 2009
Contents |
A Brief History of the Windows API
The Windows API for Internet Basic programmers is now in its second generation. Originally introduced in 1996,
the API consisted of the following files, each of which was “included” in your program:
- CosWin.ibs – The Driver Library. This file contains IB functions and support code necessary to perform
various Windows functions. Your program will call subroutines from this library. The names of the subroutines begin with “COS.”, such as COS.CreateButton.
- CosWin.inc - Declaratives for constants, variables, and formats that are used by the code contained in
CosWin.ibs
- Windows.inc – Definition of constants used to represent all the possible styles, messages, and event
notifications for each control available through the API. The constants have been derived from the C/C++
include file “windows.h” which is supplied as part of the C/C++ development platform.
Because Windows programs are “event-driven”, the API had to include a method for notifying the IB program when
an event occurred. This was accomplished through the use of “call back” subroutines. A call back subroutine is
one defined in the IB program that will be executed by the API when a particular event occurs, such as the clicking
of a button in the dialog. Since there are a number of types of events that the IB programmer may want to handle,
this meant having to define a call back subroutine for each event type. While the API provided the IB programmer
with the tools necessary to create true Windows programs for their Comet applications, its implementation was a
little cumbersome.
Comet 2004 introduced the second generation of the API. The call back mechanism was replaced with the
EventSub mechanism, which had proven itself in the implementation of hyperlinks. This greatly simplified event
handling. Now all event types could be handled in one place. The new API also included a new file, CometWin.inc.
It provides a new layer between the IB program and the API to take care of many of the housekeeping details
previously left to IB program. It is the only one of the API files you need to include in your IB program. You will use
subroutines and declarations from the original API files, but CometWin.inc will include those files for you.
Subroutines in CometWin.inc are named beginning with “CW.”, such as CW.CreateAutoModeDialog. Because
CometWin.inc includes both declarative and executable code, you will include it twice in your IB program – once at
the top of your declarative section and once at the bottom of your executable section.
Dialog or Direct?
The API accommodates two methods for creating the controls for your Windows program. The method you choose
is a matter of personal preference.
One method is to use a visual resource editor to design your dialog using “drag-and-drop” tools. We call this the
dialog method. When you’re done with the design, the dialog is compiled to a .dll, which is loaded by your IB
program. No coding is required to define the layout or style of the controls in the dialog. We support use of the
resource editor included in Microsoft’s Visual Studio.
The other method we call the “direct” method. In this case, the controls are created directly in your IB program by
making calls to the API. We’ll take a look at examples of each, then compare and contrast the two methods.
A Discussion of WinTemp.ibs
WinTemp.ibs was designed to be a template program to get you started on your Windows program using the
direct method. It creates a window with just OK and CANCEL buttons, but has all the hooks for you to add other
controls.
The Event Handler
As you know, Windows programs are event-driven. Rather than dictating the flow of the process, the program
responds to events initiated by the user. Thus it makes sense that the heart of any Windows program is the code
that intercepts these events. In WinTemp.ibs, this is a subroutine called EventHandler.
When you create your controls, you will tell Comet which events you want to be notified of. Then you tell it the
name of the subroutine to call when an event occurs and you wait for your first event:
EventSub EventHandler CW.Event$ CW.Source$
Eventwait
CW.Event$ and CW.Source$ are API variables that will receive information about what event has occurred. Then, control will be passed to the subroutine referenced in the EventSub statement:
EventHandler: gosub CW.ParseEvent ! Determine which type of event occurred select case cosCtlId case IDOK ! User pressed the OK button if cosCommand = BN.CLICKED ! To do: write code to process OK button endif case IDCANCEL ! User pressed the CANCEL button if cosCommand = BN.CLICKED CW.ExitEvents = TRUE ! Signal that we want to stop the event handler endif ! To do: write code for any other cases we expect to process endselect if CW.ExitEvents = FALSE ! Either re-establish or cancel event handler eventsub EventHandler CW.Event$ CW.Source$ else eventsub endif return
The first thing your event handler should do is to determine which event occurred. You do this by calling
CW.ParseEvent. It loads API variables with information about the event. The two you will use the most are:
cosCtlId The ID of the control that generated the event, ex. IDOK – the OK button
cosCommand The event, ex. BN.CLICKED – the button was clicked
When we return from CW.ParseEvent, we use a SELECT clause to process our event. When we’ve finished
processing the event, we need to either re-establish the event wait mechanism so we can get the next event or
signal to Comet that we are done. In the example above, the event handler is stopped when the IDCANCEL
button is clicked. This causes program flow to continue just after the EventWait statement at the top of our
program.
So that’s all there is to an event handler. You will add a CASE statement for each control from which you expect
an event. Inside each CASE you’ll have code for each event’s cosCommand value.
Initializing the API
OK, so now that you understand how events are handled, there are a few other details you need to attend to. The
very first thing your program should do is initialize the Comet Windows API (CosWin). You do this by calling
CW.Open. This will initialize required variables, hide the cursor, and establish the size of your screen, the default
font you will use, and the color of the wallpaper behind your controls:
!!!!!!!!!!! Initialize CosWin ! Set CW.Width and CW.Height to customize screen size. They are ignored if set to 0. CW.Width = 80 CW.Height = 30 ! Set CW.Font$ to change the view font. It is ignored if set to "" CW.Font$ = "Arial" ! To set your wallpaper color, define values for red, green, and blue. ! The values assigned here define a sort of parchment color. For white, set all to 255. cosRed = 255 & cosGreen = 254 & cosBlue = 236 !! As an alternative, if you want the default dialog color, call COS.GetSysColor !! gosub COS.GetSysColor ! Sets cosRed, cosGreen, and cosBlue CW.Color = (cosBlue*65536) + (cosGreen*256) + cosRed gosub CW.Open !!!!!!!!!!! Initialization complete
Among the API variables that are initialized by CW.Open, one that you may find particularly handy is CW.Remote.
If your program is running on a Comet Anywhere client, CW.Remote will be set to TRUE. You will need to know
this if you will be loading any bitmaps or launching any Windows files. In that case, you will need to first copy the
files from the host to the remote.
If you’re curious about the details of CW.Open and CW.ParseEvent, you’ll find the code in CometWin.Inc on
WDL.
Creating Your Controls
Now the fun part! Once you’ve got CosWin initialized, you’ll create each of your controls. Each control is really
a small window. It is important to keep this in mind when reading about Windows programming. Your controls
will be child windows of your Comet window, which is called the parent window.
The CtlDemo programs include an example of each control supported by the API. For most of them, the process
is pretty much the same. For each control you’ll assign an ID number, the height, width, and screen position, and
any desired style characteristics. You’ll use the following API variables:
cosCtlId - the numeric identifier for the control cosWidth - the width (in Centiunits) cosHeight - the height (in Centiunits) cosRow - the screen row (in Centiunits) where the control is to be positioned cosCol - the screen column (in Centiunits) cosStyle - the main style characteristics parameter cosExStyle - the extended style parameter
For some controls, such as buttons and edit controls you’ll also assign some text to be displayed on the control.
Use cosCtlText$ for this. And, for most controls you’ll need to set cosDlgFlags = 0. This is used to tell the API
when you’re using additional modifiers.
Here’s an example that creates a “Next” button:
cosCtlId = IDC.NEXT ! IDC.NEXT is a symbolic constant set to 41001 cosWidth = 800 & cosHeight = 150 ! The button will be 8 chars wide and 1.5 chars high cosRow = 1400 & cosCol = 3600 ! Position button on row 14, column 36 cosStyle = WS.VISIBLE + WS.CHILD + WS.TABSTOP + WS.GROUP + BS.DEFPUSHBUTTON cosExStyle = 0 cosCtlText$ = "Next" cosDlgFlags = 0 cosCWnd$ = cosDlghDlg$ gosub COS.CreateButton
One thing that might be puzzling in this code is the cosStyle assignment. This defines characteristics of the button. The style values that begin with “WS.” are generic “Window Styles” and apply to any control. So, for example any time you create a control and you want it to be visible on your screen, you’ll include the WS.VISIBLE style, regardless of the type of control. Then, for specific controls, there may unique styles values. For a button, BS.DEFPUSHBUTTON indicates that this is the default button. A full list of the style values can be found in Windows.inc. Descriptions of the styles available for each control can be found on Microsoft’s web site at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_styles_used_by_mfc.asp Whenever a window is created it is assigned a handle to uniquely identify it to Windows. Since each control is really a window, every control has its own handle. The parent window also has a handle. The WS.CHILD style indicates that this control will be a child window. We need to pass the parent’s handle to Comet when we create the new control. cosDlghDlg$ will contain the handle to the parent. We pass it in cosCWnd$. After you create the control, you need to tell Comet which event(s) you want to process. You do this by appending the control ID and event to the CosWin API command filter. So, to request that we be notified any time our “Next” button is clicked, we code:
cosCWnd$ = cosDlghDlg$ ! Pass the handle of the parent window, as it owns the command filter cosCtlText$ = intel(IDC.NEXT) + intel(BN.CLICKED) gosub COS.AppendCmdFilter
cosCtlText$ is a concatentation of word pairs. The first word is the control’s ID; the second word is the event ID. As a matter of fact, you can send multiple pairs to the command filter in one call. For example, if you had a CANCEL button as well an a NEXT button, you could either call COS.AppendCmdFilter once for each button, or make just one call:
cosCWnd$ = cosDlghDlg$ ! Pass the handle of the parent window, as it owns the command filter cosCtlText$ = intel(IDC.NEXT) + intel(BN.CLICKED) + intel(IDCANCEL) + intel(BN.CLICKED) gosub COS.AppendCmdFilter
This method of building the command filter is used for most of the controls. A few controls do it a little differently.
The List View control is one. Instead of calling COS.AppendCmdFilter, you will call COS.AppendNotifyFilter2. It
requires 3 parameters for each control event. You can see examples of how this is done in Ctl10.ibs for the List
View control.
Shutting down the API
After you stop the event handler and are about to exit your program you need to shut down the API and restore
your environment. This is done with a simple call to CW.Close:
!!!!!!!!!!! Program Exit ProgExit: eventsub ! Cancel the event handler in case F3 or fatal error occurred gosub CW.Close ! Restore environment if RUNSTATE = 6 exit stop
CW.Close destroys all of the controls you created, removes your wallpaper, and restores the cursor.
A Discussion of DlgTemp.ibs
DlgTemp.ibs was designed to be a template program to get you started on your Windows program where you’ve
used a resource editor to create a .dll for your dialog. DlgTemp.ibs can be used to create either a modal or a
modeless dialog with just OK and CANCEL buttons, but has all the hooks for you to process other controls in your
dialog.
The Event Handler
Like WinTemp.ibs, the Event Handler is the control center of the program. When using a dialog, however, there
are a couple of important differences. First, in addition to catching events for each control, you will also want to
detect when the dialog is being loaded and when it is being closed. Look at the CASE ELSE below:
EventHandler: gosub CW.ParseEvent ! Determine which type of event occurred select case cosCtlId case IDOK ! User pressed the OK button if cosCommand = BN.CLICKED ! To do: write code to process OK button endif ! To do: write code for any other control events we expect to process case else ! We got an event for something other than our controls gosub CW.IsWindowInitializing if cosState = TRUE ! Dialog is being loaded gosub InitDialog else gosub CW.CheckAutoModeClosing !!!! If the dialog is closing, CW.ExitEvents will be set to TRUE by the API endif endselect if CW.ExitEvents = FALSE ! Either re-establish or cancel event handler eventsub EventHandler CW.Event$ CW.Source$ else eventsub endif return
When the dialog is being loaded, you’ll want to initialize the state of your controls such as populating a list box, or
setting radio buttons or check boxes. It’s also a good time to establish your command filter. In WinTemp.ibs we
did these things at the time we created the control.
InitDialog: cosCWnd$ = cosDlghDlg$ cosCtlText$ = intel(IDOK) + intel(BN.CLICKED) gosub COS.AppendCmdFilter ! Setup the command filter ! This would be a good place to load any data you need into the dialog and to ! initialize the state of each control, ie check boxes, radio buttons,etc. cosState = true ! Tell the API to size the CosW window to our dialog gosub CW.AutoSizeDialog cosCWnd$ = cosDlghDlg$ cosState = SW.NORMAL gosub COS.ShowWindow ! Make the dialog visible return
Another difference when using a dialog is that clicking either the OK button or CANCEL button will cause the
dialog to close automatically. All you need to do is to detect that the dialog is closing by calling
CW.CheckAutoModeClosing. If the dialog is closing, it will set CW.ExitEvents to true and your event handler will
not be re-established. When the dialog is closing, if you want to know which button was clicked, you can save its
ID. It is set by CW.ParseEvent into coswParam.
Note: If you want an event other than the clicking of OK or CANCEL to cause the dialog to close, you can call
CW.CloseAutoModeDialog when you get that event. Conversely, if you don’t want the dialog to close
automatically when either or both OK or CANCEL are clicked, you may disable this by handling the event
explicitly. As a matter of fact, if you want to retrieve data from the dialog when OK is clicked you will have to
handle that button explicitly. Just tell the command filter you want to handle that button, and add your code to the
event handler. This gives you total control. The DlgTemp.ibs example handles the OK button explicitly.
Loading Your Dialog
Getting your dialog loaded is really easy. All you need to do is to tell the API the name of your dialog and where to find your .dll. So, at the top of our program, you see:
! Establish BEFORE calling CW.CreateAutoModeDialog or else we'll miss the "dialog is initializing" event eventsub EventHandler CW.Event$ CW.Source$ cosDllNames$ = "DlgTemp.dll" ! DLL filename cosDllDir$ = sub(pstat(PARTITION$),41,3) ! Same dir as this program cosDlgId = IDD.DIALOG1 ! Dialog ID ! If your dialog was designated as “child” it will be modeless. If “popup” it will be modal. gosub CW.CreateAutoModeDialog if cosDlgOpen = FALSE print "Dialog execution failed" go ProgExit endif eventwait
Note: If your program is running on a Comet Anywhere client, the call to CW.CreateAutoModeDialog will
automatically transfer the .dll from the host to the $(CATOOLS) folder on the remote.
In the Resource Editor
The Resource Editor is where you design your dialog and create its controls. Running DPBuild.exe will quickly
generate a template project for you.
When you compile your project to generate the .dll, an ID will be assigned to each control and to the dialog itself.
A control’s ID is what’s assigned to cosCtlID; the dialog’s ID is what’s assigned to cosDlgId. We recommend
using SET statements to give a meaningful name to each ID. As an alternative to entering these IDs manually,
you'll find a program called Inc2Use.exe in the WDL release that will make an include file that declares the IDs for
your IB program. Setup Inc2Use to run as part of your "Post-Build Steps" in your project and your IB include file
will automatically be updated whenever you make a change to your dialog. Note: This will be done for you if you
have created your project through CometDialogProjectBuilder.exe.
Dialog or Direct?
Now that you’ve seen examples of each, which method is best for you? It really is a matter of personal preference. Here are a few thoughts about each method: Dialog
- It is really convenient to be able to create your screens by dragging and dropping the
controls where you want them.
- It's easy to select a group of controls and have them automatically sized and aligned the
same.
- Assigning attributes to a control is simple. A right click on the control pops up a window
with check boxes for the style choices, a place to enter your caption, etc.
- Since the code for creating all the controls is encoded in the .dll, your companion IB
object will be smaller than a similar program written using the direct method. However, the sum of the two pieces will be larger than the single IB object.
- Visual Studio will take care of assigning identifiers to each of your controls for you.
Direct
- You only need to deal with a single development environment.
- You don’t have to package the .dll along with your application. Your IB object contains
everything.
- You can intersperse other GDI objects such as hyperlinks with your controls.
- You can always write debug messages directly to the window.
A Beginner’s Guide to Events and Functions for Selected Windows Controls
A complete list of events for each control can be found in Windows.inc. They are called “notify” or “notification” codes. A complete list of functions for each control can be found in CosWin.ibs. The Demo programs, WinTemp.ibs, and DlgTemp.ibs are released as part of the “DLG” folder.
Control Events Functions Demo Sample Button BN.CLICKED COS.CreateButton any CtlDemo program Check Box BN.CLICKED COS.CreateButton Ctl3.ibs, Dlg3.ibs COS.CheckDlgButton COS.IsDlgButtonChecked Radio Button BN.CLICKED COS.CreateButton Ctl2.ibs, Dlg2.ibs COS.CheckRadioBtn COS.GetCheckedRadioBtn Static COS.CreateStatic Ctl1.ibs Edit cosEN.LOSTFOCUS COS.CreateEdit Ctl5a.ibs, Dlg5a.ibs EN.SETFOCUS COS.EditLimitText List Box LBN.SELCHANGE COS.CreateListBox Ctl4.ibs, Dlg4.ibs LBN.DBLCLK COS.ListAddString COS.ListDelString COS.ListInsertString COS.ListFindString COS.ListGetCount COS.ListResetContent COS.ListSetCurSel COS.ListGetCurSel COS.ListGetText Combo Box CBN.SELCHANGE COS.CreateComboBox Ctl14.ibs, Dlg14.ibs CBN.DBLCLK COS.ComboAddString COS.ComboDeleteString COS.ComboInsertString COS.ComboFindString COS.ComboFindStringExact COS.ComboGetCount COS.ComboResetContent COS.ComboSetCurSel COS.ComboGetCurSel COS.ComboGetText COS.ComboLimitText List View NM.CLICK COS.CreateListControl Ctl10.ibs, Dlg10.ibs NM.DBLCLK COS.ListView.InsertTextColumn NM.RCLICK COS.ListView.SetColumnWidth LVN.COLUMNCLICK COS.ListView.InsertStringItem COS.ListView.SetFullRowSelect COS.ListView.DeleteAllItems COS.ListView.GetNextItem COS.ListView.GetItemText COS.ListView.SortItems All Controls COS.SetDlgItemFocus COS.EnableDlgItem
Each function requires setting of parameters before making the call. To determine how to do this for a given function, either look at the sample code from the CtlDemo or DlgDemo program, or search CosWin.ibs for the function name. Comments provided there explain what is required and what will be returned following the call.