середа, 11 серпня 2010 р.

Як я провів вихідні


В ори­гі­наль­ній пр­огра­мі, яка пе­ре­клю­чає роз­клад­ки кла­ві­а­тур, пер­ша кноп­ка на но­вій кла­ві­а­ту­рі вво­ди­ть­ся зі ста­рою роз­клад­кою. Я че­с­но на­ма­гав­ся звик­ну­ти до цьо­го, але не зміг. І то­ді ви­рі­шив зро­би­ти не­мож­ли­ве: ви­пра­ви­ти цей не­до­лік. Про­б­ле­ма бу­ла в то­му, що по­дія WM_INPUT від­бу­ва­є­ть­ся вже піс­ля об­роб­ки по­дії на­тис­кан­ня на кноп­ку. Ме­ні ж не­об­хід­но бу­ло вста­ви­ти по­відом­лен­ня про пе­ре­ми­кан­ня роз­клад­ки до по­відом­лен­ня про на­тис­кан­ня кноп­ки. Для то­го, щоб пе­ре­хо­пи­ти цю по­дію, у Вік­нах іс­нує за­чіп­ка на WH_KEYBOARD_LL, яка ви­кли­ка­є­ть­ся піс­ля об­роб­ки кла­ві­ши драй­ве­ром. Зда­ва­ло­ся б, про­б­лем не­ма, але... в цей мо­мент не­мож­ли­во ви­зна­чи­ти фі­зич­ну кла­ві­а­ту­ру. Оче­вид­но, доб­рі дріб­но­м'я­кі пр­огра­міс­ти ви­рі­ши­ли нас убе­рег­ти від зай­вої ін­фор­ма­ції...

Я так ро­зу­мію, пра­ви­ль­ний під­хід — це ска­ча­ти WDK, ро­зі­бра­ти­ся як пра­цює кла­ві­а­тур­ний фільтр і на­в­чи­ти­ся пе­ре­да­ва­ти з нь­о­го по­відом­лен­ня про по­точ­ну кла­ві­а­ту­ру, щоб пр­огра­ма всти­га­ла пе­ре­клю­чи­ти роз­клад­ку... Як­би я був справ­ж­нім пр­огра­міс­том, я б так і зро­бив: уяв­ляю со­бі вже справ­ж­ній ін­ста­ля­тор, який ви­ма­гає па­роль ад­мі­ніс­т­ра­то­ра, щоб ус­та­но­ви­ти кла­ві­а­тур­ний фільтр, а піс­ля ус­та­нов­ки пе­ре­за­ван­та­жу­ва­ти­ме сис­те­му. Са­ме так все і пра­цює під Вік­нами в ре­аль­но­му жит­ті!

Та я ви­рі­шив обі­йти­ся тим, що є. От­же, для кож­ної кла­ві­а­тур­ної по­дії спо­чат­ку ви­ко­ну­є­ть­ся за­чіп­ка на WH_KEYBOARD_LL, а по­тім об­роб­ник по­дії WM_INPUT який знає, яку роз­клад­ку ви­бра­ти. Пер­ше, що при­йшло в го­ло­ву, — не ґе­не­ру­ва­ти по­дію на­тис­кан­ня кноп­ки, а на­то­мість збе­рі­га­ти всі кноп­ки за до­по­м­о­гою за­чіп­ки, щоб піс­ля пе­ре­ми­кан­ня роз­клад­ки, від­пра­ви­ти їх по чер­зі за до­по­м­о­гою keybd_event. Ве­сь при­кол в то­му, що як­що пе­ре­рва­ти ге­не­ру­ван­ня по­дії на­тис­кан­ня кноп­ки, вер­нув­ши за­чіп­кою -1, то і по­дія WM_INPUT не на­стає! Та­ким чи­ном, узна­ти з якої кла­ві­а­ту­ри при­йшов сиг­нал про на­тис­кан­ня кноп­ки мож­на тіль­ки піс­ля то­го, як цей сиг­нал бу­ло об­роб­ле­но.

