Программное переключение keyboard layout
От: Michaels1  
Дата: 18.11.12 15:51
Оценка:
Привет
Пишу приложение-переключатель раскладок, "висящее в трее".
Идея его в том, что
1) при наступлении определенного события (например, нажатия специальной клавиши), мое tray-приложение должно переключить раскладку активного в данный момент чужого приложения на заданную в конфиге раскладку.
2) Мое tray-приложение также мониторит события изменения раскладки других окон, но вызванные системой, а не самим tray-приложением (например, пользователь нажал Alt+Shift, или сменил активное окно — у которого была установлена другая раскладка) — и tray-программа должна выполнить какое-то действие. Т.е., мониторится любые изменения языка в Language Bar, кроме тех, которые были вызваны моей программой посылкой WM_LANGCHANGEREQUEST.
задачу 1 решил, просто посылаю окну, хэндл которого возвращает GetForegroundWindow(), событие WM_LANGCHANGEREQUEST с кодом нужной раскладки.
задачу 2 пока не решил. Вот здесь советуют перехватывать событие изменения текущего окна, и, при наступлении такого события, устанавливать локально в поток активного окна ловушку оконных сообщений на WM_INPUTLANGCHANGE, чтобы дополнительно словить все Alt+Shift (или мышкой) переключения языка.
Я так и рассчитывал сделать, но есть 2 вопроса:
1. Tray-приложение не должно получать уведомления об изменениях языка, если эти изменения были вызваны tray-приложением посылкой WM_LANGCHANGEREQUEST активному окну. Как узнать, что язык поменялся моей tray-программой, и игнорировать такое событие?
2. Если tray-приложение 32-битный процесс, будут ли проблемы с установкой локального хука в 64-битный процесс?

Спасибо
Re: Программное переключение keyboard layout
От: sergeyt4  
Дата: 18.11.12 17:15
Оценка: 6 (1) -2
Здравствуйте, Michaels1, Вы писали:

M>2. Если tray-приложение 32-битный процесс, будут ли проблемы с установкой локального хука в 64-битный процесс?


Для ваших целей нет необходимости устанавливать хуки. Достаточно запустить обычный оконный таймер (WM_TIMER) с частотой примерно 10 раз/сек и воспользоваться тремя ф-циями:

GetGUIThreadInfo
GetWindowThreadProcessId
GetKeyboardLayout.

вот кусок из работающей программы, которая делает именно то, что вы описали: переключает раскладки, а когда переключается язык, отображает индикатор текущего языка.


    GUITHREADINFO gti;
    ZeroMemory(&gti, sizeof(GUITHREADINFO));
    gti.cbSize = sizeof(GUITHREADINFO);
    
    GetGUIThreadInfo(NULL, &gti);

    m_hWndActive = gti.hwndActive;
    m_hWndFocus = gti.hwndFocus;
    m_hWndCaret = gti.hwndCaret;

    m_dwProcessID = 0;
    m_dwThreadID = 0;

    HWND hwndActive = m_hWndCaret;
    if (!hwndActive) hwndActive = m_hWndFocus;
    if (!hwndActive) hwndActive = m_hWndActive;

    if (hwndActive)
        m_dwThreadID = ::GetWindowThreadProcessId(hwndActive, &m_dwProcessID);

    m_hKL = m_dwThreadID == NULL ? 0 : GetKeyboardLayout(m_dwThreadID);


Чем хорош обработчик на таймере — он отлавливает не только переключение раскладки в текущем окне, но и смену текущего окна. А т.к. в Windows каждое приложение имеет свою текущую раскладку (вернее, в каждом UI потоке одного приложения раскладка независима), то при смене окна может измениться раскладка.

Единственная проблема — этот код не срабатывает в консольных окнах.
Re[2]: Программное переключение keyboard layout
От: os24ever
Дата: 18.11.12 17:24
Оценка: 30 (4) +3 :)))
S>Достаточно запустить обычный оконный таймер (WM_TIMER) с частотой примерно 10 раз/сек

Убивать, убивать, убивать, убивать, убивать, ржавой секироЙ УЖОСА ВО ИМЯ ДОБРА!!!!111пыщпыщ

Я всё сказал.
Re[3]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 18.11.12 17:33
Оценка: :))
Здравствуйте, os24ever, Вы писали:

S>>Достаточно запустить обычный оконный таймер (WM_TIMER) с частотой примерно 10 раз/сек


