Announcement

Collapse
No announcement yet.

Textbox Drawing

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

  • Textbox Drawing

    Is it possible to draw on a textbox? I've got an application I'm designing for user input. It has a lot of textboxes, and I'd like to be able to draw a label for each textbox inside the textbox (on the bottom). I started doing this with a custom control, and while I'm really happy with the drawing portion, it's taking a lot of work to handle everything the textbox control already does.

    What I want to do is just take the bottom 1/3rd of a textbox, use it for drawing only, draw the label name, restrict the textbox from displaying its text there, and restrict the caret from displaying in this bottom 1/3rd section.

    Code:
    /--------------------\
    |                            |
    |                            |
    | name                    |
    \--------------------/
    I've searched textbox draw on here and Google, but am not finding a whole lot. I think I'm thinking of listviews or something, but I was hoping I can do this with textboxes also. Does anyone know if this is possible and what I need to research to make it happen?

    Thanks!

    -John
    LOCAL MyEMail AS STRING
    MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")

  • #2
    >a label for each textbox inside the textbox (on the bottom

    Why not just put an edit (textbox) control immediately above a static (label) control?

    You can paint the label control's background to match the textbox's background (see WM_CTLCOLORSTATIC notification message, return GetStockOject (%WHITE_BRUSH) )and no one will ever know your 'one' control is actually 'two' controls.

    ???

    Of course, the listview is not a bad idea, Either. you only allow editing on rows 0,2,4... and reserve rows 1,3,5... for the the label.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      It is possible.
      Dominic Mitchell
      Phoenix Visual Designer
      http://www.phnxthunder.com

      Comment


      • #4
        Here is a quick sample.

        Code:
        '###############################################################################
        '                             Phoenix Visual Designer
        '                              Generated source code
        '###############################################################################
        
        '                                Acknowledgements
        ' José Roca:
        ' For his ground breaking work which interfaces low-level COM and
        ' PowerBASIC-COM automation.
        '
        ' Jeffrey Richter:
        ' For his original implementation of a layout algorithm which positions
        ' controls in a window based on a set of rules.
        
        #DIM ALL
        #REGISTER NONE
        #COMPILE EXE
        #OPTION VERSION4
        
        #INCLUDE "WIN32API.INC"
        
        '=========================== [ Control Identifiers ] ===========================
        
        ' Form1
        %IDD_FORM1                                  = 100
        %IDC_FORM1_EDIT1                            = 101
        
        '====================== [ Global Variable Declarations ] =======================
        
        GLOBAL  ghInstance    AS DWORD    ' handle of the application instance
        
        '-------------------------------------------------------------------------------
        '
        ' PROCEDURE: WinMain
        ' PURPOSE:   Program entry point, calls initialization function, processes
        '            message loop.
        '
        '-------------------------------------------------------------------------------
        
        FUNCTION WINMAIN _
          ( _
          BYVAL hInstance     AS DWORD, _       ' handle of current instance
          BYVAL hPrevInstance AS DWORD, _       ' handle of previous instance(not used in Win32)
          BYVAL pszCmdLine    AS ASCIIZ PTR, _  ' address of command line
          BYVAL nCmdShow      AS LONG _         ' show state of window
          ) AS LONG
        
          LOCAL szClassName     AS ASCIIZ * %MAX_PATH   ' class name
          LOCAL twcx            AS WNDCLASSEX           ' class information
          LOCAL tmsg            AS tagMsg               ' message information
          LOCAL hWnd            AS DWORD                ' handle of main window
          LOCAL hWndModeless    AS DWORD                ' handle of the current active window
        
          ' Save the handle of the application instance
          ghInstance = hInstance
        
          ' Register the Form1 window
          szClassName        = "Form1_Class"
          twcx.cbSize        = SIZEOF(twcx)                               ' size of WNDCLASSEX structure
          twcx.style         = %CS_DBLCLKS                                ' class styles
          twcx.lpfnWndProc   = CODEPTR(Form1_WndProc)                     ' address of window procedure used by class
          twcx.cbClsExtra    = 0                                          ' extra class bytes
          twcx.cbWndExtra    = 0                                          ' extra window bytes
          twcx.hInstance     = ghInstance                                 ' instance of the process that is registering the window
          twcx.hIcon         = LoadIcon(%NULL, BYVAL %IDI_APPLICATION)    ' handle of class icon
          twcx.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)        ' handle of class cursor
          twcx.hbrBackground = %COLOR_BTNFACE + 1                         ' brush used to fill background of window's client area
          twcx.lpszMenuName  = %NULL                                      ' resource identifier of the class menu
          twcx.lpszClassName = VARPTR(szClassName)                        ' class name
          twcx.hIconSm       = %NULL                                      ' handle of small icon shown in caption/system Taskbar
          IF ISFALSE RegisterClassEx(twcx) THEN
            FUNCTION = %TRUE
            EXIT FUNCTION
          END IF
        
          ' Create the Form1 window
          hWnd = CreateWindowEx(%WS_EX_WINDOWEDGE, _                                          ' extended styles
                                "Form1_Class", _                                              ' class name
                                "Text box drawing", _                                         ' caption
                                %WS_OVERLAPPEDWINDOW OR %WS_VISIBLE, _                        ' window styles
                                139, 131, _                                                   ' left, top
                                360, 374, _                                                   ' width, height
                                %NULL, %NULL, _                                               ' handle of owner, menu handle
                                ghInstance, BYVAL %NULL)                                      ' handle of instance, creation parameters
          ' If window could not be created, return "failure"
          IF ISFALSE hWnd THEN
            FUNCTION = %FALSE
            EXIT FUNCTION
          END IF
        
          ' Make the window visible; update its client area
          ShowWindow hWnd, nCmdShow
          UpdateWindow hWnd
        
          ' Main message loop of program.
          ' Acquire and dispatch messages until a WM_QUIT message is received.
          WHILE ISTRUE GetMessage(tmsg, BYVAL %NULL, 0, 0)
            hWndModeless = phnxGetFormHandle(GetFocus())
            IF (ISFALSE hWndModeless) OR (ISFALSE IsDialogMessage(hWndModeless, tmsg)) THEN
              TranslateMessage tmsg
              DispatchMessage tmsg
            END IF
          WEND
        
          FUNCTION = tmsg.wParam
        
        END FUNCTION
        
        '-------------------------------------------------------------------------------
        '
        ' PROCEDURE: Form1_WndProc
        ' PURPOSE:   Processes messages for the Form1 window.
        '
        '-------------------------------------------------------------------------------
        
        FUNCTION Form1_WndProc _
          ( _
          BYVAL hWnd    AS DWORD, _ ' window handle
          BYVAL uMsg    AS DWORD, _ ' type of message
          BYVAL wParam  AS DWORD, _ ' first message parameter
          BYVAL lParam  AS LONG _   ' second message parameter
          ) EXPORT AS LONG
        
          LOCAL hWndChild   AS DWORD    ' handle of child window
          LOCAL hFont       AS DWORD    ' handle of font used by form
        
          SELECT CASE uMsg
            CASE %WM_COMMAND
        
              SELECT CASE LOWRD(wParam)
                CASE %IDC_FORM1_EDIT1
                  IF HIWRD(wParam) = %EN_CHANGE THEN
                  END IF
        
                CASE %IDCLOSE
                  IF HIWRD(wParam) = %BN_CLICKED THEN
                    PostMessage hWnd, %WM_CLOSE, 0, 0
                  END IF
              END SELECT
        
            CASE %WM_SETFOCUS
              ' Set the keyboard focus to the first control that is
              ' visible, not disabled, and has the WS_TABSTOP style
              SetFocus GetNextDlgTabItem(hWnd, %NULL, %FALSE)
        
            CASE %WM_DESTROY
              PostQuitMessage 0
              FUNCTION = %FALSE
              EXIT FUNCTION
        
            CASE %WM_CREATE
              ' Create font used by container
              hFont = GetStockObject(%DEFAULT_GUI_FONT)
        
              ' Create the Edit1 edit control
              hWndChild = CreateWindowEx(%WS_EX_CLIENTEDGE, _                                 ' extended styles
                                         "Edit", _                                            ' class name
                                         "Once upon a time", _                                ' caption
                                         %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _         ' window styles
                                         %ES_LEFT OR %ES_AUTOHSCROLL, _                       ' class styles
                                         55, 50, _                                            ' left, top
                                         211, 36, _                                           ' width, height
                                         hWnd, %IDC_FORM1_EDIT1, _                            ' handle of parent, control ID
                                         ghInstance, BYVAL %NULL)                             ' handle of instance, creation parameters
              ' Subclass the control
              SetProp hWndChild, "OLDWNDPROC", SetWindowLong(hWndChild, %GWL_WNDPROC, CODEPTR(Form1_Edit1_SubclassProc))
              SendMessage hWndChild, %WM_SETFONT, hFont, %TRUE
        
              ' Create the Close text button
              hWndChild = CreateWindowEx(%NULL, _                                             ' extended styles
                                         "Button", _                                          ' class name
                                         "Close", _                                           ' caption
                                         %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _         ' window styles
                                         %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, _       ' class styles
                                         130, 295, _                                          ' left, top
                                         76, 26, _                                            ' width, height
                                         hWnd, %IDCLOSE, _                                    ' handle of parent, control ID
                                         ghInstance, BYVAL %NULL)                             ' handle of instance, creation parameters
              SendMessage hWndChild, %WM_SETFONT, hFont, %TRUE
        
              FUNCTION = %FALSE
              EXIT FUNCTION
          END SELECT
        
          FUNCTION = DefWindowProc(hWnd, uMsg, wParam, lParam)
        
        END FUNCTION
        
        '-------------------------------------------------------------------------------
        '
        ' PROCEDURE: Form1_Edit1_SubclassProc
        ' PURPOSE:   Processes messages for the subclassed Edit window.
        '
        '-------------------------------------------------------------------------------
        
        FUNCTION Form1_Edit1_SubclassProc _
          ( _
          BYVAL hWnd    AS DWORD, _ ' control handle
          BYVAL uMsg    AS DWORD, _ ' type of message
          BYVAL wParam  AS DWORD, _ ' first message parameter
          BYVAL lParam  AS LONG _   ' second message parameter
          ) EXPORT AS LONG
        
          LOCAL trc             AS RECT
          LOCAL trcWin          AS RECT
          LOCAL ptnccsp         AS NCCALCSIZE_PARAMS PTR
          LOCAL lpOldWndProc    AS DWORD    ' address of original window procedure
          LOCAL hDC             AS DWORD
          LOCAL hFontOld        AS DWORD
          LOCAL dwBkModeOld     AS DWORD
          LOCAL cyEdge          AS LONG
          LOCAL lMsgResult      AS LONG
        
          lpOldWndProc = GetProp(hWnd, "OLDWNDPROC")
        
          SELECT CASE uMsg
            CASE %WM_DESTROY
              ' Remove control subclassing
              SetWindowLong hWnd, %GWL_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")
        
            CASE %WM_NCCALCSIZE
              ptnccsp = lParam
              ' We will create space for the label area by increasing the
              ' height of the frame on the bottom side
              GetWindowRect hWnd, trc
              lMsgResult = DefWindowProc(hWnd, %WM_NCCALCSIZE, wParam, lParam)
              @ptnccsp.rgrc(0).nBottom  = @ptnccsp.rgrc(0).nBottom - (trc.nBottom - trc.nTop) / 3
              FUNCTION = lMsgResult
              EXIT FUNCTION
        
            CASE %WM_NCPAINT
              hDC = GetWindowDC(hWnd)
              ' Calculate the bounding rectangle of the label area
              ' adjusted to the coordinate space of the window dc
              GetWindowRect hWnd, trcWin
              GetClientRect hWnd, trc
              MapWindowPoints hWnd, %NULL, BYVAL VARPTR(trc), 2
              cyEdge = trc.nTop - trcWin.nTop
              trc.nTop    = trc.nBottom
              trc.nBottom = trcWin.nBottom - cyEdge
              OffsetRect trc, -trcWin.nLeft, -trcWin.nTop
        
              ' Brush the background
              FillRect hDC, trc, %COLOR_3DSHADOW + 1
        
              hFontOld    = SelectObject(hDC, SendMessage(hWnd, %WM_GETFONT, 0, 0))
              dwBkModeOld = SetBkMode(hDC, %TRANSPARENT)
              DrawText hDC, "Hello", -1, trc, %DT_CENTER OR %DT_VCENTER
        
              SetBkMode hDC, dwBkModeOld
              SelectObject hDC, hFontOld
              ReleaseDC hWnd, hDC
              ' Let Windows paint the rest of the frame
        
            CASE %WM_SETFONT
              lMsgResult = CallWindowProc(lpOldWndProc, hWnd, %WM_SETFONT, wParam, lParam)
              ' Force a WM_NCCALCSIZE message to be sent to the window
              SetWindowPos hWnd, %NULL, 0, 0, 0, 0, %SWP_NOZORDER OR %SWP_NOMOVE OR %SWP_NOSIZE OR %SWP_FRAMECHANGED
              FUNCTION = lMsgResult
              EXIT FUNCTION
          END SELECT
        
          FUNCTION = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
        
        END FUNCTION
        Dominic Mitchell
        Phoenix Visual Designer
        http://www.phnxthunder.com

        Comment


        • #5
          Wow. That is awesome and exactly what I was hoping for. I wasn't aware of the WM_NC* messages before. I've tried this with other controls (datetimepicker, richedit, textbox, listbox) and it works great, but when I try it with a combobox it doesn't work. I was guessing this was due to the fixed height so I tried to set it up to display the text on the left, but it had some weird effects. I was reading that you can do ownerdrawn stuff with comboboxes, but it looks like it only applies to the dropdown list. Is there any way to pull off the same effect for a combobox or would I probably have to draw the name into the top row on the dropdown list or something?

          Thanks!

          -John
          LOCAL MyEMail AS STRING
          MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")

          Comment


          • #6
            Is there any way to pull off the same effect for a combobox
            No. The combo box is a unique beast in the land of Windows.
            You can use your suggestion or roll your own combo box.
            Dominic Mitchell
            Phoenix Visual Designer
            http://www.phnxthunder.com

            Comment

            Working...
            X