Popup Help Windows

Popup Help Windows

In this section, the interesting topic of popup help windows is considered . In visual programming languages, popup help windows are organized by setting appropriate properties for objects located within a container object. Your goal is to develop the mechanism that would allow you to set popup help windows for any window control without using additional libraries. To achieve this, it is necessary to proceed as follows :

  • First, it is necessary to notice that a popup help window is simply a window with predefined properties. Here are those properties: DS_3DLOOK , WS_POPUP , WS_VISIBLE , and WS_BORDER . You can experiment by adding or removing the properties. However, there is one property, without which your goal cannot be achieved. This is the WS_POPUP property. Furthermore, the definition of the popup window in the resource file must not contain the CAPTION property.

  • The display of the popup help window must not change the situation in the dialog. This means that the popup help call must be modeless by calling the CreateDialogIndirect function. Moreover, it is necessary to make provision for resetting the focus to the dialog box. For this purpose, it is enough to call the SetFocus function when needed (see Listing 14.3).

  • Thus, the popup help window is the dialog; consequently, it must have the window function. What should be contained in this function? At the least, it must process the following three events: WM_INITDIALOG , WM_PAINT , and WM_TIMER . Having received the WM_INITDIALOG message, it is necessary to determine the size and position of the popup window. Furthermore, if you assume that the popup window must automatically close after a certain time interval elapses, then it is necessary to set the timer. When the WM_PAINT message is received, it is necessary to output the text into the popup window. If the size of the popup window is set exactly according to the length of the text string that has to be displayed, then the popup window background color will be fully defined by the color of the displayed text. Finally, when the WM_TIMER message arrives, it is necessary to close the popup window.

  • As relates to the help string, everything is more or less clear. Now, you must determine where and how this help will be called. The following approach seems preferable to me: In the main dialog, determine the timer whose function would trace the cursor position. Depending on this position, the popup help window will be either called or closed. The timer function must make provision for the following:

    • It must check the cursor position. If the cursor happens to be over the required element, then it is necessary to call the help. At the same time, it is desirable to make sure that popup windows appear with a certain delay. This can be ensured by introducing a counter call popup help if the counter exceeds a predefined value.

    • When the cursor moves from the area of the required element, the popup help window must be closed.

Listing 14.3 provides a program that demonstrates the described approach. Fig. 14.2 shows a dialog with popup help. Principally, this approach is not the only possible one. After you understand the working principle of this program, you'll be able to invent your own methods of creating popup help windows.