O>Убивать, убивать, убивать, убивать, убивать, ржавой секироЙ УЖОСА ВО ИМЯ ДОБРА!!!!111пыщпыщ


O>Я всё сказал.

Зачем убивать-то!?! Не стоит! Достаточно поставить WM_TIMER с частотой хотя бы "писят" раз/сек, а еще лучше "пицот" раз/сек.... И он сам памрётъ!

А по сути согласен!
Aml Pages Home
Re: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 18.11.12 17:40
Оценка: 4 (1)
Здравствуйте, Michaels1, Вы писали:

M>Привет

M>Пишу приложение-переключатель раскладок, "висящее в трее".
M>Идея его в том, что
M>1) при наступлении определенного события (например, нажатия специальной клавиши), мое tray-приложение должно переключить раскладку активного в данный момент чужого приложения на заданную в конфиге раскладку.
M>2) Мое tray-приложение также мониторит события изменения раскладки других окон, но вызванные системой, а не самим tray-приложением (например, пользователь нажал Alt+Shift, или сменил активное окно — у которого была установлена другая раскладка) — и tray-программа должна выполнить какое-то действие. Т.е., мониторится любые изменения языка в Language Bar, кроме тех, которые были вызваны моей программой посылкой WM_LANGCHANGEREQUEST.
M>задачу 1 решил, просто посылаю окну, хэндл которого возвращает GetForegroundWindow(), событие WM_LANGCHANGEREQUEST с кодом нужной раскладки.
M>задачу 2 пока не решил. Вот здесь советуют перехватывать событие изменения текущего окна, и, при наступлении такого события, устанавливать локально в поток активного окна ловушку оконных сообщений на WM_INPUTLANGCHANGE, чтобы дополнительно словить все Alt+Shift (или мышкой) переключения языка.
M>Я так и рассчитывал сделать, но есть 2 вопроса:
M>1. Tray-приложение не должно получать уведомления об изменениях языка, если эти изменения были вызваны tray-приложением посылкой WM_LANGCHANGEREQUEST активному окну. Как узнать, что язык поменялся моей tray-программой, и игнорировать такое событие?
M>2. Если tray-приложение 32-битный процесс, будут ли проблемы с установкой локального хука в 64-битный процесс?

M>Спасибо


Все просто:
1) SetWindowsHookEx + WH_SHELL + HSHELL_LANGUAGE — получаем все извещения о смене языка.

2) SetWindowsHookEx + WH_CBT + HCBT_ACTIVATE|HCBT_SETFOCUS — получаем все переключения между окнами.

3) Как узнать что язык сменился самой своей программой?
А зачем узнавать-то? Какая разница кто сменил, система, Вы, другое чудное поделие? Какая собственно разница? По идее что-то нужно обновить в своем приложении (иконку) — дык и обновляйте в обработчиках, указанных выше (п.1 и п.2)
В конце концов, если так очень надо знать, то перед тем как вы меняете язык из своего приложения, кто мешает взвести какой-нить флаг у себя в программе? Только лишнее это. а) может сообщение не дойдет б) может язык не изменится в целевом приложении в) может еще какое поделие посредь вашей смены языка и еще раз сменит язык? Так что надежнее получать изменение языка именно когда об этом скажет само целевое приложение.
Aml Pages Home
Re[2]: Программное переключение keyboard layout
От: Michaels1  
Дата: 18.11.12 17:44
Оценка:
Здравствуйте, sergeyt4, Вы писали:

S>Чем хорош обработчик на таймере — он отлавливает не только переключение раскладки в текущем окне, но и смену текущего окна. А т.к. в Windows каждое приложение имеет свою текущую раскладку (вернее, в каждом UI потоке одного приложения раскладка независима), то при смене окна может измениться раскладка.


В первом сообщении я привел ссылку, где описывается, как отследить смену окна. Т.е. это не проблема. Таймер не хотелось бы использовать..
Основной вопрос — как игнорировать события изменения раскладки, вызванные моим tray-приложением? Можно ли как-нибудь "пометить" PostMessage WM_INPUTLANGCHANGEREQUEST, которое tray приложение посылает активному в данный момент окну (чужому приложению), с тем, чтобы это активное окно, поток которого захучен на сообщение WM_INPUTLANGCHANGE, не вызвало хук-коллбек в моем Tray процессе для этого "поддельного" WM_INPUTLANGCHANGEREQUEST (а реагировало только на изменение раскладки системой/пользователем)?
Re[2]: Программное переключение keyboard layout
От: okman Беларусь https://searchinform.ru/
Дата: 18.11.12 17:46
Оценка:
Здравствуйте, Carc, Вы писали:

