Results 1 to 28 of 28

Thread: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    This is something that has been bothering me for a long time, but it's getting worse now that there are so many different/varied DPI settings out there. I'm hoping one of you have found a solution, or even just some ideas for things I might try to resolve the issue.

    I have a RichTextBox that is a certain width (let's say 5000 twips). My application has a manifest marking it as DPI aware:

    Code:
        <asmv3:application>
            <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
                <dpiAware>True</dpiAware>
            </asmv3:windowsSettings>
        </asmv3:application>
    When I run the program at 100%, 150%, and 225% DPI, the width of the RTB is always reported to be the same 5000 twips, so everything looks good there.

    I'm setting the line length to the width of the control less a fudge factor using the EM_SETTARGETDEVICE message:

    Code:
    SendMessage Me.RichTextBox1.hwnd, EM_SETTARGETDEVICE, Me.Hdc, Me.RichTextBox1.Width - 150
    However, when I populate the RTB with identical text across the separate runs at different DPI scaling amounts, the text wraps at different positions:

    Name:  RTBDPI.jpg
Views: 449
Size:  32.0 KB

    • At 100% the text actually extends of the right-edge of the control a bit, and then 3 letter "i"s wrap over to a new line.
    • At 150% the text all fits within the control, and no "i"s wrap at the end.
    • At 225% there is a large amount of white space at the right edge of the control, and 2 letter "i"s wrap over to a new line.


    I've tried creating/using different hDC's but I don't know if there's any way to create a "baseline" hDC that would be the same across all devices/DPIs (or something along those lines if that is gibberish)?

    WordPad doesn't suffer from this problem - the same text at different DPIs always takes up the same amount of line real-estate and wraps at the same points. AFAIK WordPad uses a RichEdit , so I'm hoping there's some way to get the RTB to perform the same. Anybody have any ideas for things I can try (I'm using Kr00l's RTB in case it makes any difference.)

    Thanks in advance for any help.

  2. #2
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    The RichTextBox does not use the same RichEdit control as Wordpad in modern versions of Windows.

    InkEdit uses a newer one, so you might try testing with that.

    I suspect that the fundamental problem is that font scaling isn't simple and linear, but instead sizing changes in jumps.

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Thanks dilettante...I'm using kr00l's RTB which tries to use Msftedit.dll/RichEdit50W but will fallback to Riched20.dll/RichEdit20W if the first option fails. Tests here show that Msftedit.dll/RichEdit50W is succeeding, but may be WordPad uses something newer.

    I've also dug up an EM_SETTYPOGRAPHYOPTIONS message and 2 parameters call TO_ADVANCEDTYPOGRAPHY and TO_ADVANCEDLAYOUT that sounds promising, but I can't find much documentation on them (especially TO_ADVANCEDLAYOUT). I'll play around with them and see if they are of any use.

  4. #4
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,987

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by jpbro View Post
    WordPad doesn't suffer from this problem - the same text at different DPIs always takes up the same amount of line real-estate and wraps at the same points.
    How do you test that?

    And you need to close Wordpad, change the DPI, launch Wordpad again to make the right measurement (not just changing the DPI having Wordpad open).

    (The other issue is normal and expected, BTW, fonts scale taking steps).

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by Eduardo- View Post
    How do you test that?

    And you need to close Wordpad, change the DPI, launch Wordpad again to make the right measurement (not just changing the DPI having Wordpad open).

    (The other issue is normal and expected, BTW, fonts scale taking steps).
    Yeah, that's how I tested it - saved an RTF, closed WordPad, changed the DPI scaling, re-opened the RTF. Word-wrapping was consistent across all tested DPI scaling values.

  6. #6
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,987

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by jpbro View Post
    Yeah, that's how I tested it - saved an RTF, closed WordPad, changed the DPI scaling, re-opened the RTF. Word-wrapping was consistent across all tested DPI scaling values.
    Not here (Windows 11 current version).
    I tested just with its own rule and measures changed with DPI.
    100% <> 125%, 125% <> 150%

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Ahh, nevermind it must have been a fluke of the document I tested that it was wrapping the same at 100%, 150%, and 225%...just tried a more rigorous test with a line full of the letter "i" and I'm getting different wrap points now...Looks like I'm probably out of luck.

  8. #8
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,987

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by jpbro View Post
    Ahh, nevermind it must have been a fluke of the document I tested that it was wrapping the same at 100%, 150%, and 225%...just tried a more rigorous test with a line full of the letter "i" and I'm getting different wrap points now...Looks like I'm probably out of luck.
    It is normal for DPI awareness. BTW this is one of the things you need to be "aware" of.

    The issue is that fonts have hinting, kerning and [whatever] to adapt to the pixels (rasterization).
    And characters can't be rasterized and look good multiplying the sizes arbitrarily. Then they are scaled "in steps".

    If you want the RTB (or whatever control) to wrap at certain word, then also scale the RTB measuring the text. But... that may work well for one particular text but not for other anyway.

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by Eduardo- View Post
    It is normal for DPI awareness. BTW this is one of the things you need to be "aware" of.

    The issue is that fonts have hinting, kerning and [whatever] to adapt to the pixels (rasterization).
    And characters can't be rasterized and look good multiplying the sizes arbitrarily. Then they are scaled "in steps".

    If you want the RTB (or whatever control) to wrap at certain word, then also scale the RTB measuring the text. But... that may work well for one particular text but not for other anyway.
    I agree that I have to scale the RTB. I do this in fact - my RTB sits on top of a rendered PDF and the size of the RTB and it's font size perfectly match the size and contents of the underlying page rendering - all except for where the word-wrap points. As such, I can tell that it is scaled "properly" at any DPI.

    I think that the problem is that RTB font rendering is kind of dumb compared to say, Word. Word definitely wraps at the same point for any DPI. <Baseless Speculation>I'm guessing it does this by measuring the text extents at a baseline canvas DPI unrelated to the screen DPI. AFAIK PDFs do this too - typically using a 72DPI canvas so that text is always placed the same regardless of the screen DPI when the text is drawn onto the page</BaselessSpeculation>. This does mean that Word's rendering can look a bit wonky - if you zoom into a Word document, you'll see the spacing & anti-aliasing is imprecise, but accurate:

    Name:  Word.jpg
Views: 317
Size:  9.5 KB

    Whereas the RTB renders very precisely, but inaccurately:

    Name:  RTB.jpg
Views: 390
Size:  11.3 KB

    So the RTB appears to be working against display pixel measurements, while Word appears to be performing subpixel measurements against a screen-independent canvas. Word's rendering is a bit distorted when rendered on a display, but here we can clearly see the difference between precision and accuracy.

    Anyway, I'm thinking that there isn't a solution for this other than rolling my own RTB (I only need a subset of RTF features, so this might be do-able despite being a massive pain in the arse).w
    Last edited by jpbro; Jan 31st, 2023 at 11:46 PM.

  10. #10
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,987

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    You could try experimenting with DirectWrite.

    I cannot help because I know nothing.

  11. #11
    Frenzied Member VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    1,294

    Talking Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by Eduardo- View Post
    I cannot help because I know nothing.
    It appears you're not the only one:


  12. #12
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    "RICHEDIT60W" is the newest one, RichEdit 8.0.

    But I'm on Windows 10 1809 and Wordpad is still using 50W here.

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by Eduardo- View Post
    I cannot help because I know nothing.
    ?? I think you know a lot >0

    I'm trying to learn from you and everyone else on this forum. I also try to teach what I know when I can. IMO everyone still posting here is a smart and interesting person with a unique technical perspective, and I really enjoy exploring interesting problems with whatever remains of the VB6 community.

    Anyways, thanks for the link to DirectWrite, I'll give it a look. TBH I'm *almost* all in on RC6, so I'll probably try my hand at a Cairo RTB.

  14. #14

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by fafalone View Post
    "RICHEDIT60W" is the newest one, RichEdit 8.0.

    But I'm on Windows 10 1809 and Wordpad is still using 50W here.
    Thanks @fafalone,,,I'll see if I can get a RICHEDIT60W window working, and see if there's any improvement.

  15. #15
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,987

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by jpbro View Post
    ?? I think you know a lot >0

    I'm trying to learn from you and everyone else on this forum. I also try to teach what I know when I can. IMO everyone still posting here is a smart and interesting person with a unique technical perspective, and I really enjoy exploring interesting problems with whatever remains of the VB6 community.

    Anyways, thanks for the link to DirectWrite, I'll give it a look. TBH I'm *almost* all in on RC6, so I'll probably try my hand at a Cairo RTB.
    I repeat: I know nothing (or I don't know anything).
    Context: about DirectWrite and how to use its API.

  16. #16

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Gotcha now, I misunderstood what you meant by "I cannot help because I know nothing" as a naked sentence. I was betwixt the real world and the online world, and I interpreted that as a passive-aggressive statement that you thought that I considered your input without value. My mistake, so please accept my apologies.

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Ambiguous Input + Interpersonal History + Cultural/Language Differences = Misunderstanding, hence my apology.

  18. #18
    Fanatic Member Episcopal's Avatar
    Join Date
    Mar 2019
    Location
    Brazil
    Posts
    547

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by Eduardo- View Post
    You could try experimenting with DirectWrite.

    I cannot help because I know nothing.
    look for RichEditD2D

    https://devblogs.microsoft.com/math-...ndow-controls/

  19. #19

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Thank you Eduardo and Episcopal, I will look into DirectWrite & RichEditD2D.

  20. #20
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,207

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by jpbro View Post
    ... will look into DirectWrite & RichEditD2D.
    From Episcopals link:
    ...there’s a new message EM_SWITCHTOD2D (WM_USER + 389) with wparam = lparam = 0
    that switches the current window control to D2D...


    Seems that's all what it takes (shortly after creating the RTB-hWnd "the old way")

    Olaf
    Last edited by Schmidt; Feb 3rd, 2023 at 10:12 PM.

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,401

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by Schmidt View Post
    From Episcopals link:
    ...there’s a new message EM_SWITCHTOD2D (WM_USER + 389) with wparam = lparam = 0
    that switches the current window control to D2D...


    Seems that's all what it takes (shortly after creating the RTB-hWnd "the old way")

    Olaf
    Thanks Olaf, I did try that as a quick first test against my full app, but it didn't render any differently. My editor is a bit of a wild beast after years of undireected development, so I'll try again this weekend with a minimal test program to play around with. If that works, then I might be able to justify a big refactoring.

    I've been ruminating about writing an RC6/Cairo RTB-subset widget for a years now, but other things keep getting in the way. While I have your ear though - would Cairo's font rendering/word-wrapping be consistent across devices with different screen DPIs? I would assume the answer is yes, but I was wrong in my assumptions about the WinRTB behaviour...and you know what they say about assumptions.

  22. #22
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    I was looking at the D2D stuff... the interfaces it uses aren't normal IDL like the rest of the TOM interfaces... how would you make this declarable for VB6-compatible typelibs:

    Code:
    class ITextServices : public IUnknown
    {
    public:
    
    	//@cmember Generic Send Message interface
    	virtual HRESULT 	TxSendMessage(
    							UINT msg, 
    							WPARAM wparam, 
    							LPARAM lparam,
    							LRESULT *plresult) = 0;
    	
    	//@cmember Rendering
    	virtual HRESULT		TxDraw(	
    							DWORD dwDrawAspect,		
    							LONG  lindex,			
    							void * pvAspect,		 
    							DVTARGETDEVICE * ptd,									
    							HDC hdcDraw,			
    							HDC hicTargetDev,		 
    							LPCRECTL lprcBounds,	
    							LPCRECTL lprcWBounds,	
    							LPRECT lprcUpdate,		
    							BOOL (CALLBACK * pfnContinue) (DWORD), 
    							DWORD dwContinue,
    							LONG lViewId) = 0;	
    
    	//@cmember Horizontal scrollbar support
    	virtual HRESULT		TxGetHScroll(
    							LONG *plMin, 
    							LONG *plMax, 
    							LONG *plPos, 
    							LONG *plPage,
    							BOOL * pfEnabled ) = 0;
    
    	//@cmember Horizontal scrollbar support
    	virtual HRESULT		TxGetVScroll(
    							LONG *plMin, 
    							LONG *plMax, 
    							LONG *plPos, 
    							LONG *plPage, 
    							BOOL * pfEnabled ) = 0;
    
    	//@cmember Setcursor
    	virtual HRESULT 	OnTxSetCursor(
    							DWORD dwDrawAspect,		
    							LONG  lindex,			
    							void * pvAspect,		 
    							DVTARGETDEVICE * ptd,									
    							HDC hdcDraw,			
    							HDC hicTargetDev,		 
    							LPCRECT lprcClient, 
    							INT x, 
    							INT y) = 0;
    
    	//@cmember Hit-test
    	virtual HRESULT 	TxQueryHitPoint(
    							DWORD dwDrawAspect,		
    							LONG  lindex,			
    							void * pvAspect,		 
    							DVTARGETDEVICE * ptd,									
    							HDC hdcDraw,			
    							HDC hicTargetDev,		 
    							LPCRECT lprcClient, 
    							INT x, 
    							INT y, 
    							DWORD * pHitResult) = 0;
    
    	//@cmember Inplace activate notification
    	virtual HRESULT		OnTxInPlaceActivate(LPCRECT prcClient) = 0;
    
    	//@cmember Inplace deactivate notification
    	virtual HRESULT		OnTxInPlaceDeactivate() = 0;
    
    	//@cmember UI activate notification
    	virtual HRESULT		OnTxUIActivate() = 0;
    
    	//@cmember UI deactivate notification
    	virtual HRESULT		OnTxUIDeactivate() = 0;
    
    	//@cmember Get text in control
    	virtual HRESULT		TxGetText(BSTR *pbstrText) = 0;
    
    	//@cmember Set text in control
    	virtual HRESULT		TxSetText(LPCWSTR pszText) = 0;
    	
    	//@cmember Get x position of 
    	virtual HRESULT		TxGetCurTargetX(LONG *) = 0;
    	//@cmember Get baseline position
    	virtual HRESULT		TxGetBaseLinePos(LONG *) = 0;
    
    	//@cmember Get Size to fit / Natural size
    	virtual HRESULT		TxGetNaturalSize(
    							DWORD dwAspect,
    							HDC hdcDraw,
    							HDC hicTargetDev,
    							DVTARGETDEVICE *ptd,
    							DWORD dwMode, 	
    							const SIZEL *psizelExtent,
    							LONG *pwidth, 
    							LONG *pheight) = 0;
    
    	//@cmember Drag & drop
    	virtual HRESULT		TxGetDropTarget( IDropTarget **ppDropTarget ) = 0;
    
    	//@cmember Bulk bit property change notifications
    	virtual HRESULT		OnTxPropertyBitsChange(DWORD dwMask, DWORD dwBits) = 0;
    
    	//@cmember Fetch the cached drawing size (logical not physical)
    	virtual	HRESULT		TxGetCachedSize(DWORD *pdwWidth, DWORD *pdwHeight)=0;
    };
    There's not even a GUID for it... I got some unofficial sites listing IID_ITextServices; should I just go ahead and make a standard def anyway?

    (And what is BOOL (CALLBACK * pfnContinue) (DWORD), supposed to be? Is it a pointer or not? I'm making everything 64bit compatible these days so it matters)
    Last edited by fafalone; Feb 4th, 2023 at 02:22 AM.

  23. #23
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,207

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Quote Originally Posted by jpbro View Post
    ...did try that as a quick first test against my full app, but it didn't render any differently.
    Might be that this really works only with the Office365-RichText-Implementation (and not msftedit32.dll)...

    Quote Originally Posted by jpbro View Post
    I've been ruminating about writing an RC6/Cairo RTB-subset widget for a years now, but other things keep getting in the way. While I have your ear though - would Cairo's font rendering/word-wrapping be consistent across devices with different screen DPIs? I would assume the answer is yes, but I was wrong in my assumptions about the WinRTB behaviour...and you know what they say about assumptions.
    These days (where "Web-Exports" of richtext-formatted snippets are common-place),
    I wouldn't bother with MS-RTF anymore...

    At my workplace, we've thrown out all MS-RTF-based rich-text-editing -
    and now use HTML-based richtext-editors throughout the Desktop-App...
    (e.g. CKEditor via "IE11-elevated IE-WebBrowser-Ctl", or on Win10 and higher: TinyMCE with cWebView2).

    TinyMCE comes with a free Print-Plugin... (in case that is your "primary output-target" for rich-text -
    and not "exporting User-pre-formatted HTML-snippets to customer-websites"; as it is for us).

    Olaf

  24. #24
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    DirectWrite examples.

    Quote Originally Posted by fafalone View Post
    There's not even a GUID for it... I got some unofficial sites listing IID_ITextServices; should I just go ahead and make a standard def anyway?
    Use this IID_ITextServices = {8D33F740-CF58-11CE-A89D-00AA006CADC5}. Anyway you should get the IID from a dll dynamicly.

    Quote Originally Posted by fafalone View Post
    I was looking at the D2D stuff... the interfaces it uses aren't normal IDL like the rest of the TOM interfaces... how would you make this declarable for VB6-compatible typelibs:
    It's just C++ abstract class declaration which is an interface.

    Quote Originally Posted by fafalone View Post
    (And what is BOOL (CALLBACK * pfnContinue) (DWORD), supposed to be? Is it a pointer or not? I'm making everything 64bit compatible these days so it matters)
    It's a pointer to an user callback function:
    Code:
    Function Continue(ByVal l As Long) As Long
    As far as i understand from the documentation it isn't used (?)

  25. #25
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    It's not used but in 64bit it matters if it's pointer or a BOOL because that will throw off the stack if it's wrong.

    ITextServices GUID could be found in google, but others... I searched and came up empty, so I extracted them from msftedit.dll:

    Code:
    IID_ITextServices={8D33F740-CF58-11CE-A89D-00AA006CADC5}
    IID_ITextServices2={8D33F741-CF58-11CE-A89D-00AA006CADC5}
    IID_ITextHost={13E670F4-1A5A-11CF-ABEB-00AA00B65EA1}
    IID_ITextHost2={13E670F5-1A5A-11CF-ABEB-00AA00B65EA1}
    IID_IRicheditWindowlessAccessibility={983E572D-20CD-460B-9104-83111592DD10}
    IID_IRicheditUiaOverrides={F2FB5CC0-B5A9-437F-9BA2-47632082269F}
    However, IID_IRichEditUiaInformation for interface IRichEditUiaInformation : public IUnknown is *not* exported from msftedit.dll like the others, there's 0 results online, so it's a complete mystery.
    Last edited by fafalone; Feb 4th, 2023 at 07:39 AM.

  26. #26
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    If anyone wanted to play around with the RichEdit D2D stuff, oleexp 5.3 is out with both the ITextServices/ITextHost interfaces and The trick's Direct2D and DirectWrite typelibs integrated; all of these are also in tbShellLib for twinBASIC (I did an initial pass looking for direct2d/directwrite things that needed to be updated for 64bit, and think I got them all, but if I missed them, let me know).

  27. #27

  28. #28
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: RichTextBox Variable Word-Wrap at Different DPI Scaling Levels

    Thanks. Will add it in the next version... not an immediate priority because that interface is for accessibility, which requires IRicheditWindowlessAccessibility, which requires IRawElementProviderWindowlessSite and IRawElementProviderSimple, which are interconnected with a whole large set of interfaces in uiautomationcore.h that will take some time to bring in.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width