image from book
Figure 14.2: Dialog providing popup help
Listing 14.3: Demonstration of popup help windows
image from book
 // The HINT.RC file // Constant definitions #define WS_SYSMENU           0x00080000L // Window elements must be initially visible #define WS_VISIBLE           0x10000000L // Border around the element #define WS_BORDER            0x00800000L // Elements can be activated using the <TaB> key #define WS_TABSTOP           0x00010000L // Text in the help window is left-aligned #define ES_LEFT              0x0000L // Type of all elements of the window #define WS_CHILD            0x40000000L // Style - Button #define BS_PUSHBUTTON        0x00000000L // Center the button label #define BS_CENTER            0x00000300L // Window type---Popup #define WS_POPUP             0x80000000L // Windows 95-style dialog #define DS_3DLOOK            0x0004L // Dialog box definition DIAL1  DIALOG 0,  0, 240, 100 STYLE  WS_SYSMENU  DS_3DLOOK CAPTION "Window with popup help" FONT 8,  "Arial" { //  Edit  window,  identifier 1  CONTROL "", 1,  "edit", ES_LEFT   WS_CHILD   WS_VISIBLE    WS_BORDER   WS_TABSTOP  ,  100,  5, 130,  12 //  Button,  identifier 2  CONTROL "Exit",  2, "button", BS_PUSHBUTTON   BS_CENTER    WS_CHILD   WS_VISIBLE   WS_TABSTOP,  180,  76, 50,  14 } //  Help  dialog HINTW  DIALOG 0,  0, 240, 8 STYLE  DS_3DLOOK  WS_POPUP   WS_VISIBLE   WS_BORDER FONT 8,  "MS Sans  Serif" { } ; The HINT.INC  file ; Constants ; Help window background color RED     = 255 GREEN   = 255 BLUE    = 150 RGBB    equ (RED or (GREEN shl 8)) or  (BLUE shl 16) ; Foreground color of the popup help window RED     = 20 GREEN   = 20 BLUE    = 20 RGBT    equ (RED or (GREEN shl 8)) or  (BLUE shl 16) ; This message  arrives when the window is closed WM_CLOSE         equ 10h WM_INITDIALOG    equ 110h WM_COMMAND       equ 111h WM_TIMER         equ 113h WM_SETTEXT       equ 0Ch WM_COMMAND       equ 111h WM_PAINT         equ 0Fh ; Prototypes of external procedures IFDEF MASM       EXTERN       CreateDialogParamA@20:NEAR       EXTERN       SetFocus@4:NEAR       EXTERN       lstrcpyA@8:NEAR       EXTERN       DestroyWindow@ 4:NEAR       EXTERN       lstrlenA@4:NEAR       EXTERN       GetDlgItem@8:NEAR       EXTERN       GetCursorPos@4:NEAR       EXTERN       TextOutA@ 20:NEAR       EXTERN       SetBkColor@8:NEAR       EXTERN       SetTextColor@8:NEAR       EXTERN       BeginPaint@8:NEAR       EXTERN       EndPaint@8:NEAR       EXTERN       GetTextExtentPoint32A@16:NEAR     -       EXTERN      MoveWindow@24:NEAR       EXTERN      GetWindowRect@8:NEAR       EXTERN      ReleaseDC@8:NEAR       EXTERN      GetDC@4:NEAR       EXTERN      SendDlgItemMessageA@20:NEAR       EXTERN      ExitProcess@4:NEAR       EXTERN      GetModuleHandleA@4:NEAR       EXTERN      DialogBoxParamA@20:NEAR       EXTERN      EndDialog@8:NEAR       EXTERN      SetTimer@16:NEAR       EXTERN      KillTimer@8:NEAR ELSE       EXTERN      CreateDialogParamA:NEAR       EXTERN      SetFocus:NEAR       EXTERN      lstrcpyA:NEAR       EXTERN      DestroyWindow:NEAR       EXTERN      lstrlenA:NEAR       EXTERN      GetDlgItem:NEAR       EXTERN      GetCursorPos:NEAR       EXTERN      TextOutA:NEAR       EXTERN      SetBkColor:NEAR       EXTERN      SetTextColor:NEAR       EXTERN      BeginPaint:NEAR       EXTERN      EndPaint:NEAR       EXTERN      GetTextExtentPoint32A:NEAR       EXTERN      MoveWindow:NEAR       EXTERN      GetWindowRect:NEAR       EXTERN      ReleaseDC:NEAR       EXTERN      GetDC:NEAR       EXTERN      SendDlgItemMessageA:NEAR       EXTERN      ExitProcess:NEAR       EXTERN      GetModuleHandleA:NEAR       EXTERN      DialogBoxParamA:NEAR       EXTERN      EndDialog:NEAR       EXTERN      SetTimer:NEAR       EXTERN      KillTimer:NEAR       CreateDialogParamA@2O = CreateDialogParamA       SetFocus@4 = SetFocus       lstrcpyA@8 = lstrcpyA       DestroyWindow@4 = DestroyWindow       lstrlenA@4 = lstrlenA       GetDlgItem@8 = GetDlgItem       GetCursorPos@4 =GetCursorPos       TextOutA@20 = TextOutA       SetBkColor@8 = SetBkColor       SetTextColor@8 = SetTextColor       BeginPaint@8 = BeginPaint       EndPaint@8 = EndPaint       GetTextExtentPoint32A@16 = GetTextExtentPoint32A       MoveWindow@24 = MoveWindow       GetWindowRect@8 = GetWindowRect       ReleaseDC@8  = ReleaseDC       GetDC@4 = GetDC       SendDlgItemMessageA@20 = SendDlgItemMessageA       ExitProcess@4 = ExitProcess       GetModuleHandleA@4 = GetModuleHandleA       DialogBoxParamA@20 = DialogBoxParamA       EndDialog@8  = EndDialog       SetTimer@16  = SetTimer       KillTimer@8  = KillTimer ENDIF ;  Structures ;  Message  structure MSGSTRUCT  STRUC       MSHWND         DD ?       MSMESSAGE      DD ?       MSWPARAM       DD ?       MSLPARAM       DD ?       MSTIME         DD ?       MSPT           DD ? MSGSTRUCT ENDS ; Window size stricture RECT  STRUC       L  DD ?       T  DD ?       R  DD ?       B  DD ? RECT  ENDS ; Size structure SIZ  STRUC    X DD ?    Y DD ? SIZ  ENDS ;  Structure for BeginPaint PAINTSTR STRUC   hdc    DWORD  0   fErase DWORD  0   left   DWORD  0   top    DWORD  0   right  DWORD  0   bottom DWORD  0   fRes   DWORD 0   fIncUp DWORD 0   Reserv DB 32 dup(0) PAINTSTR ENDS ; Structure for getting the cursor position POINT  STRUC    X DD ?    Y DD ? POINT  ENDS ; The HINT.ASM file .586P ; Flat memory model .MODEL FLAT, stdcall include hint.inc ; INCLUDELIB directives for the linker IFDEF MASM ; For the LINK.EXE linker      includelib C:\masm32\lib\user32.lib      includelib C:\masm32\lib\kernel32.lib      includelib C:\masm32\lib\gdi32.lib ELSE ;  For the TLINK32.EXE linker      includelib c:\tasm32\lib\import32.lib ENDIF ;----------------------------------------------- ; Data segment _DATA SEGMENT       MSG       MSGSTRUCT <?>       HINST     DD 0 ; Application descriptor       PA        DB "DIAL1",  0       HIN       DB "HINTW",  0       XX        DD ?       YY        DD ? ;--------------------------       R1        RECT  <?>       R2        RECT  <?>       S         SIZ   <?>       PS        PAINTSTR <?>       PT        POINT  <?> ; Descriptors for popup windows for the first and the second elements       H1        DD 0       H2        DD 0 ; Help string        HINTS      DB 60  DUP(?) ; List of help strings        HINT1      DB "Edit string", 0        HINT2      DB "Exit button", 0 ; For temporarily storing the device context        DC        DD ? ; Counter        P1        DD ? _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the application  descriptor       PUSH  0       CALL  GetModuleHandleA@4       MOV   [HINST], EAX ;--------------------------------       PUSH  0       PUSH  OFFSET WNDPROC       PUSH  0       PUSH  OFFSET PA       PUSH  [HINST]       CALL  DialogBoxParamA@20       CMP   EAX,  -1       JNE   KOL KOL: ;--------------------------------       PUSH  0       CALL  ExitProcess@4 ;-------------------------------- ;  Window procedure ;  Position of  parameters in the stack ;  [EBP+014H]   ;  LPARAM ;  [EBP+10H]    ;  WAPARAM ;  [EBP+0CH]    ;  MES ;  [EBP+8]      ;  HWND WNDPROC   PROC       PUSH  EBP       MOV   EBP,  ESP       PUSH  EBX       PUSH  ESI       PUSH  EDI ;----------------       CMP   DWORD PTR [EBP+0CH],  WM_CLOSE       JNE   L1 ; The reaction to closing the window ; Delete the timer L4:       PUSH  2 ; Timer identifier       PUSH  DWORD PTR [EBP+08H]       CALL  KillTimer@8 ; Close the dialog       PUSH  0       PUSH  DWORD PTR [EBP+08H]       CALL  EndDialog@8       JMP   FINISH L1:       CMP   DWORD PTR [EBP+0CH],  WM_INITDIALOG       JNE   L2 ; Startup initialization ; Set the timer       PUSH  OFFSET TIMPROC       PUSH  500 ; 0.5-second interval       PUSH  2 ; Timer identifier       PUSH  DWORD PTR [EBP+08H]       CALL  SetTimer@16       JMP   FINISH L2:       CMP   DWORD PTR [EBP+0CH],  WM_COMMAND       JNE   L3 ; Exit button?       CMP   WORD PTR [EBP+10H],  2       JNE   L3       JMP   L4 L3: FINISH:       POP   EDI       POP   ESI       POP   EBX       POP   EBP       MOV   EAX,  0       RET   16 WNDPROC     ENDP ;----------------------------------------------- ; Timer procedure ; Position of  parameters  in  the  stack ; [EBP+014H]   ;  LPARAM -  Time elapsed since Windows startup ; [EBP+10H]    ;  WAPARAM - Timer  identifier ; [EBP+0CH]    ;  WM_TIMER ; [EBP+8]      ;  HWND TIMPROC   PROC       PUSH EBP       MOV  EBP,  ESP ; Get the cursor position       PUSH OFFSET PT       CALL GetCursorPos@4 ; Store the coordinates       MOV  EAX,  PT.X       MOV  XX,  EAX       MOV  EAX,  PT.Y       MOV  YY,  EAX : Get  the elements positions : Edit window       PUSH 1       PUSH DWORD PTR  [EBP+08H]       CALL GetDlgItem@8       PUSH OFFSET R1       PUSH EAX       CALL GetWindowRect@8 ; Exit button       PUSH 2       PUSH DWORD PTR  [EBP+08H]       CALL GetDlgItem@8       PUSH OFFSET R2       PUSH EAX       CALL GetWindowRect@8 ; Increase the counter       INC  P1       MOV  ECX,  XX       MOV  EDX,  YY ; Check  the conditions   .IF  H1==0 && P1>5     .IF  EDX<=R1.B && EDX>=R1.T && ECX>=R1.L  && ECX<=R1.R ; Prepare the  string       PUSH OFFSET HINT1       PUSH OFFSET HINTS       CALL lstrcpyA@8 ; Create the popup dialog       PUSH  0       PUSH  OFFSET HINT       PUSH  DWORD PTR [EBP+08H]       PUSH  OFFSET HIN       PUSH  [HINST]       CALL  CreateDialogParamA@20       MOV   H1,  EAX ; Set the focus       PUSH  DWORD PTR [EBP+08H]       CALL  SetFocus@4 ; Reset the counter to zero       MOV   P1,  0       JMP   _END     .ENDIF   .ENDIF   .IF H1!=0    .IF (EDX>R1.B   EDX<R1.T)    (ECX<R1.L   ECX>R1.R) ; Delete the popup window because of the  change  of  the cursor position       PUSH  H1       CALL  DestroyWindow@4       MOV   H1,  0       JMP   _END    .ENDIF   .ENDIF   .IF H2==0 && P1>5    .IF EDX<=R2.B && EDX>=R2.T &&  ECX>=R2.L &&  ECX<=R2.R ; Prepare the string       PUSH  OFFSET HINT2       PUSH  OFFSET HINTS       CALL  lstrcpyA@8 ; Create the popup dialog       PUSH  0       PUSH  OFFSET HINT       PUSH  DWORD PTR [EBP+08H]       PUSH  OFFSET HIN       PUSH  [HINST]       CALL  CreateDialogParamA@20       MOV   H2,  EAX ; Set the focus       PUSH  DWORD PTR [EBP+08H]       CALL  SetFocus@4 ; Reset the counter to zero       MOV   P1,  0       JMP   _END    .ENDIF   .ENDIF   .IF H2!=0    .IF (EDX>R2.B   EDX<R2.T)    (ECX<R2.L   ECX>R2.R) ; Delete the popup window because of the change of the cursor position       PUSH  H2       CALL  DestroyWindow@4       MOV   H2,  0       JMP   _END    .ENDIF   .ENDIF ; Restore the stack _END:       POP   EBP       RET   16 TIMPROC     ENDP ; Window procedure of popup help HINT PROC       PUSH  EBP       MOV   EBP, ESP       CMP   DWORD  PTR [EBP+0CH], WM_INITDIALOG       JNE   NO_INIT ; Initialization ; Get  the context       PUSH  DWORD  PTR [EBP+08H]       CALL  GetDC@4       MOV   DC,  EAX ; Get  the string length       PUSH  OFFSET HINTS       CALL  lstrlenA@4 ; Get  the string length and width       PUSH  OFFSET S       PUSH  EAX       PUSH  OFFSET HINTS       PUSH  DC       CALL  GetTextExtentPoint32A@16 ; Set the position and the size of the popup window       PUSH  0       PUSH  S.Y       ADD   S.X,  2       PUSH   S.X       SUB  YY,   20       PUSH  YY       ADD   XX, 10       PUSH  XX       PUSH  DWORD PTR [EBP+08H]       CALL  MoveWindow@24 ; Close the context       PUSH  DC       PUSH  DWORD PTR [EBP+08H]       CALL  ReleaseDC@8 ; Set the timer       PUSH  0       PUSH  6000 ; 6-second interval       PUSH  3 ; Timer identifier       PUSH  DWORD PTR [EBP+08H]       CALL  SetTimer@16       JMP   FIN NO_INIT: CMP   DWORD PTR [EBP+0CH],  WM_PAINT JNE   NO_PAINT ; Redraw the window ; Get the context       PUSH  OFFSET PS       PUSH  DWORD PTR [EBP+08H]       CALL  BeginPaint@8       MOV   DC, EAX ; Set the foreground and background colors       PUSH  RGBB       PUSH  EAX       CALL  SetBkColor@8       PUSH  RGBT       PUSH  DC       CALL  SetTextColor@8 ; Outpur the text       PUSH  OFFSET HINTS       CALL  lstrlenA@4       PUSH  EAX       PUSH  OFFSET HINTS       PUSH  0       PUSH  0       PUSH  DC       CALL  TextOutA@20 ; Close the context       PUSH  OFFSET PS       PUSH  DWORD PTR  [EBP+08H]       CALL  EndPaint@8       JMP   FIN NO_PAINT:       CMP   DWORD PTR  [EBP+0CH], WM_TIMER       JNE   FIN ; Process the timer event ; Delete the timer close the dialog ; The popup help window is closed because the ; 6-second timer has expired       PUSH  3       PUSH  DWORD PTR [EBP+08H]       CALL  KillTimer@8       PUSH  DWORD PTR [EBP+08H]       CALL  DestroyWindow@4 FIN:       POP    EBP       RET    16 HINT ENDP _TEXT ENDS END START 