C>Все просто:

C>1) SetWindowsHookEx + WH_SHELL + HSHELL_LANGUAGE — получаем все извещения о смене языка.

C>2) SetWindowsHookEx + WH_CBT + HCBT_ACTIVATE|HCBT_SETFOCUS — получаем все переключения между окнами.


Все так, но есть одно но. На Vista и выше хук сработает только для тех процессов,
чей integrity level равен или ниже нашего. Это значит, что если мы хотим ловить событие
переключения раскладки от любого приложения в системе, то нашу программу придется запускать
от имени администратора. Так что минусуете, по большому счету, зря. Я одно время тоже
пытался решить эту задачу универсальным способом — бился-бился, да в конце понял, что
лучше таймера с GetKeyboardLayout ничего нету.
Re[3]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 18.11.12 18:00
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, Carc, Вы писали:


C>>Все просто:

C>>1) SetWindowsHookEx + WH_SHELL + HSHELL_LANGUAGE — получаем все извещения о смене языка.

C>>2) SetWindowsHookEx + WH_CBT + HCBT_ACTIVATE|HCBT_SETFOCUS — получаем все переключения между окнами.


O>Все так, но есть одно но. На Vista и выше хук сработает только для тех процессов,

O>чей integrity level равен или ниже нашего. Это значит, что если мы хотим ловить событие
O>переключения раскладки от любого приложения в системе, то нашу программу придется запускать
O>от имени администратора. Так что минусуете, по большому счету, зря. Я одно время тоже
O>пытался решить эту задачу универсальным способом — бился-бился, да в конце понял, что
O>лучше таймера с GetKeyboardLayout ничего нету.

SetWinEventHook попробовать...
Aml Pages Home
Re[3]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 18.11.12 19:24
Оценка:
Здравствуйте, Michaels1, Вы писали:

M>Здравствуйте, sergeyt4, Вы писали:


S>>Чем хорош обработчик на таймере — он отлавливает не только переключение раскладки в текущем окне, но и смену текущего окна. А т.к. в Windows каждое приложение имеет свою текущую раскладку (вернее, в каждом UI потоке одного приложения раскладка независима), то при смене окна может измениться раскладка.


M>В первом сообщении я привел ссылку, где описывается, как отследить смену окна. Т.е. это не проблема. Таймер не хотелось бы использовать..

M>Основной вопрос — как игнорировать события изменения раскладки, вызванные моим tray-приложением? Можно ли как-нибудь "пометить" PostMessage WM_INPUTLANGCHANGEREQUEST, которое tray приложение посылает активному в данный момент окну (чужому приложению), с тем, чтобы это активное окно, поток которого захучен на сообщение WM_INPUTLANGCHANGE, не вызвало хук-коллбек в моем Tray процессе для этого "поддельного" WM_INPUTLANGCHANGEREQUEST (а реагировало только на изменение раскладки системой/пользователем)?
Код установки хука на WM_INPUTLANGCHANGEREQUEST в студию...
Aml Pages Home
Re[4]: Программное переключение keyboard layout
От: CEMb  
Дата: 20.11.12 12:51
Оценка:
Здравствуйте, Carc, Вы писали:

S>>>Достаточно запустить обычный оконный таймер (WM_TIMER) с частотой примерно 10 раз/сек


O>>Убивать, убивать, убивать, убивать, убивать, ржавой секироЙ УЖОСА ВО ИМЯ ДОБРА!!!!111пыщпыщ


O>>Я всё сказал.

C>Зачем убивать-то!?! Не стоит! Достаточно поставить WM_TIMER с частотой хотя бы "писят" раз/сек, а еще лучше "пицот" раз/сек.... И он сам памрётъ!

C>А по сути согласен!


Хмм. Наскоко помню, таймер там единственный способ отловить момент. Это даже в msdn-e написано, так что не машите тут своей пилкой для ногтей, да?

Кстати, продам с потрохами за штуку баксов уже готовую такую программу(исходники), с треем, подсвечивалкой, ремайндерами и переключателями. В этом месяце скачано 200+ раз.
Re[4]: Программное переключение keyboard layout
От: Michaels1  
Дата: 20.11.12 13:36
Оценка:
Здравствуйте, Carc, Вы писали:

