Hyphenation in Windows/PB MessageRequesters

Everything else that doesn't fall into one of the other PB categories.
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Hyphenation in Windows/PB MessageRequesters

Post by boddhi »

Hello,

Does anyone know how Windows and PB handle hyphenation of strings in message boxes?
I've been wondering about this for a long time, but I've never found any precise information.

I've noticed that, whereas some applications can display strings of varying character lengths on a single line, PB does it on several lines. These applications didn't give me the impression of using anything other than the classic Windows dialog boxes (but maybe I'm wrong...).
Under PB, I tried with strings without spaces or with non-breaking spaces, but they were inevitably cut "very" short without any particular logic (except perhaps the length in pixels?), even when there were non-breaking spaces.

Thank you for giving me more light on the subject..,
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Axolotl
Addict
Addict
Posts: 837
Joined: Wed Dec 31, 2008 3:36 pm

Re: Hyphenation in Windows/PB MessageRequesters

Post by Axolotl »

HI boddhi,
sorry that I cannot answer your question. Instead I did some research on the topic.
Here you can see the results.
It looks like the size of the messagebox (messagerequester) and the controls (gadgets) are responsible.

Code: Select all

;/===  
;| Some experimental code by Axolotl 
;| (w/o having followed my coding guidelines) 
;| 
;| Update: Compare MessageRequester vs. Messagebox_ 
;\--- 

EnableExplicit 

#Caption$   = "Very Long Text" 

Global LongText$ 
Global AdditionalWidth = 0  ; add to message box width (see what happend) 


; ---------------------------------------------------------------------------------------------------------------------

Procedure InitLongText() 
  Protected index, jj  

  LongText$ = "" 
  For index = 1 To 10 
    LongText$ + "/" + index + "/ " 
    For jj = 1 To 10 
      LongText$ + "This_is_a_very_long_text. "   ;  _ will be replaced with NBSP (non-break space) 
    Next jj 
    LongText$ + #LF$ 
  Next index 
  LongText$ + #LF$ + "/3/ End of Text. " 

  ReplaceString(LongText$, "_", Chr(160))   ; mix the SPaces up with NBSP 
EndProcedure 

; ---------------------------------------------------------------------------------------------------------------------

Macro HandleToStr(handle) 
  "0x" + Hex(handle, #PB_Quad) + " (" + Str(handle) + ")" 
EndMacro 

; ---------------------------------------------------------------------------------------------------------------------

Macro Trace(Message) 
  AddGadgetItem (10, -1, Message) 
  SetGadgetState(10, CountGadgetItems(10)-1)  
EndMacro 

; ---------------------------------------------------------------------------------------------------------------------

Procedure.s GetClassName(hWnd)  ; returns the Classname of the specified window 
  Protected className.s{#MAX_PATH} 

  GetClassName_(hWnd, @className, #MAX_PATH) 
  ProcedureReturn className 
EndProcedure 

; ---------------------------------------------------------------------------------------------------------------------

Procedure HookCB(nCode, wParam, lParam)   
  Protected *cw.CBT_CREATEWND, *cs.CREATESTRUCT 
  Protected class$ 
  Protected hStatic 

  Select nCode 
    Case #HCBT_ACTIVATE 
      Trace("#HCBT_ACTIVATE == " + HandleToStr(wParam)) 

      class$ = GetClassName(wParam) 
      Trace("  Class = " + class$) 

      Select class$ 
        Case "#32770"   ; the MessageRequester 
          ; be careful .... 
          ; the next line will change all Buttons with #IDOK 
          ; 
          SetDlgItemText_(wParam, #IDOK, @"Test")  ; change the button text 
      EndSelect 

    Case #HCBT_CREATEWND  ; .. wParam is the handle of the new window 
      Trace("#HCBT_CREATEWND == " + HandleToStr(wParam)) 

      class$ = GetClassName(wParam) 
      Trace("  Class = " + class$) 

      *cw = lParam    ; 
      ; Debug "hwndinsertAfter = " + HandleToStr(*cw\hWndInsertAfter) 

      *cs = *cw\lpcs  ; member struct 

      If *cs\hWndParent   
        Trace("  Child of or Ownded by " + HandleToStr(*cs\hWndParent))  
      EndIf 

      Trace("  Style = 0x" + Hex(*cs\style, #PB_Long) + ", 0x" + Hex(*cs\dwExStyle, #PB_Long))  
      Trace("  Size  = " + Str(*cs\cx) + ", " + Str(*cs\cy)) 

      Select class$ 
        Case "#32770"   ; the MessageRequester 
          *cs\cx + AdditionalWidth  
        ; *cs\cy + 100 
        Case "Static"   ; 
          *cs\cx + AdditionalWidth
        ; *cs\cy + 100 
        Case "Button"   ; Button, ... 
          *cs\x + AdditionalWidth 
        ; *cs\y + 100 
      ; Case "" 
        Default         ; IME, CicMarshallWndClass, MSCTFIME UI, SystemUserAdapterWindowClass .... ??? 
      EndSelect 

    Case #HCBT_DESTROYWND 
      Trace("#HCBT_DESTROYWND == " + HandleToStr(wParam)) 

  EndSelect  
  ProcedureReturn #False
EndProcedure

; ---------------------------------------------------------------------------------------------------------------------

Procedure DisplayText(Which, bShowIcon) 
  Protected result, hHook, flags_pb, flags_mb  

  ; start hooking :; 
  hHook = SetWindowsHookEx_(#WH_CBT, @HookCB(), 0, GetCurrentThreadId_()) 

  If bShowIcon ; add the correct value 
    flags_pb = #PB_MessageRequester_Info 
    flags_mb = #MB_ICONINFORMATION 
  EndIf  

  Select Which 
    Case 1  ; Purebaisc Original 
      Trace("MessageRequester ----------------------------------------") 
      result = MessageRequester(#Caption$, LongText$, flags_pb | #PB_MessageRequester_Ok) 

    Case 2  ; M$ 
      Trace("MessageBox_ ---------------------------------------------") 
      result = MessageBox_(0, @LongText$, #Caption$, flags_mb | #MB_SYSTEMMODAL | #MB_OK) 

    Default 
      result = -1 

  EndSelect 

  Trace("Return " + result) 
  Trace("") 

  ; stop hooking 
  UnhookWindowsHookEx_(hHook) 

  ProcedureReturn result 
EndProcedure 


; ---------------------------------------------------------------------------------------------------------------------

Procedure main() 
  Protected dlgWhich, showIcon 

  InitLongText() 

  If OpenWindow(0, 0, 0, 600, 400, "Inspect MessageRequester() vs. Messagebox_() ... ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
    StickyWindow(0, 1)  ; I want my app on top of all others (especially the IDE) 

    ; button line 
    ButtonGadget( 0,  10, 0, 120, 23, "Show Message") 
    OptionGadget(11, 140,  0, 90, 20, "Width +   0") 
    OptionGadget(12, 140, 25, 90, 20, "Width + 200") 
    OptionGadget(13, 140, 50, 90, 20, "Width + 400") 

    TextGadget( 1, 0, 0, 0, 0, "") : HideGadget(1, 1)  ; create a new Options Group ??? 

    OptionGadget(21, 240,  0, 80, 20, "PureBasic") 
    OptionGadget(22, 240, 25, 80, 20, "MicroSoft") 

    CheckBoxGadget(2, 340, 0, 80, 23, "Show Icon") 

    ; output some info 
    ; 
    ListViewGadget(10, 10, 80, 580, 310, $4000)   ; we are on windows, so we can use the special flag #LBS_NOSEL 
    SetGadgetFont(10, LoadFont(0, "consolas", 9)) 

    ; init 
    SetGadgetState(11, 1) : AdditionalWidth = 0 
    SetGadgetState(21, 1) : dlgWhich = 1 

    Repeat 
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow : Break ; bye 

        Case #PB_Event_Gadget 
          Select EventGadget() 
            Case  0 : DisplayText(dlgWhich, ShowIcon)  ; Show Message 
            Case 11 : AdditionalWidth =   0 
            Case 12 : AdditionalWidth = 200 
            Case 13 : AdditionalWidth + 400 
            Case 21 : dlgWhich = 1 
            Case 22 : dlgWhich = 2 
            Case  2 : showIcon ! 1  ; CheckBox toggle 
          EndSelect 
      EndSelect 
    ForEver 
  EndIf 
  ProcedureReturn 0 
EndProcedure 

End main() 
Last edited by Axolotl on Tue Jul 02, 2024 3:40 pm, edited 1 time in total.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: Hyphenation in Windows/PB MessageRequesters

Post by boddhi »

Hello Axolotl,
Axolotl wrote: [...] Here you can see the results. [...]
Thanks a lot for your code.
To tell the truth, I haven't fully studied it yet because, as a Sunday programmer, I'm not yet familiar with the APIs you've used. I'll get to work :wink:

About the native MessageRequester() function, PB seems to contain the text within a regular limit. I can't fully confirm this as I only have 1920p screens, but every time, the width of the dialog boxes never exceeds 30% of the screen width (icon or not).
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Axolotl
Addict
Addict
Posts: 837
Joined: Wed Dec 31, 2008 3:36 pm

Re: Hyphenation in Windows/PB MessageRequesters

Post by Axolotl »

Hi boddhi,
It's not a problem if you're not familiar with the API stuff.
The hook is only for inspection of the message windows.
With this update (see my first post) you can see that there is no difference between PB and original windows.

Because the hook can also influence the creation process of the window, I have changed the width of the Requester/MessageBox.
You can see that the calculation of the size is already completed, but the text is adapted to the new width.
A distinction is made between SPACE (chr(32)) and NBSP. (chr(160))

If you want play with it, the procedrue InitLongText() creates the text now.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Post Reply