Announcement

Collapse
No announcement yet.

getting focus

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

  • getting focus

    Basic windows stuff is eluding me today. Here I have a treeview in a modeless child dialog which sends the item text to a richedit control on the parent dialog when the item is selected or checked. But the treeview retains focus, whereas I want the richedit control to keep focus, so that I can enter text into it and "drop in" item text from the treeview when it is selected. How can I do this, please?

    This code will compile & run with PB Win 8.04, no fancy libraries.

    Code:
    '
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "commctrl.inc"
    #INCLUDE "comdlg32.inc"
    #INCLUDE "RichEdit.INC"
    
    %idc_DBB_lab1          = 1317
    %IDC_DBB_TREEVIEW      = 1320
    %IDC_main_bn           = 1321
    %IDC_MAIN_TB           = 1323
    %IDC_DBB_CLR_BN        = 1324
    
    
    DECLARE FUNCTION TVBrowser(BYVAL hParent AS DWORD) AS LONG
    DECLARE FUNCTION mainwindow  ( BYVAL hParent AS DWORD ) AS LONG
    
    GLOBAL ghEditWnd AS DWORD
    GLOBAL gchecked, gunchecked      AS DWORD
    
    '------------------------------------------------------------------------------
    ' thank you Chris Boss!
    SUB CopyToClipboard(BYVAL Txt AS STRING)
        LOCAL hClip AS LONG, lpAddress AS LONG
        Txt = Txt + CHR$(0)
        hClip=GlobalAlloc(%GMEM_MOVEABLE, LEN(Txt))
        lpAddress=GlobalLock(hClip)
        POKE$ lpAddress, Txt
        GlobalUnlock hClip
        IF OpenClipboard(%NULL) THEN
            EmptyClipboard
            SetClipboardData %CF_TEXT, hClip
            CloseClipboard
        ELSE
            GlobalFree hClip
        END IF
    END SUB
    '------------------------------------------------------------------------------
    FUNCTION SampleTreeViewInsertItem(BYVAL hTree AS DWORD, BYVAL hParent AS DWORD, sItem AS STRING) AS LONG
        LOCAL tTVItem   AS TV_ITEM
        LOCAL tTVInsert AS TV_INSERTSTRUCT
    
        IF hParent THEN
            tTVItem.mask      = %TVIF_CHILDREN OR %TVIF_HANDLE
            tTVItem.hItem     = hParent
            tTVItem.cchildren = 1
            TreeView_SetItem hTree, tTVItem
        END IF
    
        tTVInsert.hParent              = hParent
        tTVInsert.Item.Item.mask       = %TVIF_TEXT
        tTVInsert.Item.Item.pszText    = STRPTR(sItem)
        tTVInsert.Item.Item.cchTextMax = LEN(sItem)
    
        FUNCTION = TreeView_InsertItem(hTree, tTVInsert)
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION SampleTreeView(BYVAL hDlg AS DWORD, BYVAL lID AS LONG, BYVAL lCount AS LONG) AS LONG
        LOCAL i       AS LONG
        LOCAL j       AS LONG
        LOCAL k       AS LONG
        LOCAL hCtl    AS DWORD
        LOCAL hRoot   AS DWORD
        LOCAL hParent AS DWORD
    
        CONTROL HANDLE hDlg, lID TO hCtl
    
        FOR i = 1 TO lCount
            hRoot = SampleTreeViewInsertItem(hCtl, %NULL, USING$("Root#", i))
            CALL SampleTreeViewInsertItem(hCtl, hRoot, "*")
            FOR j = 1 TO lCount
                hParent = SampleTreeViewInsertItem(hCtl, hRoot, USING$("Item#", j))
                CALL SampleTreeViewInsertItem(hCtl, hParent, "*")
                FOR k = 1 TO lCount
                    CALL SampleTreeViewInsertItem(hCtl, hParent, USING$("SubItem#_.#", j, k))
                NEXT k
            NEXT j
        NEXT i
    END FUNCTION
    '------------------------------------------------------------------------------
    ' tear through the treeview unchecking checkboxes
    SUB UnCheckAll ( hTVWnd AS DWORD, dwitem AS DWORD)
        LOCAL TreeItem AS TV_ITEM
        LOCAL i        AS LONG
        LOCAL hitm, checked  AS DWORD
    
        TreeItem.hItem = dwItem
        WHILE TreeItem.HItem <> %NULL
            TreeItem.mask       = %TVIF_STATE OR %TVIF_HANDLE
            TreeItem.stateMask  = %TVIS_STATEIMAGEMASK
            TReeView_getItem( hTVWnd, BYVAL VARPTR(TreeItem)) ' get item
            hitm = TreeView_GetChild ( hTVWnd, TreeItem.hItem)
            IF hitm <> %NULL THEN
                unCheckAll ( hTVWnd, hItm)
            END IF
            IF (TreeItem.state AND gchecked) = gchecked THEN
                TreeItem.state = gunchecked
                TreeView_setItem( hTVWnd, BYVAL VARPTR(TreeItem)) ' set state = unchecked
            END IF
            TreeItem.HItem = Treeview_GetNextSibling(hTVWnd, TreeItem.hItem)
        WEND
    
    END SUB
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION TVBrowser_dialogProc()
        STATIC hmenu, hparent, hTVWnd AS DWORD
        LOCAL r             AS rect
        LOCAL s, s1         AS STRING
        LOCAL hDB, hedit, l, lresult AS LONG
        LOCAL sz            AS ASCIIZ*256
        LOCAL psz           AS ASCIZ PTR
        LOCAL lpNmh         AS NMHDR PTR
        LOCAL lpTV          AS NM_TREEVIEW PTR
        LOCAL treeItem      AS TV_ITEM
        LOCAL pTVITEM       AS tv_item PTR
        LOCAL TVdi          AS TV_DISPINFO
        LOCAL TVht          AS TV_HITTESTINFO
        LOCAL DWPOS         AS DWORD
        STATIC bITEMmode AS LONG ' boolean
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                hTVWnd = getdlgitem(CBHNDL, %IDC_DBB_TREEVIEW )
                CONTROL ADD LABEL, CBHNDL, %idc_DBB_lab1,"check boxes press button" & s ,5, 2, 175,12
                SampleTreeView(CBHNDL, %IDC_DBB_TREEVIEW, 20)
             '
             CASE %WM_NOTIFY
                 lpNmh = CBLPARAM
                 SELECT CASE @lpNmh.Code
    
                    CASE %NM_CLICK
                      IF @lpNmh.idFrom = %IDC_DBB_TREEVIEW THEN
                        ' This will ensure that when the user either clicks the checkbox or the
                        ' buttons (+/-) the item/node will be selected. You get a strange flashing
                        ' experience if you do not do this, comment out this code and then use a
                        ' checkbox or the buttons and see what occurs. (found this code on MSDN)
                        dwPos = GetMessagePos          ' Get the mouse position
                        TVht.pt.x = LO(WORD, dwPos)    ' Store the mouse x pos in the hittest udt
                        tvht.pt.y = HI(WORD, dwPos)    ' Store the mouse y pos in the hittest udt
                        MapWindowPoints(%HWND_DESKTOP, @LPnMH.hwndFrom, TVht.pt, 1)
                        ' clicked on the checkbox?
                        ' Get the TreeView item/node returned in the hittest udt member of hItem
                        TreeView_HitTest( hTVWnd, BYVAL VARPTR(TVht))
                        ' examine the flags to see if the checkbox was hit
                        TreeItem.mask       = %TVIF_TEXT
                        TreeItem.cchTextMax = SIZEOF(sz)
                        TreeItem.psztext    = VARPTR(sz)
                        TreeItem.hItem      = TVHT.Hitem
                        TreeView_GetItem (hTVWnd, BYVAL VARPTR(TreeItem))
                        copyToClipboard ( TRIM$(sz))
                        SendMessage ghEditWnd, %WM_PASTE, 0, 0 ' paste text from clipboard
                      END IF
                 END SELECT
    
            CASE %WM_LBUTTONDOWN
                SendMessage CBHNDL, %WM_NCLBUTTONDOWN, %HTCAPTION, BYVAL %NULL  ' force drag
    
            CASE %WM_COMMAND
            SELECT CASE CBCTL  ' <- look at control's id
               CASE %IDC_DBB_CLR_BN
                  IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                      dwpos = TreeView_GetRoot( hTVWnd)
                      Uncheckall ( hTVWnd, dwPos)
                  END IF
            END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION TVBrowser(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
        LOCAL hDlg  AS DWORD
        LOCAL s AS STRING
    
        DIALOG NEW hParent, "", 10, 100, 140, 220, %WS_POPUP OR %WS_CHILD OR %WS_THICKFRAME OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_TOOLWINDOW OR _
            %WS_EX_TOPMOST OR %WS_EX_LEFT OR %WS_EX_LTRREADING TO hdlg
        DIALOG  SET COLOR   hDlg, -1, RGB(255, 255, 155)
    
        CONTROL ADD "SysTreeView32", hDlg,%IDC_DBB_TREEVIEW, "SysTreeView32_1", 5, 15, 135, 175, %WS_CHILD OR %WS_VISIBLE OR _
            %WS_TABSTOP OR %TVS_HASBUTTONS OR %TVS_HASLINES OR %TVS_CHECKBOXES OR %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS, _
            %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    
            CONTROL ADD BUTTON,  hDlg, %IDC_DBB_CLR_BN, "UNCHK ALL", 0, 190, 70, 15
    
        DIALOG SHOW MODELESS hDlg, CALL TVBrowser_dialogProc TO lRslt
    
        FUNCTION = lRslt
    END FUNCTION
    '--------------------------------------------------------------------------------
    CALLBACK FUNCTION mainwindowproc()
        LOCAL sz AS ASCIZ * 64
        LOCAL l AS LONG
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ghEditWnd = getdlgitem(CBHNDL,%IDC_MAIN_TB)
                TVBrowser (0)
                l = sendmessage( ghEditWnd, %EM_GETEVENTMASK, 0, 0)
                sendmessage ghEditWnd, %EM_SETEVENTMASK, 0, l OR %ENM_CHANGE
    
            CASE %WM_LBUTTONDOWN
                SendMessage CBHNDL, %WM_NCLBUTTONDOWN, %HTCAPTION, BYVAL %NULL  ' force drag
    
            CASE %WM_NOTIFY
                BEEP
                LOCAL nh AS NMHDR PTR
                nh =  CBLPARAM                                'More Richedit events
                IF CBCTL = %IDC_MAIN_TB THEN                  'Get caret movement
                   SELECT CASE @nh.code
                   END SELECT
                END IF
    
            CASE %WM_COMMAND
                SELECT CASE CBCTL  ' <- look at control's id
                   CASE %IDC_MAIN_BN
                       IF CBCTLMSG = %BN_CLICKED THEN DIALOG END CBHNDL, 0
                   CASE %IDC_MAIN_TB
                       IF CBCTLMSG = %EN_CHANGE THEN BEEP
                END SELECT
        END SELECT
    END FUNCTION
    '--------------------------------------------------------------------------------
    FUNCTION mainwindow  ( BYVAL hParent AS DWORD ) AS LONG
        LOCAL lRslt AS LONG
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "", 160, 100, 330, 200, %WS_POPUP OR %WS_THICKFRAME OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR _
            %WS_EX_TOPMOST OR %WS_EX_LEFT OR %WS_EX_LTRREADING TO hdlg
    
        CONTROL ADD "RichEdit", hDlg, %IDC_MAIN_TB, "", 5,5,320,177, _
                %WS_CHILD  OR %WS_CLIPSIBLINGS  OR %WS_VISIBLE OR %ES_MULTILINE OR %WS_VSCROLL OR _
                %WS_HSCROLL OR %ES_AUTOVSCROLL OR %ES_AUTOHSCROLL OR %ES_WANTRETURN, %WS_EX_CLIENTEDGE
        CONTROL ADD BUTTON,  hDlg, %IDC_main_bn, "exit", 300, 185, 30, 15
    
        DIALOG SHOW MODAL hdlg CALL mainwindowproc
    END FUNCTION
    '=================================================================================
    FUNCTION PBMAIN () AS LONG
    
        InitCommonControls
        gchecked   = 2: SHIFT LEFT gchecked,   12
        gunchecked = 1: SHIFT LEFT gunchecked, 12
    '
      '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      'Load the Richedit dll.
      '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      IF LoadLibrary("RICHED32.DLL") = 0 THEN
         MSGBOX "Unable to load RICHED32.DLL - sorry, no point in continuing",,"File missing!"
         EXIT FUNCTION  'is this correct? At least it seems to terminate properly..
      END IF
      '
    '
          mainwindow(0)
    END FUNCTION

  • #2
    A richedit control doesn't have to have focus for you to programmatically insert text into it. If you want it to have focus so that the user can type into it, can't you sinply insert a CONTROL SET FOCUS at an appropriate point?

    Comment


    • #3
      You may run into trouble trying to set focus to another control from within the notification message (NM_CLICK). Try "posting" a message to your callback using a user defined message and then set the focus.

      For example:

      At the top of your code add the following:
      Code:
      %MSG_SETFOCUS = %WM_USER + 100
      Add the following at the end of your NM_CLICK message handler. PostMessage will allow the NM_CLICK to fully complete.
      Code:
      PostMessage CbHndl, %MSG_SETFOCUS, 0, 0
      Add the following in your TVBrowser_dialogProc callback function:
      Code:
              Case %MSG_SETFOCUS
                   SetFocus ghEditWnd
      Paul Squires
      FireFly Visual Designer (for PowerBASIC Windows 10+)
      Version 3 now available.
      http://www.planetsquires.com

      Comment


      • #4
        Thanks Paul, that works!

        Comment

        Working...
        X