|
External Development Guide: Callable IDL |
|
To build your Microsoft Windows application that calls IDL, you must take the following steps:
idl_export.h into your source code. This include file is found in the external/include subdirectory of the IDL distribution.
IDL.LIB.
IDL.DLL in a directory with your application. See the readme.txt file located in the IDL_DIR/external/callable for more information.The following program demonstrates how to display message text sent from IDL, execute IDL statements entered by a user, and how to obtain data from IDL variables. It performs the following actions:
Each line is numbered to make discussion easier. These numbers are not part of the actual program. The source code for this program can be found in the file simple.c, located in the callable subdirectory of the external subdirectory of the IDL distribution. See the source code for details of the program not printed here.
1 /*-------------------------------------------------------------
2 * simple.c Source code for sample IDL callable application
3 *
4 * Copyright (c) 1992-1995, ITT Visual Information Solutions
9 *--------------------------------------------------------------
*/
10 #include <windows.h>
11 #include <windowsx.h>
12 #include <ctl3d.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include "simple.h"
16 #include "idl_export.h"
17
18 /*-------------------------------------------------------------
19 * WinMain
20 *
21 * This is the required entry point for all windows
applications.
22 *
23 * RETURNS: TRUE if successful
24 *-----------------------------------------------------------*/
25 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE
hInstancePrev,
26 LPSTR lpszCmndline, int nCmdShow)
27 {
28 IDL_INIT_DATA init_data;
29 HWND hwnd;
30 MSG msg;
31
32 // Register the main window class.
33 if (!RegisterWinClass(hInstance)) {
34 return(0);
35 }
36
37 ...
38
39 // Create and display the main window.
40 if ((hwnd = InitMainWindow(hInstance)) == NULL) {
41 return(0);
42 }
43 MainhWnd = hwnd;
44
45 // Register our output function with IDL.
46 IDL_ToutPush(OutFunc);
47
48 // Initialize IDL
49 init_data.options = IDL_INIT_BACKGROUND;
50 init_data.options |= IDL_INIT_HWND;
51 init_data.hwnd = hwnd;
52 if (!IDL_Initialize(&init_data))
53 return(FALSE);
54
55 // Main message loop.
56 while (GetMessage(&msg, NULL, 0, 0)) {
57 TranslateMessage(&msg);
58 DispatchMessage(&msg);
59 }
60
61 return(msg.wParam);
62 }
63
64
65 /*-------------------------------------------------------------
66 * RegisterWinClass
67 *
68 * To create a Main window (TLB in IDL speak). You must first
69 * register the class for that window
70 *
71 * RETURNS: TRUE if successful
72 *-----------------------------------------------------------*/
73 BOOL RegisterWinClass(HINSTANCE hInst)
74 {
75 WNDCLASS wc;
76
77 wc.style = CS_HREDRAW | CS_VREDRAW;
78 wc.lpfnWndProc = MainWndProc;
79 wc.cbClsExtra = 0;
80 wc.cbWndExtra = 0;
81 wc.hInstance = hInst;
82 wc.hIcon = NULL;
83 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
84 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
85 wc.lpszMenuName = NULL;
86 wc.lpszClassName = "Simple";
87
88 if (!RegisterClass(&wc)) {
89 return(FALSE);
90 }
91
92 return(TRUE);
93}
94
95 /*-------------------------------------------------------------
96 * InitMainWindow
97 *
98 * This is where our Main window is created and displayed
99 *
100 * RETURNS: Handle to window
101 *-----------------------------------------------------------*/
102 HWND InitMainWindow(HINSTANCE hInst)
103 {
104 HWND hwnd;
105 CREATESTRUCT cs;
106
107
108 hwnd = CreateWindow("Simple",
109 "Callable IDL Sample Application",
110 WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE,
111 CW_USEDEFAULT,
112 0,
113 600,
114 480,
115 NULL,
116 NULL,
117 hInst,
118 &cs);
119
120 if (hwnd) {
121 ShowWindow(hwnd, SW_SHOWNORMAL);
122 UpdateWindow(hwnd);
123 }
124
125 return(hwnd);
126 }
127
128 /*------------------------------------------------------------
129 * MainWndProc
130 *
131 * The window procedure (event handler) for our main window.
132 * All messages (events) sent to our app are routed through
133 * here
134 * RETURNS: Depends of message.
135 *----------------------------------------------------------*/
136 LRESULT WINAPI MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
137 {
138 static int nDisplayable = 0;
139
140
141 switch (uMsg) {
142 //When our app is first created, we are sent this message.
143 //We take this opportunity to create our child controls and
144 //place them in their desired locations on the window.
145 case WM_CREATE:
146 if (!CreateControls(((LPCREATESTRUCT)lParam)->hInstance, hwnd)) {
147 return(0);
148 }
149 if (!LayoutControls(hwnd)) {
150 return(0);
151 }
152 nDisplayable = GetCharacterHeight(GetDlgItem(hwnd, IDE_COMMANDLOG));
153 break;
154
155 ...
156
157 case WM_DESTROY:
158 PostQuitMessage(1);
159 break;
160
161 //Each time a button or menu item is selected, we get this message
162 case WM_COMMAND:
163 OnCommand(hwnd, LOWORD(wParam), wParam, lParam);
164 return(FALSE);
165
166 //This is a message we send ourselves to indicate the need to
167 //display a text message in our log window.
168 case IDL_OUTPUT:
169 OutputMessage(wParam, lParam, nDisplayable);
170 return(FALSE);
171
172 case WM_CLOSE:
173 IDL_Cleanup(TRUE);
174 return(FALSE);
175
176 default:
177 break;
178 }
179
180 return(DefWindowProc(hwnd, uMsg, wParam, lParam));
181 }
182
183 /*------------------------------------------------------------
184 * OnCommand
185 *
186 * This is the message handle for our WM_COMMAND messages
187 *
188 * RETURNS: FALSE
189 *----------------------------------------------------------*/
190 BOOL OnCommand(HWND hWnd, UINT uId, WPARAM wParam, LPARAM lParam)
191 {
192
193 switch(uId){
194 case IDB_SENDCOMMAND:{
195 LPSTR lpCommand;
196 LPSTR lpOut;
197
198 lpCommand = GlobalAllocPtr(GHND, 256);
199 lpOut = GlobalAllocPtr(GHND, 256);
200 if(!lpCommand)
201 return(FALSE);
202
203 /* First we get the string that is in the input window */
204 GetDlgItemText(hWnd, IDE_COMMANDLINE, lpCommand,
255);
205
206 /* and then clear the window */
207 SetDlgItemText(hWnd, IDE_COMMANDLINE, "");
208
209 lstrcpy(lpOut, "\r\nSent to IDL: ");
210 lstrcat(lpOut, lpCommand);
211
212 /* Send the string to our "log" window */
213 OutFunc(IDL_TOUT_F_NLPOST, lpOut, strlen(lpOut));
214
215 /* then send the string to IDL */
216 IDL_ExecuteStr(lpCommand);
217
218 /* Now clean up */
219 GlobalFreePtr(lpCommand);
220 GlobalFreePtr(lpOut);
221 }
222 break;
223 }
224 return(FALSE);
225 }
226
227 /*------------------------------------------------------------
228 * OutFunc
229 *
230 * This is the output function that receives messages from IDL
231 * and displays them for the user
232 *
233 * RETURNS: NONE
234 *----------------------------------------------------------*/
235 void OutFunc(long flags, char *buf, long n)
236 {
237 static fShowMain = FALSE;
238
239 /* If there is a message, post it to our MAIN window */
240 if (n){
241 SendMessage (MainhWnd, IDL_OUTPUT, 0, (LPARAM)buf);
242 }
243
244 /* If we need to post a new line message... */
245 if (flags & IDL_TOUT_F_NLPOST){
246 SendMessage (MainhWnd, IDL_OUTPUT, 0, (LPARAM)(LPSTR)"\r\n\0");
247 }
248
249 /* This message gets sent to the log window to have it scroll
250 and display the last message at the bottom of the window.
251 With this, the user will always see the last screen full of
252 messages sent
253 */
254 SendMessage (MainhWnd, IDL_OUTPUT, (WPARAM)TRUE,
255 (LPARAM)(LPSTR)"\0");
256
257 return;
258 }
259
260 /*------------------------------------------------------------
261 * OutputMessage
262 *
263 * Here we do the actual display of the text to our log window
264 *
265 * RETURNS: nothing
266 *
267 *----------------------------------------------------------*/
268 void OutputMessage(WPARAM wParam, LPARAM lParam, int nDisplayable)
269 {
270 LRESULT lRet;
271 LONG lBufflen, lNumLines, lFirstView;
272
273 /* Turn off the READONLY bit and postpone redraw */
274 lRet = SendMessage(hwndLog, EM_SETREADONLY, FALSE, 0L);
275 lRet = SendMessage(hwndLog, WM_SETREDRAW, FALSE, 0L);
276
277 /* Get the length of the text in the log window*/
278 lBufflen = SendMessage (hwndLog, WM_GETTEXTLENGTH, 0, 0L);
279 lNumLines = SendMessage (hwndLog, EM_GETLINECOUNT, 0, 0L);
280 lFirstView = SendMessage (hwndLog, EM_GETFIRSTVISIBLELINE, 0, 0L);
281 lRet = SendMessage (hwndLog, EM_SETSEL, lBufflen, lBufflen);
282
283 /* If we are adding text, wParam will be 0 */
284 if(!wParam) {
285 lRet = SendMessage (hwndLog, EM_REPLACESEL, 0, lParam);
286 } else {
287 if (lNumLines > (lFirstView + nDisplayable)){
288 int iLineLen = 0;
289 int iChar;
290 int iLines = 0;
291 lNumLines--;
292 while(!iLineLen){
293 iChar = SendMessage(hwndLog, EM_LINEINDEX,
294 (WPARAM)lNumLines, 0L);
295 iLineLen = SendMessage(hwndLog, EM_LINELENGTH,
296 iChar, 0L);
297 if(!iLineLen)
298 lNumLines--;
299 }
300 iLines = lNumLines-(lFirstView + (nDisplayable - 1));
301 iLines = iLines >= 0 ? iLines : 0;
302 SendMessage (hwndLog, EM_LINESCROLL, 0, (LPARAM)iLines);
303 }
304 }
305
306 /* Set the window to redraw and reset the READONLY bit */
307 lRet = SendMessage(hwndLog, WM_SETREDRAW, TRUE, 0L);
308 lRet = SendMessage(hwndLog, EM_SETREADONLY, TRUE, 0L);
309
310 return;
311 }
The following is a commentary on the program, by line number:
idl_export.h contains the IDL_ function prototypes, IDL specific structures, and IDL constants.
Call IDL_ToutPush() with the address of the output function (OutFunc) as it's only argument. This will register OutFunc as a callback for IDL. IDL will call OutFunc when it needs to display text.
Initialize IDL as a non-interactive session and supply it with the handle to the main window.
Start the windows message loop.
This is the Main window procedure. It will handle any messages that are sent to the main window. This includes WM_COMMAND messages that occur as a result of user interaction with the client controls. In addition, it handles a user defined message called IDL_OUTPUT (the name doesn't matter but this is a clue as to its purpose).
When the user presses either the "Send" or "Quit" buttons, route the message to the OnCommand function.
When we receive an IDL_OUTPUT message, call the function that displays text in the scrolling window (OutputMessage. See line 263).
When we receive the WM_CLOSE message, call IDL_Cleanup() to unlink IDL from our application.
OnCommand handles the WM_COMMAND messages generated when the user clicks on the application's buttons.
Get the IDL command that the user has entered in the single line edit control and store it in a buffer.
Clear the text in the edit control.
Display the command sent to IDL in the output window.
Call IDL_ExecuteStr() with the IDL command retrieved in line 204.
OutFunc is the callback registered with IDL to handle text messages IDL sends to our application. In addition it will handle text from IDL routines that display information, such as PRINT.
OutputMessage handles displaying the text to the output window. Since this window is a multi-line edit control, we have created it as a read-only window. See the source code for additional information on handling this situation.
OutputMessage appends new messages to the existing text in the control.
When the text has been displayed, OutputMessage scrolls the window to display the last line of text in the bottom of the window.
IDL Online Help (March 06, 2007)