C>Код установки хука на WM_INPUTLANGCHANGEREQUEST в студию...


  Скрытый текст
HWINEVENTHOOK winEventHook = 0;
HHOOK wndProcHook = 0;

void CALLBACK aWindowWentForegroundEvent(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) {
if(wndProcHook) {
UnhookWindowsHookEx(wndProcHook);
wndProcHook = 0;
}

HMODULE dllHandle=LoadLibrary("Hook.dll");
if(!dllHandle) {
MessageBox(0, "Unable to load Hook.dll", 0, 0);
return;
}
HOOKPROC hookFunction = reinterpret_cast<HOOKPROC> (GetProcAddress(dllHandle,"_aWndProcEvent@12"));
if(!hookFunction) {
MessageBox(0, "Couldn't find aWndProcEvent", 0, 0);
return;
}

wndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, hookFunction, dllHandle/*module instance*/, 0/*dwEventThread*/);
if(!wndProcHook) {
MessageBox(0, "Couldn't install a hook", 0, 0);
return;
}
}

void __stdcall OnTimer(HWND, UINT, UINT_PTR, DWORD) {
GUITHREADINFO gti;
ZeroMemory(&gti, sizeof(GUITHREADINFO));
gti.cbSize = sizeof(GUITHREADINFO);

GetGUIThreadInfo(NULL, &gti);

HWND hWnd = gti.hwndFocus ? gti.hwndFocus : gti.hwndActive;


if(!a) {
PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, (DWORD) 0x4190419);
a = 1;
} else {
PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, (DWORD) 0x4090409);
a = 0;
}
}

void MyDialog::OnInitDialog() {
winEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, aWindowWentForegroundEvent, 0, 0, WINEVENT_OUTOFCONTEXT);
::SetTimer(m_hWnd, 1, 1000, OnTimer);
}

Сама библиотека Hook.dll

extern "C" __declspec(dllexport) LRESULT CALLBACK aWndProcEvent(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam) {
if(nCode== HC_ACTION) {
CWPSTRUCT *s = (CWPSTRUCT*)lParam;
if(s->message == WM_INPUTLANGCHANGEREQUEST) {

if(!GetKeyState(VK_SCROLL)) {
keybd_event( VK_SCROLL , 0x45, KEYEVENTF_EXTENDEDKEY | 0, 1 );
keybd_event( VK_SCROLL , 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 1);
} else if(GetKeyState(VK_SCROLL)) {
keybd_event( VK_SCROLL , 0x45, KEYEVENTF_EXTENDEDKEY | 0, 1 );
keybd_event( VK_SCROLL , 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 1);
}
}
}

return CallNextHookEx(0, nCode, wParam, lParam);
}


Как этот тест-код работает:
Я устанавливаю хук на изменение текущего языка (когда язык в системе меняется — мигает Scroll lock), и устанавливаю таймер, который меняет язык текущего языка.
Так вот: Scroll lock мигает каждую секунду. А не хотелось бы — нужно чтоб скролл лок менял состояние только когда язык меняется ОС/пользователем, а не моим приложением.

Зачем мне это нужно: я пишу программу которая, по нажатию Scroll lock ON, должна выставить язык1, по нажатию Scroll lock OFF — язык2, при изменении тек. языка пользователем (Ctrl+Shift, Alt+Shift) — зажечь Scroll lock если выбранный язык принадлежит множеству {язык3, язык5, язык7, ...}, и погасить Scroll lock если принадлежит другому множеству {язык4, язык6, язык8, ...}.
Вот такое странное ТЗ мне дали

Поэтому мне и нужно знать в хук-коллбек-процедуре, что язык поменялся моим приложением или кем-то другим...
Как такое реализовать?

(Как я понял после экспериментов, для корректной работы такого в 64-битных системах нужно создать еще 64-битную программку (который установит хук в 64-битные процессы) и 64-битную dll, в дополнение к существующим 32-битным версиям..)
Re[5]: Программное переключение keyboard layout
От: Michaels1  
Дата: 20.11.12 13:38
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Хмм. Наскоко помню, таймер там единственный способ отловить момент. Это даже в msdn-e написано, так что не машите тут своей пилкой для ногтей, да?


Где именно написано?
Таймер — источник race conditions в моем случае..
Re[6]: Программное переключение keyboard layout
От: CEMb  
Дата: 20.11.12 15:14
Оценка:
Здравствуйте, Michaels1, Вы писали:

