1use crate::memory::HeapMemory;
15use crate::{
16 common::{HWND, LPARAM},
17 ext::StringExt,
18};
19pub use windows::Win32::UI::{
20 Controls::{HOTKEYF_ALT, HOTKEYF_CONTROL, HOTKEYF_EXT, HOTKEYF_SHIFT},
21 Input::{
22 Ime::{
23 CANDIDATELIST, HIMC, IME_CMODE_ALPHANUMERIC, IME_CMODE_CHARCODE, IME_CMODE_CHINESE,
24 IME_CMODE_EUDC, IME_CMODE_FIXED, IME_CMODE_FULLSHAPE, IME_CMODE_HANGEUL,
25 IME_CMODE_HANGUL, IME_CMODE_HANJACONVERT, IME_CMODE_JAPANESE, IME_CMODE_KATAKANA,
26 IME_CMODE_LANGUAGE, IME_CMODE_NATIVE, IME_CMODE_NATIVESYMBOL, IME_CMODE_NOCONVERSION,
27 IME_CMODE_RESERVED, IME_CMODE_ROMAN, IME_CMODE_SOFTKBD, IME_CMODE_SYMBOL,
28 IME_CONVERSION_MODE, IME_SENTENCE_MODE, IME_SMODE_AUTOMATIC, IME_SMODE_CONVERSATION,
29 IME_SMODE_NONE, IME_SMODE_PHRASEPREDICT, IME_SMODE_PLAURALCLAUSE, IME_SMODE_RESERVED,
30 IME_SMODE_SINGLECONVERT, IMN_CHANGECANDIDATE, IMN_CLOSECANDIDATE,
31 IMN_CLOSESTATUSWINDOW, IMN_GUIDELINE, IMN_OPENCANDIDATE, IMN_OPENSTATUSWINDOW,
32 IMN_PRIVATE, IMN_SETCANDIDATEPOS, IMN_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONWINDOW,
33 IMN_SETCONVERSIONMODE, IMN_SETOPENSTATUS, IMN_SETSENTENCEMODE, IMN_SETSTATUSWINDOWPOS,
34 IMN_SOFTKBDDESTROYED,
35 },
36 KeyboardAndMouse::{
37 VIRTUAL_KEY, VK_0, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6, VK_7, VK_8, VK_9, VK_A,
38 VK_ABNT_C1, VK_ABNT_C2, VK_ACCEPT, VK_ADD, VK_APPS, VK_ATTN, VK_B, VK_BACK,
39 VK_BROWSER_BACK, VK_BROWSER_FAVORITES, VK_BROWSER_FORWARD, VK_BROWSER_HOME,
40 VK_BROWSER_REFRESH, VK_BROWSER_SEARCH, VK_BROWSER_STOP, VK_C, VK_CANCEL, VK_CAPITAL,
41 VK_CLEAR, VK_CONTROL, VK_CONVERT, VK_CRSEL, VK_D, VK_DBE_ALPHANUMERIC,
42 VK_DBE_CODEINPUT, VK_DBE_DBCSCHAR, VK_DBE_DETERMINESTRING,
43 VK_DBE_ENTERDLGCONVERSIONMODE, VK_DBE_ENTERIMECONFIGMODE, VK_DBE_ENTERWORDREGISTERMODE,
44 VK_DBE_FLUSHSTRING, VK_DBE_HIRAGANA, VK_DBE_KATAKANA, VK_DBE_NOCODEINPUT,
45 VK_DBE_NOROMAN, VK_DBE_ROMAN, VK_DBE_SBCSCHAR, VK_DECIMAL, VK_DELETE, VK_DIVIDE,
46 VK_DOWN, VK_E, VK_END, VK_EREOF, VK_ESCAPE, VK_EXECUTE, VK_EXSEL, VK_F, VK_F1, VK_F10,
47 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20,
48 VK_F21, VK_F22, VK_F23, VK_F24, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9,
49 VK_FINAL, VK_FPARAM, VK_G, VK_GAMEPAD_A, VK_GAMEPAD_B, VK_GAMEPAD_DPAD_DOWN,
50 VK_GAMEPAD_DPAD_LEFT, VK_GAMEPAD_DPAD_RIGHT, VK_GAMEPAD_DPAD_UP,
51 VK_GAMEPAD_LEFT_SHOULDER, VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON,
52 VK_GAMEPAD_LEFT_THUMBSTICK_DOWN, VK_GAMEPAD_LEFT_THUMBSTICK_LEFT,
53 VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT, VK_GAMEPAD_LEFT_THUMBSTICK_UP,
54 VK_GAMEPAD_LEFT_TRIGGER, VK_GAMEPAD_MENU, VK_GAMEPAD_RIGHT_SHOULDER,
55 VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON, VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN,
56 VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT, VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT,
57 VK_GAMEPAD_RIGHT_THUMBSTICK_UP, VK_GAMEPAD_RIGHT_TRIGGER, VK_GAMEPAD_VIEW,
58 VK_GAMEPAD_X, VK_GAMEPAD_Y, VK_H, VK_HANGEUL, VK_HANGUL, VK_HANJA, VK_HELP, VK_HOME,
59 VK_I, VK_ICO_00, VK_ICO_CLEAR, VK_ICO_HELP, VK_IME_OFF, VK_IME_ON, VK_INSERT, VK_J,
60 VK_JUNJA, VK_K, VK_KANA, VK_KANJI, VK_L, VK_LAUNCH_APP1, VK_LAUNCH_APP2,
61 VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LBUTTON, VK_LCONTROL, VK_LEFT, VK_LMENU,
62 VK_LSHIFT, VK_LWIN, VK_M, VK_MBUTTON, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE,
63 VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP, VK_MENU, VK_MODECHANGE, VK_MULTIPLY, VK_N,
64 VK_NAVIGATION_ACCEPT, VK_NAVIGATION_CANCEL, VK_NAVIGATION_DOWN, VK_NAVIGATION_LEFT,
65 VK_NAVIGATION_MENU, VK_NAVIGATION_RIGHT, VK_NAVIGATION_UP, VK_NAVIGATION_VIEW, VK_NEXT,
66 VK_NONAME, VK_NONCONVERT, VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
67 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_O, VK_OEM_1,
68 VK_OEM_102, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5, VK_OEM_6, VK_OEM_7, VK_OEM_8,
69 VK_OEM_ATTN, VK_OEM_AUTO, VK_OEM_AX, VK_OEM_BACKTAB, VK_OEM_CLEAR, VK_OEM_COMMA,
70 VK_OEM_COPY, VK_OEM_CUSEL, VK_OEM_ENLW, VK_OEM_FINISH, VK_OEM_FJ_JISHO, VK_OEM_FJ_LOYA,
71 VK_OEM_FJ_MASSHOU, VK_OEM_FJ_ROYA, VK_OEM_FJ_TOUROKU, VK_OEM_JUMP, VK_OEM_MINUS,
72 VK_OEM_NEC_EQUAL, VK_OEM_PA1, VK_OEM_PA2, VK_OEM_PA3, VK_OEM_PERIOD, VK_OEM_PLUS,
73 VK_OEM_RESET, VK_OEM_WSCTRL, VK_P, VK_PA1, VK_PACKET, VK_PAUSE, VK_PLAY, VK_PRINT,
74 VK_PRIOR, VK_PROCESSKEY, VK_Q, VK_R, VK_RBUTTON, VK_RCONTROL, VK_RETURN, VK_RIGHT,
75 VK_RMENU, VK_RSHIFT, VK_RWIN, VK_S, VK_SCROLL, VK_SELECT, VK_SEPARATOR, VK_SHIFT,
76 VK_SLEEP, VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_T, VK_TAB, VK_U, VK_UP, VK_V,
77 VK_VOLUME_DOWN, VK_VOLUME_MUTE, VK_VOLUME_UP, VK_W, VK_X, VK_XBUTTON1, VK_XBUTTON2,
78 VK_Y, VK_Z, VK_ZOOM,
79 },
80 },
81 WindowsAndMessaging::{
82 WM_CHAR, WM_DEADCHAR, WM_IME_CHAR, WM_IME_COMPOSITION, WM_IME_COMPOSITIONFULL,
83 WM_IME_CONTROL, WM_IME_ENDCOMPOSITION, WM_IME_KEYDOWN, WM_IME_KEYLAST, WM_IME_KEYUP,
84 WM_IME_NOTIFY, WM_IME_REQUEST, WM_IME_SELECT, WM_IME_SETCONTEXT, WM_IME_STARTCOMPOSITION,
85 WM_KEYDOWN, WM_KEYUP, WM_MOUSEMOVE, WM_SYSCHAR, WM_SYSDEADCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
86 },
87};
88use windows::Win32::{
89 Foundation::POINT,
90 UI::{
91 Input::{
92 Ime::{
93 ImmGetCandidateListCountW, ImmGetCandidateListW, ImmGetContext,
94 ImmGetConversionStatus, ImmReleaseContext,
95 },
96 KeyboardAndMouse::{
97 keybd_event, mouse_event, GetAsyncKeyState, GetFocus, GetKeyNameTextW, GetKeyState,
98 SetActiveWindow, KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP, MOUSEEVENTF_LEFTDOWN,
99 MOUSEEVENTF_LEFTUP, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP,
100 },
101 },
102 WindowsAndMessaging::{GetCursorPos, SetCursorPos},
103 },
104};
105
106pub fn set_active_window(h_wnd: HWND) -> HWND {
115 unsafe { SetActiveWindow(h_wnd).unwrap_or(Default::default()) }
116}
117
118pub fn get_focus() -> HWND {
127 unsafe { GetFocus() }
128}
129
130pub fn get_async_key_state(key: VIRTUAL_KEY) -> (bool, bool) {
135 let state = unsafe { GetAsyncKeyState(key.0 as i32) };
136 let (high, low) = (state >> 8, state & 0xff);
137 (high != 0, low != 0)
138}
139
140pub fn get_key_state(key: VIRTUAL_KEY) -> (bool, bool) {
145 let state = unsafe { GetKeyState(key.0 as i32) };
146 let high = state >> 8;
147 let low = state & 0xffi16;
148 (high != 0, low != 0)
149}
150
151pub fn send_key(key: VIRTUAL_KEY) {
153 unsafe {
154 keybd_event(key.0 as u8, 0, KEYEVENTF_EXTENDEDKEY, 0);
155 keybd_event(key.0 as u8, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
156 }
157}
158
159pub fn get_key_name(l_param: &LPARAM) -> String {
163 unsafe {
164 let mut text: [u16; 16] = [0; 16];
165 let len = GetKeyNameTextW(l_param.0 as i32, &mut text);
166 String::from_utf16_lossy(&text[..len as usize])
167 }
168}
169
170pub fn imm_get_context(h_wnd: HWND) -> HIMC {
176 unsafe { ImmGetContext(h_wnd) }
177}
178
179pub fn imm_release_context(h_wnd: HWND, h_imc: HIMC) -> bool {
185 unsafe { ImmReleaseContext(h_wnd, h_imc) }.as_bool()
186}
187
188pub fn imm_get_candidate_list_count(h_imc: HIMC) -> (u32, u32) {
193 unsafe {
194 let mut list_count = 0u32;
195 let buffer_len = ImmGetCandidateListCountW(h_imc, &mut list_count);
196 (buffer_len, list_count)
197 }
198}
199
200pub fn imm_get_candidate_list(h_imc: HIMC, index: u32) -> Option<(CANDIDATELIST, Vec<String>)> {
206 unsafe {
207 let len = ImmGetCandidateListW(h_imc, index, None, 0);
208 if len < 1 {
209 return None;
210 }
211 let heap = HeapMemory::default();
212 let ptr = heap.alloc((len + 1) as usize);
213 ptr.write_bytes(b'0', (len + 1) as usize);
215 let p_list = ptr as *mut CANDIDATELIST;
216 ImmGetCandidateListW(h_imc, index, Some(p_list), len);
217 let list = *p_list;
218 let p1 = p_list as *const u32;
219 let p2 = p_list as *const u8;
220 let mut data = Vec::new();
221 for i in 0..list.dwCount {
222 let offset = *p1.wrapping_add(6 + i as usize); data.push(p2.wrapping_add(offset as usize).to_string_utf16());
226 }
227 heap.free(ptr);
228 Some((list, data))
229 }
230}
231
232pub fn imm_get_conversion_status(h_imc: HIMC) -> Option<(IME_CONVERSION_MODE, IME_SENTENCE_MODE)> {
239 unsafe {
240 let (mut conversion, mut sentence) = std::mem::zeroed();
241 if !ImmGetConversionStatus(h_imc, Some(&mut conversion), Some(&mut sentence)).as_bool() {
242 return None;
243 }
244 Some((conversion, sentence))
245 }
246}
247
248pub fn click(x: i32, y: i32) {
250 unsafe {
251 SetCursorPos(x, y).expect("SetCursorPos failed");
252 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
253 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
254 }
255}
256
257pub fn right_click(x: i32, y: i32) {
259 unsafe {
260 SetCursorPos(x, y).expect("SetCursorPos failed");
261 mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
262 mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
263 }
264}
265
266pub fn get_cur_mouse_point() -> (i32, i32) {
268 unsafe {
269 let mut point = POINT { x: 0, y: 0 };
270 GetCursorPos(&mut point).expect("GetCursorPos failed");
271 (point.x, point.y)
272 }
273}