TONT 42663 为何 GetWindowText 的规则如此诡异?

前人栽树,后人乘凉,但这棵树也不是100%靠谱的。

原文链接:https://blogs.msdn.microsoft.com/oldnewthing/20030904-00/?p=42663

Joel Spolsky rightly points out that the rules for GetWindowText exhibit abstraction leakage. Why are the rules for GetWindowText so weird?

Joel Spolsky正确地指出了GetWindowText存在抽象泄露(abstraction leakage)的问题(译注:指所有试图通过抽象来简化、隐藏底层实现的机制,看似简化了实现某个功能的难度,但因为其实现并非十全十美,所以在特定情况下总是有漏洞的,而当因此导致的奇怪问题发生时,其学习成本会陡然上升,可自行搜索Leaky abstraction进一步了解)。为什么GetWindowText的规则那么诡异呢?

Set the wayback machine to 1983. Your typical PC had an 8086 processor running at a whopping 4.7MHz, two 360K 5¼-inch floppy drives (or if you were really loaded, one floppy drive and a 10MB hard drive), and 256KB of memory. [Original entry said 256MB – oops. Thanks to Joe Beda for pointing this out.]

时光倒流回1983年。常见的电脑配置有运行在『飞快的』4.7Mhz频率下的8086处理器,两个360K 5.25英寸软驱(或者你真的有很多东西要存的话,大概会是一个软驱和一块容量为10MB的硬盘),以及256KB的内存。[之前错写成256MB了,抱歉,感谢Joe Beda指出。]

This was the world of Windows 1.0.

这就是Windows 1.0所面对的世界(硬件配置)。

Windows 1.0 was a coöperatively-multitasked system. No pre-emptive multitasking here. When your program got control, it had control for as long as it wanted it. Only when you called a function like PeekMessage or GetMessage did you release control to other applications.

Windows 1.0是协同式多任务系统。抢占式多任务是什么,(那时候是)不存在的。当一个程序获得(系统的)控制权后,就可以想持有多久就持有多久。只有当调用类似PeekMessage和GetMessage之类的方法时,才会将控制权释放给其它应用程序。

This was important, because in the absence of a hardware memory manager, you really had to make sure that your memory didn’t get ripped out from under you.

这一点在当时很重要,因为当时并不存在硬件级内存管理这种东西,程序的确得自行把握好自己的内存不被其它代码拿走乱搞。

One important consequence of coöperative multitasking is that if your program is running, not only do you know that no other program is running, but you also know that every window is responding to messages. Why? Because if they were hung, they wouldn’t have released control to you!

协同式多任务很重要的结果之一,是如果你的程序正在运行,你不光知道不可能有其它程序在运行,还知道每一个窗口都会对消息进行响应。为什么呢,因为如果窗口挂起了,它们是不可能将控制权交还给你的!

This means that it is always safe to send a message. You never had to worry about the possibility of sending a message to a hung window, since you knew that no windows were hung.

这就意味着发送消息永远是安全的。你完全不用担心会把消息发送给一个挂起的窗口,因为不可能有窗口处于挂起状态。

In this simpler world, GetWindowText was a straightforward function:

在这种比较简单的情况下,GetWindowText是这样一个简洁明了的方法:

int WINAPI
GetWindowText(HWND hwnd, LPSTR pchBuf, int cch)
{
// ah for the simpler days(哎呀好怀念那单纯的日子)
return SendMessage(hwnd, WM_GETTEXT, (WPARAM)cch, (LPARAM)pchBuf);
}

This worked for all windows, all the time. No special handling of windows in a different process.

这样的做法随时对任何窗口都有效,不用关心对不同进程中的窗口需要做什么特殊处理。

It was the transition to Win32 and pre-emptive multitasking that forced the change in the rules, because for the first time, there was the possibility that (gasp) the window you were trying to communicate with was not responding to messages.

但当进入Win32和抢占式多任务的时代后,规则不得不发生变化,因为自始至终第一次,你要发送消息去的窗口可能并不会响应消息(哎)。

Now you have the backwards compatibility problem. As I described in my original article, many parts of the system and many programs rely on the ability to retrieve window text without hanging. So how do you make it possible to retrieve window text without hanging, while still giving controls like the edit control the ability to do their own window text management?

这里就有一个向下兼容性的问题了。就像我前面所说的,系统中的许多部分,以及很多应用程序已经习惯于获取窗体中的文本、且不会发生任何延迟。那么,现在如何才能达到无延迟获取窗体文本,但又不影响类似编辑控件(edit control)之类的控件自行处理其窗体文本管理事件的呢?

The Win32 rules on GetWindowText are the result of this attempt to reconcile conflicting goals.

这就是Win32环境下GetWindowText的规则,在这种相互冲突的需求中尝试调停的结果了。

(This same story, with slight changes, also works as a discussion of why DDE works the way it does. But fewer people use DDE nowadays, so the effect is not as dramatic.)

(同样的故事(细节不同)也可以DDE的动作行为进行解释,不过现在已经很少有人用DDE了,所以由此产生的效果不像上文那么有戏剧性。)

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

 剩余字数 ( Characters available )

Your comment will be available after auditing.
您的评论将在通过审核后显示。

Please DO NOT add any links in your comment, otherwise it would be identified as SPAM automatically and never be audited.
请不要在评论中插入任何链接,否则将被自动归类为垃圾评论,且永远不会被提交给博主进行复审。

*