CEM>>Хмм. Наскоко помню, таймер там единственный способ отловить момент. Это даже в msdn-e написано, так что не машите тут своей пилкой для ногтей, да?


M>Где именно написано?

M>Таймер — источник race conditions в моем случае..

Не нашёл, значит я наврал
Вобщем, н лет назад мы с какого-то примера сдули вариант с опросом по таймеру. Я думал, что с мсдн-овского.
А так таймер — да, самое плохое решение. Но в данном случае небольшой опрос нормально подходил для решения задачи.
Re[5]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.11.12 08:43
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Carc, Вы писали:


S>>>>Достаточно запустить обычный оконный таймер (WM_TIMER) с частотой примерно 10 раз/сек


O>>>Убивать, убивать, убивать, убивать, убивать, ржавой секироЙ УЖОСА ВО ИМЯ ДОБРА!!!!111пыщпыщ


O>>>Я всё сказал.

C>>Зачем убивать-то!?! Не стоит! Достаточно поставить WM_TIMER с частотой хотя бы "писят" раз/сек, а еще лучше "пицот" раз/сек.... И он сам памрётъ!

C>>А по сути согласен!


CEM>Хмм. Наскоко помню, таймер там единственный способ отловить момент. Это даже в msdn-e написано, так что не машите тут своей пилкой для ногтей, да?

Ой ли? Случаем ли в подразделе "Programming India Today"?

CEM>Кстати, продам с потрохами за штуку баксов уже готовую такую программу(исходники), с треем, подсвечивалкой, ремайндерами и переключателями. В этом месяце скачано 200+ раз.

Переключалка раскладки в трее? А стандартная вроде бесплатно в упаковке и так есть? И напоминалки чего? Не забудь переключить раскладку?
Aml Pages Home
Re[7]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.11.12 08:46
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Michaels1, Вы писали:


CEM>>>Хмм. Наскоко помню, таймер там единственный способ отловить момент. Это даже в msdn-e написано, так что не машите тут своей пилкой для ногтей, да?


M>>Где именно написано?

M>>Таймер — источник race conditions в моем случае..

CEM>Не нашёл, значит я наврал

CEM>Вобщем, н лет назад мы с какого-то примера сдули вариант с опросом по таймеру. Я думал, что с мсдн-овского.
CEM>А так таймер — да, самое плохое решение. Но в данном случае небольшой опрос нормально подходил для решения задачи.
В данном случае? В случае топик-стартера? Постоянно работающая хелпер-софтина, которая трочитъ все декстопные приложения по несколько раз в секунду? Причем по барабану что там происходит, просмотр порнухи видео, проигрывание заставки Windows, отсутствие пользовательского ввода!?!

Убивать таких толстовцев надо (C)
Aml Pages Home
Re[5]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.11.12 09:01
Оценка:
[поскипано]

M>(Как я понял после экспериментов, для корректной работы такого в 64-битных системах нужно создать еще 64-битную программку (который установит хук в 64-битные процессы) и 64-битную dll, в дополнение к существующим 32-битным версиям..)

Да, нужно создавать.

М-дя, мутный какой-то код... Зачем вообще хук-процедуру экспортировать из DLL? Для установки хука вполне достаточно системе дать ее адрес, а торчать наружу для вызова ей необходимости нет.

Ну и потом, когда язык меняется приложением можно банально взвести какой-нибудь флаг в DLL, и при получении управления в хуковой процедуре проверять этот флаг, если взведен, то соответственно ничего не делать со скролл-локом.

Только мутно это все и багообразующе капитально. ДЛЛ будет грузиться во все процессы, и каждый раз этот флаг будет находиться в чужом адресном пространстве. Соответственно, нужно шарить эту память между процессами. А это уже еще интереснее, в любом момент любой поток любого процесса по сути сможет попробовать получить доступ к этому флагу. Нужна будет синхронизация...

Тяжелый вариант получится — шаг в сторону\шаг на месте и здравствуй трудноуловимые баги. Как вариант можно попробовать переложить функционал манипулирования скролл-локом на свой exe. И соответственно из хуковой процедуры как-то передавать ему управление (чего-нить вроде WM_COPYDATA, или взводить какой-нить эвент из DLL, который будет ожидаться в exe).

