rodrigocfd / windigo

Windows API and GUI in idiomatic Go.
https://pkg.go.dev/github.com/rodrigocfd/windigo
MIT License
405 stars 22 forks source link

GetTextExtentPoint32 len(lpString) is not calculated correctly #3

Closed beikege closed 3 years ago

beikege commented 3 years ago

https://github.com/rodrigocfd/windigo/blob/0151ff04f45224c76e327b24cb15cc7484514fb7/ui/any_globals.go#L111

https://github.com/rodrigocfd/windigo/blob/0151ff04f45224c76e327b24cb15cc7484514fb7/win/hdc.go#L250-L259

https://github.com/rodrigocfd/windigo/blob/0151ff04f45224c76e327b24cb15cc7484514fb7/internal/proc/gdi32.go#L39

https://docs.microsoft.com/en-us/windows/win32/gdi/specifying-length-of-text-output-string

Each of these functions has both an "ANSI" version and a Unicode version (for example, DrawTextExA and DrawTextExW, respectively). For the "ANSI" version of each function, the length is specified as a BYTE count and for the Unicode function it is specified as a WORD count.

It is traditional to think of this as a "character count". That is generally accurate for many languages, including English, but it is not accurate in general. In "ANSI" strings, characters in SBCS code pages take one byte each, but most characters in DBCS code pages take two bytes. Similarly, most currently defined Unicode characters reside in the Basic Multilingual Plane (BMP) and their UTF-16 representations fit in one WORD, but supplementary characters are represented in Unicode by ''surrogates'', which require two WORDs.

rodrigocfd commented 3 years ago

I'm aware of the ANSI/Unicode versions, but since the whole library is intended to work only with Go strings, I don't see much use for an ANSI implementation.

As for the character count, you are correct. I'm considering using RuneCountInString internally to find out the actual number of characters. It's a standard library function which seems to do all the hard work for us, and it would avoid a "length" parameter, which would transfer the burder to the user. What do you think?

beikege commented 3 years ago

RuneCountInString Solved my problem.

fmt.Println(len("你好 rodrigocfd"))                    // 17
fmt.Println(utf8.RuneCountInString("你好 rodrigocfd")) // 13

win32 api https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lstrlenw there is also a similar function

beikege commented 3 years ago

Thank you