![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
как определить контекст указателя(курсора)? [D7, WinXP]
Dmitry_177 © (2007-02-12 23:25:00)как определить контекст курсора? Т.е. чтобы можно было там рисовать? Вобщем задача такая, чтобы не путать раскладку клавиатуры, хочу около стрелки рисовать флажек страны, язык которой сейчас установлен в раскладке клавиатуры.. Но я хочу чтобы это было во всех приложениях..
Вобщем думаю нужно ставить хук на WH_CALLWNDPROCRET и потом в обработке смотреть на WM_INPUTLANGCHANGEREQUEST.. Но это все понятно, а как мне получить потом контекст указателя, чтобы там флаг подрисовать?
Dmitry_177 (2007-02-20 16:03:00) [1]Не работает..
Всеравно после выключения программы курсор с флагом остается.. Это если я сам ее выключу а не сама через 5 секунд..
Rouse_ (2007-02-20 09:40:00) [2]
program kbl1;
uses
Windows,
Messages;
{$R Cursors.res}
var
AMessage: TMsg;
OldCursor: HCURSOR;
NeedStop: Boolean = False;
EndTime: Cardinal;
hTimer: THandle;
function TimerProc(Window: HWnd; Message: Cardinal;
wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
Pt: TPoint;
WndHandle: HWND;
RemoteThreadID: DWORD;
RemoteLayout: WORD;
CursorHandle: HCURSOR;
begin
NeedStop := GetTickCount >= EndTime;
GetCursorPos(Pt);
WndHandle := WindowFromPoint(Pt);
if WndHandle > HINSTANCE_ERROR then
begin
RemoteThreadID := GetWindowThreadProcessId(WndHandle);
RemoteLayout := GetKeyboardLayout(RemoteThreadID) and $FFFF;
case RemoteLayout of
$409: CursorHandle := LoadCursor(HInstance, 'CURSOR_EN');
$419: CursorHandle := LoadCursor(HInstance, 'CURSOR_RU');
else
CursorHandle := OldCursor;
end;
SetSystemCursor(CursorHandle, 32513{IDC_IBEAM});
end;
end;
begin
OldCursor := CopyIcon(LoadCursor(0, IDC_IBEAM));
EndTime := GetTickCount + 5000 {будем работать 5 секунд};
hTimer := SetTimer(0, 0, 100, @TimerProc);
while GetMessage(AMessage, 0, 0, 0) and not NeedStop do
begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;
KillTimer(hTimer, 0);
SetSystemCursor(OldCursor, 32513{IDC_IBEAM});
DestroyCursor(OldCursor);
end.
Dmitry_177 (2007-02-19 21:55:00) [3]Сделал я так, без формы.. Все работает как надо =) Но, есть одно НО.. Если выключить программу то курсор остается с флагом который был впоследний раз.. Думал в самом конце программы, после цикла SetSystemCursor(OldCursor, 32513{IDC_IBEAM})поправит все дело, так это не помогло.. Пробовал и с try..finally, тоже самое.. Если делать с формой и обрабатывать по WM_TIMER, то тоже все работает.. Но там я пробовал в WM_DESTROY и WM_CLOSE выполнить SetSystemCursor(OldCursor, 32513{IDC_IBEAM}), тоже не помогло.. Такое ощущение что при выключении программа сразуже вылитает и не обрабатывает последующие сообщения и действия после цикла.. Может кто знает как это сделать?
P.S. при следующей загрузке программы в OldCursor загружается уже не обычный курсор, а тот который уже с флагом установлен.. Так что при всех моих этих тестах я каждый раз перезагружал комп..
program Cursors;
uses
Windows,
Messages;
{$R Cursors.res}
var
AMessage: TMsg;
OldCursor: HCURSOR;
function TimerProc(Window: HWnd; Message: Cardinal; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
Pt: TPoint;
WndHandle: HWND;
RemoteThreadID: DWORD;
RemoteLayout: WORD;
CursorHandle: HCURSOR;
begin
GetCursorPos(Pt);
WndHandle := WindowFromPoint(Pt);
if WndHandle > HINSTANCE_ERROR then
begin
RemoteThreadID := GetWindowThreadProcessId(WndHandle);
RemoteLayout := GetKeyboardLayout(RemoteThreadID) and $FFFF;
case RemoteLayout of
$409: CursorHandle := LoadCursor(HInstance, 'CURSOR_EN');
$419: CursorHandle := LoadCursor(HInstance, 'CURSOR_RU');
else
CursorHandle := OldCursor;
end;
SetSystemCursor(CursorHandle, 32513{IDC_IBEAM});
end;
end;
begin
OldCursor := LoadCursor(0, IDC_IBEAM);
SetTimer(0, 0, 100, @TimerProc);
while GetMessage(AMessage, 0, 0, 0) do
DispatchMessage(AMessage);
SetSystemCursor(OldCursor, 32513{IDC_IBEAM});
end.
А еще правильно ли я написал все параметры функции function TimerProc(Window: HWnd; Message: Cardinal; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;?
Rouse_ (2007-02-19 09:49:00) [4]Если откроешь Aml Maple в отладчике, то увидишь заветное WM_TIME :)
Ну и в коде, в районе WinMain-а можно увидеть его частоту срабатывания:
push 0 ; lpTimerFunc
push 64h ; uElapse
push 0Ah ; nIDEvent
push [ebp+hWnd] ; hWnd
call ds:SetTimer
Dmitry_177 (2007-02-19 00:39:00) [5]Всеже я не пойму как Aml Maple отлавливает переключение раскладки во всех программах без библиотеки.. Ведь с использованием WH_MOUSE_LL в коде, который приведен выше определяется раскладка при событиях с мышкой, в частности при перемещении, а Aml Maple определяет переключение если мышка в покое, т.е. даже без перемещения... Вот не пойму я как она это так делает...
Rouse_ (2007-02-14 14:16:00) [6]Хе, пардон - на время то и не обратил внимание :)
Dmitry_177 (2007-02-14 10:49:00) [7]Rouse_, я тут и там одновременно спрашивал.. посмотри на время и там и тут =)
Rouse_ (2007-02-13 15:02:00) [8]Блин я же тебе показывал сегодня:
function LowLevelMouseProc(nCode: Integer; WParam: WPARAM;
LParam: LPARAM): LRESULT; stdcall;
var
WndHandle: THandle;
RemoteThreadID: THandle;
RemoteLayout: WORD;
CursorHandle: THandle;
Code: Longint;
begin
Result := CallNextHookEx(MouseHook, nCode, WParam, LParam);
if WParam = WM_MOUSEMOVE then
begin
WndHandle := WindowFromPoint(PMSLLHOOKSTRUCT(LParam)^.pt);
if WndHandle > HINSTANCE_ERROR then
begin
RemoteThreadID := GetWindowThreadProcessId(WndHandle);
AttachThreadInput(GetCurrentThreadId, RemoteThreadID, True);
RemoteLayout := GetKeyboardLayout(RemoteThreadID) and $FFFF;
case RemoteLayout of
$409: // Английская раскладка
CursorHandle := LoadCursor(HInstance, 'CURSOR_EN');
$419: // Русская раскладки
CursorHandle := LoadCursor(HInstance, 'CURSOR_RU');
else
// Неизвестная раскладка
CursorHandle := OldCursor;
end;
AttachThreadInput(GetCurrentThreadId, RemoteThreadID, False);
SetSystemCursor(CursorHandle, 32513{IDC_IBEAM}); // <- это и означает что над EDIT-ом курсор измениться...
Code := SendMessage(WndHandle, WM_NCHITTEST, 0,
LongInt(PointToSmallPoint(PMSLLHOOKSTRUCT(LParam)^.pt)));
SendMessage(WndHandle, WM_SETCURSOR, WndHandle, MakeLong(Code, WM_MOUSEMOVE));
end;
end;
end;
Sapersky (2007-02-13 14:31:00) [9]Флажок около стрелки уже есть, называется Aml Maple. Мне кажется, логичнее рисовать флажок (или подпись En/Ru, постоянно маячащий перед носом флажок - в том же Дельфи, например - раздражает) около текстового курсора (каретки) - см. CreateCaret и т.д. Хотя там свои сложности, например, с Word'ом, который использует произвольную каретку или вообще сам её рисует, толком не разобрался.
Dmitry_177 (2007-02-13 02:09:00) [10]решил немного подругому сделать.. вобщем как мне определить что курсор изменился? т.е. был стрелочкой, а изменился на "I", т.е. над Edit-ом например, где можно печатать.. Есть ли такое сообщение по смене курсора?
Альберт (2007-02-13 00:48:00) [11]LoadCursor
SetCursor
другие функции
ClipCursor
CreateCursor
DestroyCursor
GetCursorPos
LoadCursor
SetCursor
SetCursorPos
ShowCursor
Dmitry_177 (2007-02-13 00:18:00) [12]
> может проще свои курсоры нарисовать и менять их при необходимости
ну хоть даже так, как мне их поменять?
Альберт (2007-02-13 00:09:00) [13]может проще свои курсоры нарисовать и менять их при необходимости