В общем я бы переделал дизайн в целом... Отчасти я нечто подобное делал в Aml Maple. Там именно так сделано, некоторые вещи всегда выполняет именно exe-приложение, DLL только смотрит. Не скажу что верх идеала, чего уж тут. Но поскольку это не самая популярная возможность, а задач и так с головой хватает, то этот функционал так и оставил пока. DLL смотрит за языком, когда нужно оповещает exe, он решает что и когда делать. Тупо, в лоб, но работает. Для третьесортной возможности пока сойдет. Ну а когда время выдается, пишутся новые варианты толковее реализованные, но это больше для души и желания поковыряться в поисках красивого решения. До релизного варианта так ничего и не доводил пока.
Aml Pages Home
Re[8]: Программное переключение keyboard layout
От: CEMb  
Дата: 21.11.12 09:45
Оценка:
Здравствуйте, Carc, Вы писали:

CEM>>А так таймер — да, самое плохое решение. Но в данном случае небольшой опрос нормально подходил для решения задачи.

C>В данном случае? В случае топик-стартера? Постоянно работающая хелпер-софтина, которая трочитъ все декстопные приложения по несколько раз в секунду? Причем по барабану что там происходит, просмотр порнухи видео, проигрывание заставки Windows, отсутствие пользовательского ввода!?!

Зачем все? Ему же тока активное надо? И раз в секунду — нормально, не квейк же.
Да и уже фигня-вопрос, твой вариант
Автор: Carc
Дата: 18.11.12
 более нормальный, просто когда писали коран мою программу, я тогда ещё про этот шелловский хук не знал ничего Единственное, чё добавлю: можно это сделать без хука, подписавшись
Автор: CEMb
Дата: 29.10.12
 на событие. Тогда 86vs64 + dll сторонние — по барабану, что сильно упрощает жизнь.

Btw, вон та фигня, в трее, которая язык(раскладку) показывает, на самом деле напрямик встраивается в процесс текущего окна. Т.е. вон то малекнькое окошко TF_FloatingLangBar_WndTitle — оно прям в текущем процессе. Узнал случайно, когда красил окна оно тоже вслед за процессом красилось.
Re[9]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.11.12 10:02
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Carc, Вы писали:


CEM>>>А так таймер — да, самое плохое решение. Но в данном случае небольшой опрос нормально подходил для решения задачи.

C>>В данном случае? В случае топик-стартера? Постоянно работающая хелпер-софтина, которая трочитъ все декстопные приложения по несколько раз в секунду? Причем по барабану что там происходит, просмотр порнухи видео, проигрывание заставки Windows, отсутствие пользовательского ввода!?!

CEM>Зачем все? Ему же тока активное надо? И раз в секунду — нормально, не квейк же.

