4

I found out today that GetWindowLong (and GetWindowLongPtr) has 'ANSI' (A) and 'Unicode' (W) flavours, even though they don't have TSTR arguments. The MSDN page on GetWindowLong only indicates that these variants exist, but doesn't mention why.

I can imagine that it must match the encoding of CreateWindowEx (which also has A/W flavours) or RegisterClass, but for many reasons, I don't think this makes sense. Apparently, it matters, because someone reported that the Unicode version may fail on XP (even though XP is NT and, as I understand it, all Unicode under the hood). I have also tried to disassemble the 32-bit version of USER32.DLL (which contains both flavours of GetWindowLong), and there is extra work done based on some apparent encoding difference*.

Which function am I supposed to choose?


*The flavours of GetWindowLong are identical, except for a boolean they pass around to other functions. This boolean is compared to a flag bit in a memory structure I can't be bothered to track down using static code analysis.

  • 1
    Stupid question - why would one care about the ANSI version, now in 2012? – Pavel Radzivilovsky Jan 28 '12 at 13:56
  • I can imagine two scenarios where it is important. One is where you use window classes provided by third parties, and they register it as an ANSI class. Any `A<->W` conversion that happens behind the scenes might incur some performance penalties. The other is where you use ANSI because you simply don't care about i18n (e.g. you are writing a game and your window is taking the full screen anyway). –  Jan 29 '12 at 18:28
  • I see.. Well, A functions do the conversions internally anyway (for an ANSI application). Also, the performance of string conversion for UI code is seldom an issue. – Pavel Radzivilovsky Jan 30 '12 at 10:23

1 Answers1

7

I believe the reason is explained in Raymond Chen's article, What are these strange values returned from GWLP_WNDPROC?

If the current window procedure is incompatible with the caller of GetWindowLongPtr, then the real function pointer cannot be returned since you can't call it. Instead, a "magic cookie" is returned. The sole purpose of this cookie is to be recognized by CallWindowProc so it can translate the message parameters into the format that the window procedure expects.

For example, suppose that you are running Windows XP and the window is a UNICODE window, but a component compiled as ANSI calls GetWindowLong(hwnd, GWL_WNDPROC). The raw window procedure can't be returned, because the caller is using ANSI window messages, but the window procedure expects UNICODE window messages. So instead, a magic cookie is returned. When you pass this magic cookie to CallWindowProc, it recognizes it as a "Oh, I need to convert the message from ANSI to UNICODE and then give the UNICODE message to that window procedure over there."

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • And what makes it that a window is a UNICODE window? `RegisterClassW` or `CreateWindowExW`? –  Jan 27 '12 at 16:45
  • 2
    [`RegisterClassEx`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633587.aspx) determines that: "If you register the window class by using RegisterClassExA, the application tells the system that the windows of the created class expect messages with text or character parameters to use the ANSI character set; if you register it by using RegisterClassExW, the application requests that the system pass text parameters of messages as Unicode." – David Heffernan Jan 27 '12 at 16:47