image from book
 

The program presented in Listing 14.3 requires some comments.

First, note that this program uses conditional run-time constructs. This approach is logical. It is justified by the needs to reduce the program size and improve its readability. Nesting of the conditional constructs and placement of braces are based on the desire to reduce the string length yet preserve program compatibilitythe possibility of translating it using both MASM32 and TASM32. As I have already mentioned, these two assemblers differ significantly, especially when speaking about macros.

To translate this program, issue the following commands using MASM32:

 ML /c /coff /DMASM hint.asm     RC hint.rc     LINK /SUBSYSTEM:WINDOWS hint.obj hint.res 

To translate this program, issue the following commands using TASM32:

 TASM32 /ml hint.asm     BRCC32 hint.rc     TLINK32 -aa hint.obj,,,,,hint.res 

As you probably understand, the timer procedure checks the cursor position every 0.5 seconds. If the cursor is positioned over some element (e.g., edit window or button) and popup help has not been called yet ( H1 or H2 is different from zero), then popup help is called. At the same time, the value of the counter ( P1 ) is taken into account to ensure that the popup help window appears with a certain delay. If the procedure is next called when the cursor is positioned outside the element and the popup window still displayed, it will be closed. However, this mechanism does not account for a cursor that quickly moves from one element to another. In this case, there could be two popup help windows on the screen. The first popup must be closed immediately.

In Listing 14.3, the dialog box has only two elements: the edit window and the button. I wanted to note that popup help can be specified for any element. The position of the popup window in relation to the cursor can be easily regulated . You can change it yourself.

The GetCursorPos function places the cursor position in coordinates relative to the screen. No problems will arise here, because the GetWindowsRec function also places the position of the window element in absolute coordinates. Before that, you have to determine the window descriptor using the GetDlgItem function.



The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net