| 1359 | |
| 1360 | |
| 1361 | int GetWindowTextTimeout(HWND aWnd, LPTSTR aBuf, INT_PTR aBufSize, UINT aTimeout) |
| 1362 | // This function must be kept thread-safe because it may be called (indirectly) by hook thread too. |
| 1363 | // aBufSize is an int so that any negative values passed in from caller are not lost. |
| 1364 | // Returns the length of what would be copied (not including the zero terminator). |
| 1365 | // In addition, if aBuf is not NULL, the window text is copied into aBuf (not to exceed aBufSize). |
| 1366 | // AutoIt3 author indicates that using WM_GETTEXT vs. GetWindowText() sometimes yields more text. |
| 1367 | // Perhaps this is because GetWindowText() has built-in protection against hung windows and |
| 1368 | // thus isn't actually sending WM_GETTEXT. The method here is hopefully the best of both worlds |
| 1369 | // (protection against hung windows causing our thread to hang, and getting more text). |
| 1370 | // Another tidbit from MSDN about SendMessage() that might be of use here sometime: |
| 1371 | // "However, the sending thread will process incoming nonqueued (those sent directly to a window |
| 1372 | // procedure) messages while waiting for its message to be processed. To prevent this, use |
| 1373 | // SendMessageTimeout with SMTO_BLOCK set." Currently not using SMTO_BLOCK because it |
| 1374 | // doesn't seem necessary. |
| 1375 | // Update: GetWindowText() is so much faster than SendMessage() and SendMessageTimeout(), at |
| 1376 | // least on XP, so GetWindowTextTimeout() should probably only be used when getting the max amount |
| 1377 | // of text is important (e.g. this function can fetch the text in a RichEdit20A control and |
| 1378 | // other edit controls, whereas GetWindowText() doesn't). This function is used to implement |
| 1379 | // things like WinGetText and ControlGetText, in which getting the maximum amount and types |
| 1380 | // of text is more important than performance. |
| 1381 | { |
| 1382 | if (!aWnd || (aBuf && aBufSize < 1)) // No HWND or no room left in buffer (some callers rely on this check). |
| 1383 | return 0; // v1.0.40.04: Fixed to return 0 rather than setting aBuf to NULL and continuing (callers don't want that). |
| 1384 | |
| 1385 | LRESULT result, length; |
| 1386 | if (aBuf) |
| 1387 | { |
| 1388 | *aBuf = '\0'; // Init just to get it out of the way in case of early return/error. |
| 1389 | if (aBufSize == 1) // Room only for the terminator, so go no further (some callers rely on this check). |
| 1390 | return 0; |
| 1391 | |
| 1392 | // Below demonstrated that GetWindowText() is dramatically faster than either SendMessage() |
| 1393 | // or SendMessageTimeout() (noticeably faster when you have hotkeys that activate |
| 1394 | // windows, or toggle between two windows): |
| 1395 | //return GetWindowText(aWnd, aBuf, aBufSize); |
| 1396 | //return (int)SendMessage(aWnd, WM_GETTEXT, (WPARAM)aBufSize, (LPARAM)aBuf); |
| 1397 | |
| 1398 | // Don't bother calling IsWindowHung() because the below call will return |
| 1399 | // nearly instantly if the OS already "knows" that the target window has |
| 1400 | // be unresponsive for 5 seconds or so (i.e. it keeps track of such things |
| 1401 | // on an ongoing basis, at least XP seems to). |
| 1402 | result = SendMessageTimeout(aWnd, WM_GETTEXT, (WPARAM)aBufSize, (LPARAM)aBuf |
| 1403 | , SMTO_ABORTIFHUNG, aTimeout, (PDWORD_PTR) &length); |
| 1404 | if (length >= aBufSize) // Happens sometimes (at least ==aBufSize) for apps that wrongly include the terminator in the reported length. |
| 1405 | length = aBufSize - 1; // Override. |
| 1406 | |
| 1407 | // v1.0.40.04: The following check was added because when the text is too large to to fit in the |
| 1408 | // buffer, the OS (or at least certain applications such as AIM) return a length that *includes* |
| 1409 | // the zero terminator, violating the documented behavior of WM_GETTEXT. In case the returned |
| 1410 | // length is too long by 1 (or even more than 1), calculate the length explicitly by checking if |
| 1411 | // there's another terminator to the left of the indicated length. The following loop |
| 1412 | // is used in lieu of strlen() for performance reasons (because sometimes the text is huge). |
| 1413 | // It assumes that there will be no more than one additional terminator to the left of the |
| 1414 | // indicated length, which so far seems to be true: |
| 1415 | for (LPTSTR cp = aBuf + length; cp >= aBuf; --cp) |
| 1416 | { |
| 1417 | if (!*cp) |
| 1418 | { |
no outgoing calls
no test coverage detected