Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

PB/DLL 6.0, BUILT-IN POPUP HELP

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PB/DLL 6.0, BUILT-IN POPUP HELP

    Code:
    ' There has been some samples posted on how to use hhctrl.ocx for
    ' context sensitive popup help, but unfortunately, that also means
    ' using a control that wasn't available in Win95 (plus it's MS bloat..)
    '
    ' Following is similar popup help, by code. It pops up a transparent
    ' dialog, draws info "label" + shadow and looks pretty much the same.
    ' Advantage is, you won't have to answer support questions on why your
    ' popup help doesn't work in your user's Win95 systems.. (and definitely
    ' leaner on memory than MS's 380KB ocx, that gives same result..  
    '
    ' For use in your own code, copy/paste HelpPopup and HelpPopupProc.
    ' See PBMAIN and DlgProc for how to set up and use.
    '
    ' Public Domain by Borje Hagsten, September 2001.
    '
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Declares
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    %ID_CB1    = %WM_USER + 200
    %ID_CTXHLP = %WM_USER + 210
     
    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
    DECLARE CALLBACK FUNCTION HelpPopupProc
    DECLARE SUB HelpPopup(BYVAL hParent AS LONG, zTxt AS ASCIIZ)
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main entrance - create dialog and controls, etc
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION PBMAIN () AS LONG
      LOCAL hDlg AS LONG
     
      DIALOG NEW 0, "Popup help demo",,, 147, 50, _
                 %WS_CAPTION OR %WS_SYSMENU OR %DS_CONTEXTHELP, 0 TO hDlg
     
      CONTROL ADD BUTTON,  hDlg, %IDOK,     "&Ok",      4,  4,  70, 14
      CONTROL ADD BUTTON,  hDlg, %IDCANCEL, "&Cancel", 74,  4,  70, 14
      CONTROL ADD COMBOBOX, hDlg, %ID_CB1, , 4, 22, 140, 100, %CBS_DROPDOWNLIST
      CONTROL ADD LABEL, hDlg, 333, "Right-click on controls..", 4, 38, 140, 12, %SS_CENTER
     
      'set id's for context sensitive help
      CALL SetWindowContextHelpId(GetDlgItem(hDlg, %IDOK), %IDOK)
      CALL SetWindowContextHelpId(GetDlgItem(hDlg, %IDCANCEL), %IDCANCEL)
      CALL SetWindowContextHelpId(GetDlgItem(hDlg, %ID_CB1), %ID_CB1)
     
      DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main callback
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION DlgProc() AS LONG
      SELECT CASE CBMSG
         CASE %WM_INITDIALOG
            LOCAL hPopup AS LONG
            STATIC CtrlHlp AS LONG 'static variable, to hold id for clicked control
     
         CASE %WM_COMMAND
            SELECT CASE LOWRD(CBWPARAM)
               CASE %IDOK     : BEEP
               CASE %IDCANCEL : DIALOG END CBHNDL
     
               CASE %ID_CTXHLP         'This one handles result of popup menu.
                  SELECT CASE CtrlHlp  'Send these on to HelpPopup sub.
                     CASE %IDOK     : HelpPopup CBHNDL, "Press Ok to beep.."
                     CASE %IDCANCEL : HelpPopup CBHNDL, "Press Cancel to close dialog."
                     CASE %ID_CB1   : HelpPopup CBHNDL, "Combo box, listing everything I like about MS Windows.."
                  END SELECT
            END SELECT
     
         ' WM_CONTEXTMENU handles right-click on controls with context help id set.
         ' Result is handled in WM_COMMAND above (under %ID_CTXHLP)
         CASE %WM_CONTEXTMENU
            CtrlHlp = GetWindowContextHelpId(CBWPARAM) 'the id we set in PBMAIN
            IF CtrlHlp > 0 THEN                        'if we have id, show popup menu
               MENU NEW POPUP TO hPopup
               MENU ADD STRING, hPopup, "What's this?", %ID_CTXHLP, %MF_ENABLED
               TrackPopupMenu hPopup, %TPM_LEFTALIGN OR %TPM_RIGHTBUTTON, _
                              LOWRD(CBLPARAM), HIWRD(CBLPARAM), 0, CBHNDL, BYVAL 0
     
            END IF
     
         ' WM_HELP handles result of question mark click + following click on a control.
         ' Here I pass it on to the ID_CTXHLP menu handling under WM_COMMAND
         CASE %WM_HELP
            LOCAL lphi AS HELPINFO pointer
            lphi    = CBLPARAM
            CtrlHlp = @lphi.iCtrlId
            SendMessage CBHNDL, %WM_COMMAND, MAKLNG(%ID_CTXHLP, %BN_CLICKED), 0
     
      END SELECT
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Show help popup dialog. Note - dialog is bigger than text-part, because we
    ' also want to draw bottom/right "shadow" for nice 3-D effect.
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    SUB HelpPopup(BYVAL hParent AS LONG, zTxt AS ASCIIZ)
      LOCAL hDlgHelp AS LONG, pt AS POINTAPI
      LOCAL hDC AS LONG, hFont AS LONG, rh AS LONG, rw AS LONG, rc AS RECT
     
      GetCursorPos pt
     
      DIALOG NEW hParent, "",,, 107, 28, %WS_POPUP TO hDlgHelp
     
      SetWindowText hDlgHelp, zTxt
     
      GetClientRect hDlgHelp, rc                        'get dialog's size
      rc.nLeft   = rc.nLeft + 5                         'adjust rectangle for text
      rc.nTop    = rc.nTop + 5
      rc.nRight  = rc.nRight - 12
      rc.nBottom = rc.nBottom - 12
     
      hDC = GetDc(hDlgHelp)
      hFont = SelectObject(hDC, GetStockObject(%ANSI_VAR_FONT)) 'must use same font in DC
      rw = rc.nRight
      rh = DrawText(hDC, zTxt, LEN(zTxt), rc, %DT_CALCRECT OR %DT_EXTERNALLEADING) 'calculate size
     
      IF rc.nRight > rw * 1.2 THEN         'if above 20% increase in width
         GetClientRect hDlgHelp, rc        'get original size and calculate with wordbreak instead
         rc.nLeft   = rc.nLeft + 5         '(change to your own liking - this is set for my needs)
         rc.nTop    = rc.nTop + 5
         rc.nRight  = rc.nRight - 12
         rc.nBottom = rc.nBottom - 12
         rh = DrawText(hDC, zTxt, LEN(zTxt), rc, %DT_CALCRECT OR %DT_WORDBREAK OR %DT_EXTERNALLEADING)
      END IF
      hFont = SelectObject(hDC, hFont)
      ReleaseDc hDlgHelp, hDC
      
      DIALOG PIXELS hDlgHelp, pt.x, pt.y TO UNITS pt.x, pt.y
      DIALOG PIXELS hDlgHelp, rc.nRight + 14, rh + 18 TO UNITS rc.nRight, rh
     
      DIALOG SET LOC hDlgHelp, pt.x - rc.nRight / 2, pt.y - rh + 12
      DIALOG SET SIZE hDlgHelp, rc.nRight, rh
     
      DIALOG SHOW MODAL hDlgHelp CALL HelpPopupProc
     
    END SUB
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Help popup's callback procedure. Here info text + shadow is drawn, etc.
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    CALLBACK FUNCTION HelpPopupProc
      SELECT CASE CBMSG
         CASE %WM_INITDIALOG
            LOCAL I AS LONG, J AS LONG, hDC AS LONG, hBrush AS LONG, hPen AS LONG, hFont AS LONG
            LOCAL zTxt AS ASCIIZ * 1024, rc AS RECT, ps AS PAINTSTRUCT
            SetCapture CBHNDL
     
         CASE %WM_ERASEBKGND : FUNCTION = 1 : EXIT FUNCTION 'make dialog transparent
     
         CASE %WM_PAINT
            hDC = BeginPaint(CBHNDL, ps)
            GetClientRect CBHNDL, rc                        'get control's size
            GetWindowText CBHNDL, zTxt, 1024                'get control's text
     
            'Have tried creating a hollow brush with every other pixel set, to
            'create hollow shadow fast, but no success. Should be possible, like
            'in Windows shutdown, but how? No biggie, since we only draw small
            'areas here - so following does the job fast enough.
     
            'BOTTOM SHADOW
            FOR I = rc.nBottom - 7 TO rc.nBottom
               IF I MOD 2 = 0 THEN
                  FOR J = 7 TO rc.nRight STEP 2
                     SetPixelV hDC, J, I, GetSysColor(%COLOR_3DDKSHADOW)
                  NEXT
               ELSE
                  FOR J = 6 TO rc.nRight STEP 2
                     SetPixelV hDC, J, I, GetSysColor(%COLOR_3DDKSHADOW)
                  NEXT
               END IF
            NEXT
     
            'RIGHT SHADOW
            FOR I = 6 TO rc.nBottom - 8
               IF I MOD 2 THEN
                  FOR J = rc.nRight - 7 TO rc.nRight STEP 2
                     SetPixelV hDC, J, I, GetSysColor(%COLOR_3DDKSHADOW)
                  NEXT
               ELSE
                  FOR J = rc.nRight - 6 TO rc.nRight STEP 2
                     SetPixelV hDC, J, I, GetSysColor(%COLOR_3DDKSHADOW)
                  NEXT
               END IF
            NEXT
     
            'DRAW "LABEL"
            hBrush = SelectObject(hDC, GetSysColorBrush(%COLOR_INFOBK)) 'Select brush into device context
            hPen = CreatePen(%PS_SOLID, 1, GetSysColor(%COLOR_INFOTEXT))
            hPen = SelectObject(hDC, hPen)
            Rectangle hDC, rc.nLeft, rc.nTop, rc.nRight - 6, rc.nBottom - 6
            DeleteObject SelectObject(hDC, hPen)
     
            hPen = CreatePen(%PS_SOLID, 1, GetSysColor(%COLOR_3DFACE))
            hPen = SelectObject(hDC, hPen)
            Rectangle hDC, rc.nLeft + 1, rc.nTop + 1, rc.nRight - 7, rc.nBottom - 7
            DeleteObject SelectObject(hDC, hPen)
     
            'DRAW TEXT in "LABEL"
            CALL SetBkMode(hDC, %TRANSPARENT)                    'Set text background
     
            hFont = SelectObject(hDC, GetStockObject(%ANSI_VAR_FONT))
            CALL SetTextColor(hDC, GetSysColor(%COLOR_INFOTEXT)) 'Set text color
            rc.nLeft   = rc.nLeft + 5
            rc.nTop    = rc.nTop + 5
            rc.nRight  = rc.nRight - 12
            rc.nBottom = rc.nBottom - 12
            DrawText hDC, zTxt, LEN(zTxt), rc, %DT_EDITCONTROL OR %DT_WORDBREAK
     
            'CLEAN UP
            hFont = SelectObject(hDC, hFont)
            CALL SelectObject(hDC, hBrush)                            'Select old brush back
            EndPaint CBHNDL, ps
            FUNCTION = 0 : EXIT FUNCTION
     
         ' are these enough? Think so - at least popup seems to close on all events.
         CASE %WM_KEYDOWN, %WM_KEYUP, %WM_CHAR, %WM_SYSKEYDOWN, %WM_SYSKEYUP, %WM_HOTKEY, _
              %WM_LBUTTONDOWN, %WM_RBUTTONDOWN, %WM_MBUTTONDOWN, %WM_KILLFOCUS
             ReleaseCapture
             DIALOG END CBHNDL
     
      END SELECT
    END FUNCTION

    ------------------
Working...
X