goldendict-ng/mouseover_win32/GetWord.c

213 lines
5.8 KiB
C
Raw Normal View History

#define _WIN32_WINNT 0x0501
#include "GetWord.h"
#include "TextOutHook.h"
TKnownWndClass GetWindowType(HWND WND, const char* WNDClass)
{
const char* StrKnownClasses[] = {
"RICHEDIT20A",
"RICHEDIT20W",
"RICHEDIT",
"EDIT",
"INTERNET EXPLORER_SERVER",
"CONSOLEWINDOWCLASS", // NT
"TTYGRAB", // 9x
"VIRTUALCONSOLECLASS", // ConEmu
};
TKnownWndClass KnownClasses[] = {
kwcRichEdit,
kwcRichEdit,
kwcRichEdit,
kwcMultiLineEdit,
kwcInternetExplorer_Server,
kwcConsole,
kwcConsole,
kwcConEmu,
};
int i;
for (i=0; i<8; i++) {
if (_stricmp(WNDClass, StrKnownClasses[i])==0)
break;
}
if (i<8) {
if (KnownClasses[i] == kwcMultiLineEdit) {
if ((GetWindowLong(WND, GWL_STYLE) & ES_MULTILINE) == 0)
return kwcSingleLineEdit;
}
else if (KnownClasses[i] == kwcConEmu) {
HWND hConsole = (HWND)(DWORD_PTR)GetWindowLongPtr(WND, 0);
if (!hConsole || !IsWindow(hConsole))
return kwcUnknown;
}
return KnownClasses[i];
} else
return kwcUnknown;
}
static BOOL Is_XP_And_Later()
{
OSVERSIONINFO stOSVI;
BOOL bRet;
memset(&stOSVI, 0, sizeof(OSVERSIONINFO));
stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
bRet = GetVersionEx(&stOSVI);
if (FALSE == bRet) return FALSE;
return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId && (5 < stOSVI.dwMajorVersion || (5 == stOSVI.dwMajorVersion && 1 <= stOSVI.dwMinorVersion)));
}
static char* ExtractWordFromRichEditPos(HWND WND, POINT Pt, DWORD *BeginPos)
{
return ExtractFromEverything(WND, Pt, BeginPos);
}
static char* ExtractWordFromEditPos(HWND hEdit, POINT Pt, DWORD *BeginPos)
{
return ExtractFromEverything(hEdit, Pt, BeginPos);
}
static char* ExtractWordFromIE(HWND WND, POINT Pt, DWORD *BeginPos)
{
return ExtractFromEverything(WND, Pt, BeginPos);
}
typedef struct TConsoleParams {
HWND WND;
POINT Pt;
RECT ClientRect;
WCHAR Buffer[256];
int BeginPos;
} TConsoleParams;
static int GetWordFromConsolePack(TConsoleParams *params)
{
int WordLen=0;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE) {
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
COORD CurPos;
CurPos.X = csbi.srWindow.Left + (SHORT)(params->Pt.x * (csbi.srWindow.Right - csbi.srWindow.Left + 1) / params->ClientRect.right);
CurPos.Y = csbi.srWindow.Top + (SHORT)(params->Pt.y * (csbi.srWindow.Bottom - csbi.srWindow.Top + 1) / params->ClientRect.bottom);
if ((CurPos.X >= 0) && (CurPos.X <= csbi.dwSize.X - 1) && (CurPos.Y >= 0) && (CurPos.Y <= csbi.dwSize.Y - 1)) {
int BegPos;
WCHAR *Buf;
params->BeginPos = CurPos.X;
CurPos.X = 0;
Buf = GlobalAlloc(GMEM_FIXED, (csbi.dwSize.X + 1)*sizeof(WCHAR));
if (Buf) {
DWORD ActualRead;
if ((ReadConsoleOutputCharacterW(hStdOut, Buf, csbi.dwSize.X, CurPos, &ActualRead)) && (ActualRead == (DWORD)csbi.dwSize.X)) {
BegPos=0;
WordLen=ActualRead;
if(WordLen>85) {
while(params->BeginPos-BegPos>43 && WordLen>85) {
BegPos++; WordLen--;
}
if(WordLen>85) WordLen=85;
params->BeginPos -= BegPos;
}
if(WordLen) {
memset(params->Buffer, 0, sizeof(params->Buffer));
lstrcpynW(params->Buffer, Buf + BegPos, WordLen+1);
}
}
GlobalFree(Buf);
}
}
}
}
return WordLen;
}
static char* GetWordFromConsole(HWND WND, POINT Pt, DWORD *BeginPos)
{
TConsoleParams *TP;
DWORD pid;
DWORD WordSize;
char *Result;
*BeginPos=0;
if((TP = malloc(sizeof(TConsoleParams))) == NULL)
return(NULL);
ZeroMemory(TP,sizeof(TConsoleParams));
TP->WND = WND;
TP->Pt = Pt;
ScreenToClient(WND, &(TP->Pt));
GetClientRect(WND, &(TP->ClientRect));
// GetWindowThreadProcessId(GetParent(WND), &pid);
GetWindowThreadProcessId(WND, &pid);
if (pid != GetCurrentProcessId()) {
if(Is_XP_And_Later()) {
if(AttachConsole(pid)) {
WordSize = GetWordFromConsolePack(TP);
FreeConsole();
} else {
WordSize = 0;
}
} else {
WordSize = 0;
}
} else {
WordSize = GetWordFromConsolePack(TP);
}
if (WordSize > 0 && WordSize <= 255) {
TEverythingParams CParams;
ZeroMemory(&CParams, sizeof(CParams));
CParams.Unicode=1;
CParams.BeginPos=TP->BeginPos;
CParams.WordLen=WordSize;
CopyMemory(CParams.MatchedWordW, TP->Buffer, WordSize * sizeof(wchar_t));
ConvertToMatchedWordA(&CParams);
*BeginPos = CParams.BeginPos;
Result = _strdup(CParams.MatchedWordA);
} else {
Result = NULL;
}
free(TP);
return Result;
}
static char* GetWordFromConEmu(HWND WND, POINT Pt, DWORD *BeginPos)
{
HWND hConsole = (HWND)(DWORD_PTR)GetWindowLongPtr(WND, 0);
if (!hConsole || !IsWindow(hConsole))
return NULL;
RECT rcConEmu;
if (!GetWindowRect(WND, &rcConEmu) || rcConEmu.right <= rcConEmu.left || rcConEmu.bottom <= rcConEmu.top)
return NULL;
RECT rcConsole;
if (!GetClientRect(hConsole, &rcConsole) || rcConsole.right <= rcConsole.left || rcConsole.bottom <= rcConsole.top)
return NULL;
POINT ptReal = { (Pt.x - rcConEmu.left) * (rcConsole.right - rcConsole.left + 1) / ( rcConEmu.right - rcConEmu.left + 1),
(Pt.y - rcConEmu.top) * (rcConsole.bottom - rcConsole.top + 1 ) / (rcConEmu.bottom - rcConEmu.top + 1) };
ClientToScreen(hConsole, &ptReal);
return GetWordFromConsole(hConsole, ptReal, BeginPos);
}
char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, DWORD *BeginPos)
{
typedef char* (*GetWordFunction_t)(HWND, POINT, DWORD*);
const GetWordFunction_t GetWordFunction[]= {
ExtractFromEverything,
ExtractWordFromRichEditPos,
ExtractWordFromEditPos,
ExtractWordFromEditPos,
ExtractWordFromIE,
GetWordFromConsole,
GetWordFromConEmu,
};
return GetWordFunction[WndType](WND, Pt, BeginPos);
}