Overlapping StatusBar text

Windows specific forum
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Overlapping StatusBar text

Post by breeze4me »

There is a problem drawing text in a field with #PB_StatusBar_Right or #PB_StatusBar_Center set.
See the image below.
Image

Code: Select all

If OpenWindow(0, 0, 0, 440, 50, "StatusBar", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(90)
    AddStatusBarField(100)
    AddStatusBarField(#PB_Ignore)
    AddStatusBarField(100)
  EndIf
  
  StatusBarText(0, 0, "Area normal")
  StatusBarText(0, 1, "Area borderless", #PB_StatusBar_BorderLess)
  StatusBarText(0, 2, "Area right", #PB_StatusBar_Right) 
  StatusBarText(0, 3, "Area centered", #PB_StatusBar_Center)
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Fred
Administrator
Administrator
Posts: 18199
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Overlapping StatusBar text

Post by Fred »

After investigation, it seems like a Windows issue. We use a tab character to center it and a double tab to right align it as it's the standard way to do that, but Windows seems to ignore the clipping when those are set. I don't want to introduce ownerdrawn items for right/centered text because I know it will introduce other issues, so I guess we will have to live with that (you can use WindowBounds() to ensures your status bar doesn't go too small).
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Overlapping StatusBar text

Post by breeze4me »

Okay, this issue doesn't seem to have an easy solution.
The code below is a workaround using the MS Detours library.

Image

Code: Select all

EnableExplicit

Import "User32.lib"
  DrawTextExW(hdc, *lpchText, cchText.l, *lprc, format.l, *lpdtp)
EndImport

Prototype DrawTextEx(hdc, *lpchText, cchText.l, *lprc, format.l, *lpdtp)
Global DrawTextEx__.DrawTextEx = @DrawTextExW()

Import "detours.lib"
  DetourTransactionBegin.l()
  DetourTransactionCommit.l()
  DetourUpdateThread.l(hThread)
  DetourAttach.l(*ppPointer, pDetour)
  DetourDetach.l(*ppPointer, pDetour)
EndImport

Procedure My_DrawTextEx(hdc, *lpchText, cchText.l, *lprc.RECT, format.l, *lpdtp)
  Protected iResult, hWnd, rt.RECT, i, hRgn, *Buffer
  
  If format & #DT_CALCRECT <> #DT_CALCRECT And *lpchText
    hWnd = WindowFromDC_(hdc)
    If hWnd
      *Buffer = AllocateMemory(64)
      If *Buffer
        GetClassName_(hWnd, *Buffer, 30)
        If CompareMemory(*Buffer, @"msctls_statusbar32", 36)
          i = CountString(PeekS(*lpchText), Chr($200B))
          If i > 0
            i - 1
            SendMessage_(hWnd, #SB_GETRECT, i, @rt)
            hRgn = CreateRectRgnIndirect_(rt)
            If hRgn
              SaveDC_(hdc)
              SelectClipRgn_(hdc, hRgn)
              iResult = DrawTextEx__(hdc, *lpchText, cchText, *lprc, format, *lpdtp)
              RestoreDC_(hdc, -1)
              DeleteObject_(hRgn)
              
              FreeMemory(*Buffer)
              ProcedureReturn iResult
            EndIf
          EndIf
        EndIf
        FreeMemory(*Buffer)
      EndIf
    EndIf
  EndIf
  ProcedureReturn DrawTextEx__(hdc, *lpchText, cchText, *lprc, format, *lpdtp)
EndProcedure

If DetourTransactionBegin() = #NO_ERROR
  If DetourUpdateThread(GetCurrentThread_()) = #NO_ERROR
    If DrawTextEx__
      If DetourAttach(@DrawTextEx__, @My_DrawTextEx()) <> #NO_ERROR
        Debug "Detours Error: DrawTextEx__"
      EndIf
    EndIf
    DetourTransactionCommit()
  EndIf
EndIf

Procedure My_StatusBarText(StatusBar, Field, Text.s, Appearance = 0)
  Protected i, HiddenString.s
  For i = 0 To Field
    HiddenString + Chr($200B)
  Next
  If Appearance
    StatusBarText(StatusBar, Field, Text + HiddenString, Appearance)
  Else
    StatusBarText(StatusBar, Field, Text + HiddenString)
  EndIf
EndProcedure

Macro StatusBarText(StatusBar, Field, Text, Appearance = 0)
  My_StatusBarText(StatusBar, Field, Text, Appearance)
EndMacro



If OpenWindow(0, 0, 0, 440, 50, "StatusBar", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(90)
    AddStatusBarField(100)
    AddStatusBarField(#PB_Ignore) ; automatically resize this field
    AddStatusBarField(100)
  EndIf
  
  StatusBarText(0, 0, "Area normal")
  StatusBarText(0, 1, "Area borderless", #PB_StatusBar_BorderLess)
  StatusBarText(0, 2, "Area right", #PB_StatusBar_Right) 
  StatusBarText(0, 3, "Area centered", #PB_StatusBar_Center)
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Post Reply