Announcement

Collapse
No announcement yet.

Owner Drawn Status Bar

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

  • Owner Drawn Status Bar

    I did a bunch of searches in PB for "Owner Drawn Status", "Draw Status", and other variations for an Owner Drawn Status bar, and the only usable result is Jose Roca's EXCELLENT example Statusbar wrapper.

    code to place in your Window Callback
    Code:
        CASE %WM_DRAWITEM
           ' Ownerdraw statusbar
           IF WPARAM = %ID_STATUSBAR THEN
              DSS_StatusbarDrawItem hWnd, LPARAM           '<--- See Jose Roca's statusbar wrapper
    and the wrapper function itself
    Code:
    SUB DSS_StatusbarDrawItem (BYVAL hDlg AS  DWORD, BYVAL lParam AS LONG)
    
        LOCAL lpdis AS DRAWITEMSTRUCT PTR
        LOCAL zp AS ASCIIZ PTR
        LOCAL hBrush AS DWORD
        LOCAL clrFg AS DWORD
        LOCAL clrBk AS DWORD
    
        lpdis = lParam
    ''msgbox str$(@lpdis.CtlType)
    '    InflateRect @lpdis.rcItem, -1, -1 'test with smaller rect for "better" look
        DECR @lpdis.rcItem.nRight          'or maybe this is better..?
        DECR @lpdis.rcItem.nBottom
    
        clrBk = %BLUE
        clrFg = %WHITE
    
    
        SELECT CASE @lpdis.itemID
           CASE 1 : clrBk = %YELLOW : clrFg = %RED
           CASE 2 : clrBk = %RED : clrFg = %YELLOW
           CASE 3 : clrBk = RGB(0,160,0) : clrFg = %WHITE
        END SELECT
    
        hBrush = CreateSolidBrush(clrBk)
        FillRect @lpdis.hDC, @lpdis.rcItem, hBrush
        SetBkColor @lpdis.hDC, clrBk
        SetTextColor @lpdis.hDC, clrFg
        DeleteObject hBrush
    
        zp = @lpdis.itemData
    '    DrawText @lpdis.hDC, @zp, LEN(@zp), @lpdis.rcItem, %DT_CENTER OR %DT_SINGLELINE OR %DT_VCENTER
        DrawText @lpdis.hDC, @zp, LEN(@zp), @lpdis.rcItem, %DT_SINGLELINE OR %DT_VCENTER
    
    END SUB
    ' ==========================================================================
    Although an excellent wrapper and great example to work with, (worked perfect without having to modify code), I wanted to take things a step farther and more generic (if only to understand how the code works).

    According to Docs (If I read them right) then WPARAM = the control you want to change, and LPARAM = DRAWITEMSTRUCT

    Breaking down to not use the callback, but a function directly called, so far I have come up with
    Code:
    SUB DSS_StatusbarDrawItem (BYVAL HwndWindow AS DWORD, BYVAL DrawItem AS DRAWITEMSTRUCT, ForeGroundColor AS DWORD, BackGroundColor AS DWORD)
        LOCAL hBrush AS DWORD
         LOCAL zp AS ASCIIZ PTR
    '    InflateRect @lpdis.rcItem, -1, -1 'test with smaller rect for "better" look
        DECR DrawItem.rcItem.nRight          'or maybe this is better..?
        DECR DrawItem.rcItem.nBottom
        hBrush = CreateSolidBrush(BackGroundColor)
        FillRect DrawItem.hDC, DrawItem.rcItem, hBrush
        SetBkColor DrawItem.hDC, BackGroundColor
        SetTextColor DrawItem.hDC, ForeGroundColor
        DeleteObject hBrush
        zp = DrawItem.itemData
    '    DrawText @lpdis.hDC, @zp, LEN(@zp), @lpdis.rcItem, %DT_CENTER OR %DT_SINGLELINE OR %DT_VCENTER
        DrawText DrawItem.hDC, @zp, LEN(DrawItem.itemData), DrawItem.rcItem, %DT_SINGLELINE OR %DT_VCENTER
    END SUB
    ' ==========================================================================
    However I am having a lil' bit of trouble understanding each of the elements of the UDT for DrawItemStruct, that I hope someone can help clear up.

    I tried checking values of each from the original working code, but nothing matches up with the defined values in Win32Api.Inc, so I am TOTALLY confused

    My thoughts on the elements are:
    type DRAWITEMSTRUCT
    CtlType = ODT_BUTTON, 'Owner-drawn button
    ODT_COMBOBOX 'Owner-drawn combo box
    ODT_LISTBOX 'Owner-drawn list box
    ODT_LISTVIEW 'List view control
    ODT_MENU 'Owner-drawn menu item
    ODT_STATIC 'Owner-drawn static control
    ODT_TAB 'Tab control
    '<--- CtlType shows absolutely nothing for StatusBar, so I am guessing Static label is used in statusbar?
    CtlID = Specifies the identifier of the combo box, list box, button, or static control. This member is not used for a menu item.
    '<--- So if I declare HwndStatus = 1000 then is CtlId 1000? or the Windows handle that results from creation? or 0 since not a combo, list, button, or label?
    itemID = Specifies the menu item identifier for a menu item (it goes on from there, but no mention of a statusbar
    '<--- In this case if I split the statusbar into parts, is this the value I plug in for say part 8?????
    itemAction = ODA_DRAWENTIRE 'The entire control needs to be drawn.
    ODA_FOCUS 'Check if has focus
    ODA_SELECT 'The selection status has changed.
    '<--- Since I am not setting focus or selecting, but just changing colors, I assume I have to pass ODA_DRAWENTIRE?
    itemState = ODS_CHECKED 'The menu item is to be checked. This bit is used only in a menu.
    ODS_COMBOBOXEDIT The drawing takes place in the selection field (edit control) of an ownerdrawn combo box.
    ODS_DEFAULT The item is the default item.
    ODS_DISABLED The item is to be drawn as disabled.
    ODS_FOCUS The item has the keyboard focus.
    ODS_GRAYED The item is to be grayed. This bit is used only in a menu.
    ODS_SELECTED The menu item's status is selected.
    hwndItem = Identifies the control for combo boxes, list boxes, buttons, and static controls. For menus, this member identifies the menu containing the item.
    '<--- So is this the value I plug in for my part of the statusbar?????
    HDC hDC;
    '<--- For the time being until I clear up the other parts, I assume this is the Hdc of the statusbar? (or would it be a part of the statusbar?
    RECT rcItem; <--- For the time being I assume this will be the rect of the part I wish to change
    DWORD itemData; '<---Not sure if this will be my text? or some other value?
    End Type

    Hopefully not toooooo confusing, but I am just trying to understand the docs when the docs do not even state anything to do with a statusbar.....which also makes me wonder, if it works, does it mean I am using the right api? or just lucking out that it works?
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

  • #2
    Is that a Statusbar control (Classname="msctls_statusbar32"), or a STATIC control used as a statusbar?

    (Show the line of code used to create that control).

    The "official" status bar control is one of the Microsoft Common Controls, and slighltly different rules apply to many of the Common Controls.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Basically the code for the StatusBar is
      Code:
                  hStatus = CreateStatusWindow(%WS_CHILD OR %WS_VISIBLE OR %SBS_SIZEGRIP, "", hWnd, %ID_STATUSBAR)
                  DIM prts(0 TO 11) AS LONG
                  GetClientRect hStatus, rc
      '*** Dimension the parts
                  prts(0) = rc.nRight * 0.05     : prts(1) = rc.nRight * 0.15     'Port:Portnum
                  prts(2) = rc.nRight * 0.16     : prts(3) = rc.nRight * 0.25     'Space:Baud
                  prts(4) = rc.nRight * 0.35     : prts(5) = rc.nRight * 0.36     'Baudratenum:Space
                  prts(6) = rc.nRight * 0.43     : prts(7) = rc.nRight * 0.78     'Status:PortStatus
                  prts(8) = rc.nRight * 0.79     : prts(9) = rc.nRight * 0.85     'Space:VXM
                  prts(10) = rc.nRight * 0.95     : prts(11) = rc.nRight * 1      'VXMStatus:Space
                  Sendmessage hStatus, %SB_SETPARTS, 12, VARPTR(prts(0))
      And my 1st poor attempt
      Code:
                          DrawItem.CtlType = %ODT_STATIC
                          DrawItem.CtlId = hStatus
                          DrawItem.ItemId = 7
                          DrawItem.ItemAction = %ODA_DRAWENTIRE
                          DrawItem.ItemState = %ODS_SELECTED
                          DrawItem.HwndItem = hStatus
                          DrawItem.hDC = GetDC(hStatus)
                          GetClientRect(hStatus, DrawItem.rcItem)
                          @zp = " Port Closed" + " - " + "Already Open in Other App"
                          DrawItem.ItemData = VARPTR(zp)
                          DSS_StatusbarDrawItem(hStatus, DrawItem, %WHITE, %RED)
      Which obviously is not quite right, because I am only guessing at the correct values. (Currently the whole statusbar (except 1 part) show red background, with white blocks (I am guessing are nulls) rather than the text and just 1 part being red, but like I said, I am guessing at what value should be what?
      Cliff Nichols
      Member
      Last edited by Cliff Nichols; 3 Apr 2008, 10:32 AM. Reason: Left stuff off
      Engineer's Motto: If it aint broke take it apart and fix it

      "If at 1st you don't succeed... call it version 1.0"

      "Half of Programming is coding"....."The other 90% is DEBUGGING"

      "Document my code????" .... "WHYYY??? do you think they call it CODE? "

      Comment


      • #4
        Code:
        DrawItem.CtlType = %ODT_STATIC
        DrawItem.CtlId = hStatus
        ....
        ?????

        You don't set the members of the DRAWITEMSTUCT; Windows sets those for your use.

        I have the text for owner-drawn status bars for this on my disk version of SDK, let me see if I can find it online and give you a link...

        found it.. http://msdn2.microsoft.com/en-us/lib...28(VS.85).aspx

        Basically you have to send the SB_SETTEXT message with the SBT_OWNERDRAW value in uflag; and the control will then send you a WM_DRAWITEM with appropriate DRAWITEMSTRUCT to use for that status bar part. This step seems to be missing from your code.

        According to the doc, Windows will re-send WM_DRAWITEM messages for each statusbar part whenever that part needs to be redrawn.

        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Thank you MCM....that cleared a bit up (although in this case my solution is "Cheating" of sorts) since I noticed even when I almost had things correct, that callback would erase and repaint.

          So for the time being (until I can understand more fully) I took Jose's premise and small modification to set different colors depending on what I want to show the user.

          Only bad part, is to the color-blind (but from my understanding, they can tell the differences between stoplight colors (if not just the position), my idea is partially following suit.

          Red = Error (OMG...something is wrong)
          Yellow = Communication (or something is changing)
          Green = All is fine (....no need to panic....ALLLL IS FINNNNE.....Do NOT PANIC) '<--- Sorry bad spin on Animal House quote

          Although I consider it "Cheating" it works....(I just hate not having the time to handle and understand what I am handling without "Mama M$ cleaning up behind me")
          Engineer's Motto: If it aint broke take it apart and fix it

          "If at 1st you don't succeed... call it version 1.0"

          "Half of Programming is coding"....."The other 90% is DEBUGGING"

          "Document my code????" .... "WHYYY??? do you think they call it CODE? "

          Comment


          • #6
            Do you have this working?

            If so, maybe a demo in source code forum would be a nice thing to do.

            If not, beg me and I'll create one. Could be a 'fun' little program I could knock off in an hour or so.


            MCM
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              I can whip something up a bit later, but at the moment the one drawback I have (and I KNOWWWWW it must be something simple) is what color is the default Windows/Dialog background color?
              I tried %GREY and %LTGREY and even tried %COLOR_BTNFACE (But that was almost black)

              I know its something simple to do with a brush though
              Engineer's Motto: If it aint broke take it apart and fix it

              "If at 1st you don't succeed... call it version 1.0"

              "Half of Programming is coding"....."The other 90% is DEBUGGING"

              "Document my code????" .... "WHYYY??? do you think they call it CODE? "

              Comment


              • #8
                GetSysColor[Brush] (%COLOR_WINDOW) I think.

                (somewhere there's something about using system colors to do with when you have to add or subtract one, too, but I can't remember that right now).
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Thank you MCM...I see what I was doing wrong (add one to the :doh count)
                  (I was passing GetSysColor(%COLOR_WINDOW) as a parameter, and not the results of GetSysColor(%COLOR_WINDOW)

                  I was working on a pure DDT idea vs pure SDK idea for an example, (for VB Refugees), but immediately I ran into problems...(maybe because I am learning more SDK these days, and forgetting DDT)

                  Hopefully this weekend I can find time to break it all down into a tutorial 101 kinda thing
                  Engineer's Motto: If it aint broke take it apart and fix it

                  "If at 1st you don't succeed... call it version 1.0"

                  "Half of Programming is coding"....."The other 90% is DEBUGGING"

                  "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                  Comment

                  Working...
                  X