Сим­вол з ко­ду­ван­ням від чу­жої кла­ві­а­ту­ри об­роб­ля­є­ть­ся при на­тис­кан­ні на кноп­ку. А відпус­кан­ня кноп­ки за­зви­чай ні­ч­о­го пога­н­о­го не ро­бить. Отож мож­на по­че­ка­ти ко­ли кноп­ку відпу­щ­е­но, пе­ре­да­ти цей сиг­нал, ви­зна­чи­ти кла­ві­а­ту­ру, пе­ре­мк­ну­ти, як­що по­тріб­но, роз­клад­ку, а по­тім вве­с­ти цей сим­вол ще раз за до­по­м­о­гою keybd_event. Це призво­дить до на­ступ­н­о­го ефек­ту: як­що ми на­тис­ка­є­мо, на­при­клад, SHIFT от­ри­му­є­мо та­ку по­с­лідов­ність по­дій — SHIFT відпу­щ­е­но, SHIFT на­тисну­то, SHIFT відпу­щ­е­но за­мість SHIFT на­тисну­то, а по­тім відпу­щ­е­но. Са­ма по со­бі ця по­с­лідов­ність не має фа­таль­них на­с­лід­ків. Але ра­зом з від­по­від­ни­ми не­кон­т­ро­льо­ва­ни­ми по­ді­я­ми для CTRL і ALT мо­же пе­ре­клю­ча­ти в якісь не­зви­чай­ні ре­жи­ми, ко­ли сис­те­ма ду­має, що ваш SHIFT на­тисну­то, у той час, ко­ли ви йо­го відпус­ти­ли. Ви­рі­шен­ня ці­єї про­б­ле­ми по­ля­гає в то­му, що при на­тис­кан­ні цих трьох кно­пок, ми зав­жди ство­рю­є­мо по­дію.

Це пра­цює. Але ство­рює од­ну не­зруч­ність: як­що відпус­ти­ти, на­при­клад, SHIFT до то­го, як по­дію на­тис­кан­ня на букву бу­ло об­роб­ле­но (на­тис­ну­ти SHIFT, на­тис­ну­ти букву, відпус­ти­ти SHIFT, відпус­ти­ти букву), SHIFT не спра­цьо­вує — і на­би­ра­є­ть­ся ма­лень­ка бук­ва. Те са­ме сто­су­є­ть­ся ALT і CTRL. По­дію відпус­кан­ня обо­в'яз­ко­во не­об­хід­но пе­ре­да­ти, бо инак­ше WM_INPUT не від­бу­де­ть­ся, а зна­чить мож­на впус­ти­ти лан­цюг ви­ко­нан­ня бу­фе­ра. То­му від­прав­ля­є­ть­ся по­дія відпус­кан­ня, а в бу­фер за­пи­су­є­ть­ся вір­ту­аль­не на­тис­кан­ня ці­єї ж кноп­ки спо­чат­ку і відпус­кан­ня її ж укін­ці.

Та най­ці­ка­ві­ше бу­ло по­пе­ре­ду. При пе­ре­хо­ді від од­ної кла­ві­а­ту­ри до ин­шої, як­що на­тис­ну­ти од­но­час­но кіль­ка кно­пок, во­ни на­тис­ка­ю­ть­ся з CTRL. Як з'я­су­ва­ло­ся, при­чи­на в то­му, що піс­ля по­відом­лен­ня про змі­ну роз­клад­ки, з кла­ві­а­ту­ри при­хо­дить по­дія віпус­кан­ня CTRL. Пра­по­рець ви­став­ле­ний, як по­дія на ре­аль­ній кла­ві­а­ту­рі, при то­му що ні­як­о­го CTRL я не тор­ка­ю­ся! Тоб­то ця по­дія при­хо­дить са­ме від драй­ве­ра, і я на­віть уя­ви­ти бо­ю­ся чо­му... Від­так я зро­зу­мів, що моя кла­ві­а­тур­на но­ва­ція не вно­сить особ­ли­в­о­го ха­о­су в уже ціл­ком ха­о­тич­ну по­ве­дін­ку сис­те­ми. То­му піс­ля змі­ни роз­клад­ки, я про­с­то ви­став­ляю пра­по­рець не збе­рі­га­ти CTRL, ALT і SHIFT у бу­фер до­ки бу­фер не очис­ти­ть­ся і по­збав­ля­ю­ся ці­єї про­б­ле­ми.

Втім, не­хо­ро­шу по­ве­дін­ку ви­клю­чи­ти пов­ніс­тю я не зу­мів. Як­що, на­при­клад, на­тис­ну­ти SHIFT на од­ній кла­ві­а­ту­рі, а букву на ин­шій, пр­огра­ма сміш­но на­ма­га­є­ть­ся встиг­ну­ти пе­ре­клю­чи­ти­ся дві­чі, але їй це не вда­є­ть­ся. В ре­зуль­та­ті вво­ди­ть­ся ма­лень­ка бук­ва з роз­клад­ки кла­ві­а­ту­ри, на якій на­тисну­то SHIFT. Вза­га­лі, як­що по­тре­ну­ва­ти­ся, мож­на зро­би­ти там пе­ре­пов­нен­ня бу­фе­ра, або­що — та в нор­маль­но­му ре­жи­мі пра­цює до­сить при­стой­но як для збо­чен­ня...