В принципе раз в секунду и диск форматировать то же нормально, главное щоб железка тянула...
Вопрос один, ЗАЧЕМ? Главное, зачем оно пользователю? Тут в принципе есть нормальный ответ, как ни странно. Если код который что-то там по таймеру более надежен и легок в сопровождении, то опять же, как ни странно, это пользователю надо. Хоть он об этом и не знает. Работает и решает проблемы пользователя — значь смысел езь! Но все ж, мы ж не просто пользователи? Имеет смысл и поискать решение.
Но никогда не забываем о старом архитектурном принципе: вопрос не выбора "А" или "Б". А какого фига вообще дизайн заставляет нас выбирать? И нельзя бы, чтобы всё было, а нам за это ничего не было оттянуть решение на попозжее? Ибо поздний выбор в архитектуре завсегда дешевше обходится (ибо информации как правило для выбора решения "А" или "Б" больше, и "чиста тетеретически", выбор правильнее.

Иногда можно и по таймеру, сам иногда балуюсь этим решением в одном вполне рабочем и живом проекте и именно про раскладку. Так что иногда можно и так. Вопрос только когда это "иногда" оправдано, а когда нет. У топик-стартера нет. Там задачка в принципе несложная: смена окна + смена языка. Ловится это и методами ловушек (хуки, подписка на события я в этом, несколько широком аспекте говорю).

CEM>Да и уже фигня-вопрос, твой вариант
Автор: Carc
Дата: 18.11.12
 более нормальный, просто когда писали коран мою программу, я тогда ещё про этот шелловский хук не знал ничего Единственное, чё добавлю: можно это сделать без хука, подписавшись
Автор: CEMb
Дата: 29.10.12
 на событие. Тогда 86vs64 + dll сторонние — по барабану, что сильно упрощает жизнь.

Вот и я про то же. Иногда упрощение жизни стоит того, чтобы заставить лишний раз калькулятор впустую посчитать код раз в секунду. Но в то же время и на академический интерес с прибором класть не надо.
А шел-хук он непростой. Там был вариант и без DLL, а хук глобальный. Только undocumented он, вроде в 2К еще работал — дальше на память не вспомню. В общем там подумать стоит. В приниципе отдетектить доступность того или иного решения в ран-тайм несложно, можно на лету выбирать стратегию с DLL-хуком или глобальный хук в exe, пусть и undocumented.

CEM>Btw, вон та фигня, в трее, которая язык(раскладку) показывает, на самом деле напрямик встраивается в процесс текущего окна. Т.е. вон то малекнькое окошко TF_FloatingLangBar_WndTitle — оно прям в текущем процессе. Узнал случайно, когда красил окна оно тоже вслед за процессом красилось.

Ну это где как? В старых виндах по моему эта иконка отдельной жизнью жила, и работала аккурат через хуки.
Aml Pages Home
Re[10]: Программное переключение keyboard layout
От: CEMb  
Дата: 21.11.12 10:17
Оценка:
Здравствуйте, Carc, Вы писали:

C>А шел-хук он непростой. Там был вариант и без DLL, а хук глобальный. Только undocumented он, вроде в 2К еще работал — дальше на память не вспомню. В общем там подумать стоит. В приниципе отдетектить доступность того или иного решения в ран-тайм несложно, можно на лету выбирать стратегию с DLL-хуком или глобальный хук в exe, пусть и undocumented.


Не, там совсем вроде без хука, хотя написано что это типа как хук(так и есть, но) там события посылаются мессаджами подписанному окну. Т.е. не надо писать отдельную функцию для хука. Я у себя эту штуку внедрил сразу, программа сразу стала легче и шустрее(та, которая в соседней ветке).
Re[11]: Программное переключение keyboard layout
От: Carc Россия http://www.amlpages.com/home.php
Дата: 21.11.12 10:47
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Carc, Вы писали:


C>>А шел-хук он непростой. Там был вариант и без DLL, а хук глобальный. Только undocumented он, вроде в 2К еще работал — дальше на память не вспомню. В общем там подумать стоит. В приниципе отдетектить доступность того или иного решения в ран-тайм несложно, можно на лету выбирать стратегию с DLL-хуком или глобальный хук в exe, пусть и undocumented.


CEM>Не, там совсем вроде без хука, хотя написано что это типа как хук(так и есть, но) там события посылаются мессаджами подписанному окну. Т.е. не надо писать отдельную функцию для хука. Я у себя эту штуку внедрил сразу, программа сразу стала легче и шустрее(та, которая в соседней ветке).

Я про это и говорю: там в общем сводилось всё что-то вроде RegisterWindowMessage ("Чего_то_Shell_Hook_дай_мне_зараза_строка_вроде") и получаем сообщения в оконную. Но!!!
1) Не уверен насчет шустрее. Глобальный хук будет дергаться в адресном пространстве захученного процесса. Здесь в адресном пространстве процесса поставившего хук. Со всеми вытекающими: переключения контекстов, побудка потока обрабатывающего сообщения и все дела. Но это так — чистая теория — не факт как это на деле реализовано. Может быть система просто где-то в недрах ставит нужное сообщение в очередь нашего окна, и лишних приседаний минимум.

2) Во вторых. Это undocumented. Я точно не помню где, ибо этим RegisterWindowMessage + Shell_Hook еще в назапамятном детстве баловался — но факт налицо. Где-то я встречался с тем что это undocumented feature не поддерживается. В какой-то там винде. Отсюда и все вероятно будущие проблемы. А в той же Мапле мне пофиг было, там по любому DLL была для других вещей нужна. Прицепить к ней отдельный функционал хука и не мучаться больше с undocumented было простым решением. Эти недокументированные вещи я юзал только в exe-файле, да и то это было в состоянии Research-функциоанала (там просто понадобилась другая архитектура наблюдатель\подписчик на события, причем наблюдатель только интерфейсом торчит наружу, поэтому легко пробовались разные способы. Но опять же это все в стадии пробы сил, проверки идей, не уверен что я бы решился на такую реализацию в релизном, законченном варианте).
Aml Pages Home
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.