Ще один не ду­же при­єм­ний ефект — сим­вол вво­ди­ть­ся піс­ля відпус­кан­ня кноп­ки, а не піс­ля на­тис­кан­ня. З ці­єї ж при­чи­ни не­адек­ват­но об­роб­ля­є­ть­ся за­тис­кан­ня од­ної кноп­ки на де­який час. Сим­во­ли з'яв­ля­ю­ть­ся з за­піз­нен­ням і пер­ший бу­де зі ста­рої кла­ві­а­ту­ри. Ду­маю, як­що ви звик­ли до слі­п­о­го на­бо­ру, то, мож­ли­во, за­чіп­ку кра­ще від­клю­чи­ти і про­с­то при­сто­су­ва­ти­ся до не­пра­ви­ль­н­о­го пер­ш­о­го сим­во­лу при пе­ре­хо­ді з од­ної кла­ві­а­ту­ри на ин­шу.


Ну і про не­ос­нов­не, але най­більш по­міт­не... Я зро­бив ви­бір роз­клад­ки для кож­ної мо­ви. Це пе­ре­тво­рює пр­ограм­ку на до­сить та­ку уні­вер­саль­ну шту­ку. Уя­віть, що у вас п'ять кла­ві­а­тур з різ­ною кіль­кіс­тю кно­пок. Це не при­кол: у вас мо­же бу­ти но­ут­бук плюс USB-кла­ві­а­ту­ра вдо­ма, на ро­бо­ті, в дру­зів — всю­ди різ­ні. І ви на­би­ра­є­те текст де­ся­ть­ма мо­ва­ми. За до­по­м­о­гою ці­єї пр­огра­ми ви мо­же­те на­лаш­ту­ва­ти для кож­ної па­ри кла­ві­а­ту­ра-мо­ва ок­ре­му роз­клад­ку з ав­то­ма­тич­ним пе­ре­клю­чен­ням на неї при на­бо­рі. Для де­яких кла­ві­а­тур мож­на за­да­ти мо­ви, для яких во­ни не пра­цю­ють, — на них не мож­на бу­де пе­ре­клю­чи­ти­ся за до­по­м­о­гою ці­єї кла­ві­а­ту­ри. Для цьо­го при пер­шо­му на­тис­кан­ні кноп­ки у та­ких мо­вах слід за­да­ти роз­клад­ку з ин­шої мо­ви.

Най­про­с­ті­ша кон­фіґу­ра­ція: дві мо­ви, — на­при­клад: ук­ра­їн­сь­ка та ан­г­лі­йсь­ка, — і дві кла­ві­а­ту­ри — по од­ній для кож­ної мо­ви.
  • Спо­чат­ку ви­би­ра­є­мо ан­г­лі­йсь­ку мо­ву і на­тис­ка­є­мо на кноп­ку «ук­ра­їн­сь­кої» кла­ві­а­ту­ри.
  • Ста­ви­мо їй роз­клад­ку ук­ра­їн­сь­кої мо­ви. Пр­огра­ма пе­ре­клю­ча­є­ть­ся на ук­ра­їн­сь­ку мо­ву.
  • Те­пер на­тис­ка­є­мо кноп­ку «ан­г­лі­йсь­кої» кла­ві­а­ту­ри і ви­би­ра­є­мо їй ан­г­лі­йсь­ку роз­клад­ку.
  • Від­те­пер кноп­ки на ан­г­лі­йсь­кій кла­ві­а­ту­рі ав­то­ма­тич­но вво­ди­ти­муть ан­г­лі­йсь­кі бук­ви, а ук­ра­їн­сь­кої — ук­ра­їн­сь­кі.
Пр­ограм­ку від­клю­ча­ти не по­тріб­но. Це ще од­на особ­ли­вість, яку я до­дав: пр­огра­ма ба­чить но­ві кла­ві­а­ту­ри і роз­клад­ки на льо­ту. Ну і, зви­чай­но, па­м'я­тає всі кла­ві­а­ту­ри, які ко­ли-не­будь під­клю­ча­ли­ся до ва­ш­о­го ком­п'ю­те­ра. Як­що ви ви­да­ли­те роз­клад­ку, яку ви­ко­рис­то­вує якась із кла­ві­а­тур, пр­огра­ма не змо­же на неї пе­ре­клю­чи­ти­ся і мо­жуть бу­ти про­б­ле­ми. Те са­ме сто­су­є­ть­ся особ­ли­во ро­зу­м­них пр­ограм, на кшталт Бе­ла­за­ру, які за­ван­та­жу­ють влас­ні роз­клад­ки — у цьо­му ра­зі вам до­ве­де­ть­ся на­лаш­то­ву­ва­ти ре­ак­цію пр­огра­ми на но­ві мо­ви вво­ду. До­да­ва­ти но­ві роз­клад­ки мож­на без об­ме­жень, про­те од­на кла­ві­а­ту­ра мо­же ви­ко­рис­то­ву­ва­ти тіль­ки од­ну роз­клад­ку для кож­ної мо­ви.

Ска­ча­ти: пр­огра­му або код.

Як­що код вас не зля­кає, бу­ду ра­дий ко­мен­та­рям і про­по­зи­ці­ям.

Нема коментарів

Дописати коментар

Hy-phen-a-tion