win32u: Move menu tracking implementation from user32.
[wine.git] / dlls / user32 / defwnd.c
blob4c8748f10cb7d314d23e66d4414720ca22242a88
1 /*
2 * Default window procedure
4 * Copyright 1993, 1996 Alexandre Julliard
5 * 1995 Alex Korobka
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <string.h>
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winnls.h"
29 #include "imm.h"
30 #include "win.h"
31 #include "user_private.h"
32 #include "controls.h"
33 #include "wine/server.h"
34 #include "wine/exception.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(win);
39 /* bits in the dwKeyData */
40 #define KEYDATA_ALT 0x2000
41 #define KEYDATA_PREVSTATE 0x4000
43 #define DRAG_FILE 0x454C4946
45 static short iF10Key = 0;
46 static short iMenuSysKey = 0;
48 /***********************************************************************
49 * DEFWND_HandleWindowPosChanged
51 * Handle the WM_WINDOWPOSCHANGED message.
53 static void DEFWND_HandleWindowPosChanged( HWND hwnd, const WINDOWPOS *winpos )
55 RECT rect;
57 WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &rect );
58 if (!(winpos->flags & SWP_NOCLIENTMOVE))
59 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG(rect.left, rect.top));
61 if (!(winpos->flags & SWP_NOCLIENTSIZE) || (winpos->flags & SWP_STATECHANGED))
63 if (IsIconic( hwnd ))
65 SendMessageW( hwnd, WM_SIZE, SIZE_MINIMIZED, 0 );
67 else
69 WPARAM wp = IsZoomed( hwnd ) ? SIZE_MAXIMIZED : SIZE_RESTORED;
71 SendMessageW( hwnd, WM_SIZE, wp, MAKELONG(rect.right-rect.left, rect.bottom-rect.top) );
77 /***********************************************************************
78 * DEFWND_ControlColor
80 * Default colors for control painting.
82 HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType )
84 if( ctlType == CTLCOLOR_SCROLLBAR)
86 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
87 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
88 SetTextColor( hDC, GetSysColor(COLOR_3DFACE));
89 SetBkColor( hDC, bk);
91 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
92 * we better use 0x55aa bitmap brush to make scrollbar's background
93 * look different from the window background.
95 if (bk == GetSysColor(COLOR_WINDOW))
96 return SYSCOLOR_Get55AABrush();
98 UnrealizeObject( hb );
99 return hb;
102 SetTextColor( hDC, GetSysColor(COLOR_WINDOWTEXT));
104 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
105 SetBkColor( hDC, GetSysColor(COLOR_WINDOW) );
106 else {
107 SetBkColor( hDC, GetSysColor(COLOR_3DFACE) );
108 return GetSysColorBrush(COLOR_3DFACE);
110 return GetSysColorBrush(COLOR_WINDOW);
114 /***********************************************************************
115 * DEFWND_Print
117 * This method handles the default behavior for the WM_PRINT message.
119 static void DEFWND_Print( HWND hwnd, HDC hdc, ULONG uFlags)
122 * Visibility flag.
124 if ( (uFlags & PRF_CHECKVISIBLE) &&
125 !IsWindowVisible(hwnd) )
126 return;
129 * Unimplemented flags.
131 if ( (uFlags & PRF_CHILDREN) ||
132 (uFlags & PRF_OWNED) ||
133 (uFlags & PRF_NONCLIENT) )
135 WARN("WM_PRINT message with unsupported flags\n");
139 * Background
141 if ( uFlags & PRF_ERASEBKGND)
142 SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
145 * Client area
147 if ( uFlags & PRF_CLIENT)
148 SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
153 /***********************************************************************
154 * DEFWND_DefWinProc
156 * Default window procedure for messages that are the same in Ansi and Unicode.
158 static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
160 switch(msg)
162 case WM_NCMOUSEMOVE:
163 return NC_HandleNCMouseMove( hwnd, wParam, lParam );
165 case WM_NCMOUSELEAVE:
166 return NC_HandleNCMouseLeave( hwnd );
168 case WM_WINDOWPOSCHANGED:
169 DEFWND_HandleWindowPosChanged( hwnd, (const WINDOWPOS *)lParam );
170 break;
172 case WM_LBUTTONDOWN:
173 case WM_RBUTTONDOWN:
174 case WM_MBUTTONDOWN:
175 iF10Key = iMenuSysKey = 0;
176 break;
178 case WM_LBUTTONDBLCLK:
179 return NC_HandleNCLButtonDblClk( hwnd, HTCLIENT, lParam );
181 case WM_NCLBUTTONDBLCLK:
182 return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
184 case WM_RBUTTONUP:
186 POINT pt;
187 pt.x = (short)LOWORD(lParam);
188 pt.y = (short)HIWORD(lParam);
189 ClientToScreen(hwnd, &pt);
190 SendMessageW( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELPARAM(pt.x, pt.y) );
192 break;
194 case WM_NCRBUTTONUP:
196 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
197 * in Windows), but what _should_ we do? According to MSDN :
198 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
199 * message to the window". When is it appropriate?
201 break;
203 case WM_XBUTTONUP:
204 case WM_NCXBUTTONUP:
205 if (HIWORD(wParam) == XBUTTON1 || HIWORD(wParam) == XBUTTON2)
207 SendMessageW(hwnd, WM_APPCOMMAND, (WPARAM)hwnd,
208 MAKELPARAM(LOWORD(wParam), FAPPCOMMAND_MOUSE | HIWORD(wParam)));
210 break;
212 case WM_CONTEXTMENU:
213 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
214 SendMessageW( GetParent(hwnd), msg, (WPARAM)hwnd, lParam );
215 else
217 LONG hitcode;
218 POINT pt;
219 pt.x = (short)LOWORD(lParam);
220 pt.y = (short)HIWORD(lParam);
221 hitcode = NC_HandleNCHitTest(hwnd, pt);
223 /* Track system popup if click was in the caption area. */
224 if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
225 TrackPopupMenu( NtUserGetSystemMenu(hwnd, FALSE),
226 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
227 pt.x, pt.y, 0, hwnd, NULL );
229 break;
231 case WM_POPUPSYSTEMMENU:
232 /* This is an undocumented message used by the windows taskbar to
233 display the system menu of windows that belong to other processes. */
234 TrackPopupMenu( NtUserGetSystemMenu(hwnd, FALSE), TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
235 (short)LOWORD(lParam), (short)HIWORD(lParam), 0, hwnd, NULL );
236 return 0;
238 case WM_PRINT:
239 DEFWND_Print(hwnd, (HDC)wParam, lParam);
240 return 0;
242 case WM_CTLCOLORMSGBOX:
243 case WM_CTLCOLOREDIT:
244 case WM_CTLCOLORLISTBOX:
245 case WM_CTLCOLORBTN:
246 case WM_CTLCOLORDLG:
247 case WM_CTLCOLORSTATIC:
248 case WM_CTLCOLORSCROLLBAR:
249 return (LRESULT)DEFWND_ControlColor( (HDC)wParam, msg - WM_CTLCOLORMSGBOX );
251 case WM_CTLCOLOR:
252 return (LRESULT)DEFWND_ControlColor( (HDC)wParam, HIWORD(lParam) );
254 case WM_SETCURSOR:
255 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
257 /* with the exception of the border around a resizable wnd,
258 * give the parent first chance to set the cursor */
259 if ((LOWORD(lParam) < HTSIZEFIRST) || (LOWORD(lParam) > HTSIZELAST))
261 HWND parent = GetParent( hwnd );
262 if (parent != GetDesktopWindow() &&
263 SendMessageW( parent, WM_SETCURSOR, wParam, lParam )) return TRUE;
266 NC_HandleSetCursor( hwnd, wParam, lParam );
267 break;
269 case WM_SYSCOMMAND:
270 return NC_HandleSysCommand( hwnd, wParam, lParam );
272 case WM_KEYDOWN:
273 if(wParam == VK_F10) iF10Key = VK_F10;
274 break;
276 case WM_SYSKEYDOWN:
277 if( HIWORD(lParam) & KEYDATA_ALT )
279 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
280 if ( (wParam == VK_MENU || wParam == VK_LMENU
281 || wParam == VK_RMENU) && !iMenuSysKey )
282 iMenuSysKey = 1;
283 else
284 iMenuSysKey = 0;
286 iF10Key = 0;
288 if( wParam == VK_F4 ) /* try to close the window */
290 HWND top = NtUserGetAncestor( hwnd, GA_ROOT );
291 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
292 PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
295 else if( wParam == VK_F10 )
297 if (NtUserGetKeyState(VK_SHIFT) & 0x8000)
298 SendMessageW( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, -1 );
299 iF10Key = 1;
301 else if (wParam == VK_ESCAPE && (NtUserGetKeyState(VK_SHIFT) & 0x8000))
302 SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
303 break;
305 case WM_KEYUP:
306 case WM_SYSKEYUP:
307 /* Press and release F10 or ALT */
308 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
309 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
310 SendMessageW( NtUserGetAncestor( hwnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
311 iMenuSysKey = iF10Key = 0;
312 break;
314 case WM_SYSCHAR:
316 iMenuSysKey = 0;
317 if (wParam == '\r' && IsIconic(hwnd))
319 PostMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
320 break;
322 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
324 if (wParam == '\t' || wParam == '\x1b') break;
325 if (wParam == ' ' && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD))
326 SendMessageW( GetParent(hwnd), msg, wParam, lParam );
327 else
328 SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
330 else /* check for Ctrl-Esc */
331 if (wParam != '\x1b') MessageBeep(0);
332 break;
335 case WM_SHOWWINDOW:
337 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
338 WND *pWnd;
339 if (!lParam) return 0; /* sent from ShowWindow */
340 if ((style & WS_VISIBLE) && wParam) return 0;
341 if (!(style & WS_VISIBLE) && !wParam) return 0;
342 if (!GetWindow( hwnd, GW_OWNER )) return 0;
343 if (!(pWnd = WIN_GetPtr( hwnd ))) return 0;
344 if (pWnd == WND_OTHER_PROCESS) return 0;
345 if (wParam)
347 if (!(pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP))
349 WIN_ReleasePtr( pWnd );
350 return 0;
352 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
354 else pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
355 WIN_ReleasePtr( pWnd );
356 NtUserShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
357 break;
360 case WM_CANCELMODE:
361 iMenuSysKey = 0;
362 NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, FALSE );
363 break;
365 case WM_VKEYTOITEM:
366 case WM_CHARTOITEM:
367 return -1;
369 case WM_DROPOBJECT:
370 return DRAG_FILE;
372 case WM_QUERYDROPOBJECT:
373 return (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
375 case WM_QUERYDRAGICON:
377 UINT len;
379 HICON hIcon = (HICON)GetClassLongPtrW( hwnd, GCLP_HICON );
380 HINSTANCE instance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
381 if (hIcon) return (LRESULT)hIcon;
382 for(len=1; len<64; len++)
383 if((hIcon = LoadIconW(instance, MAKEINTRESOURCEW(len))))
384 return (LRESULT)hIcon;
385 return (LRESULT)LoadIconW(0, (LPWSTR)IDI_APPLICATION);
387 break;
389 case WM_ISACTIVEICON:
390 return (win_get_flags( hwnd ) & WIN_NCACTIVATED) != 0;
392 case WM_NOTIFYFORMAT:
393 if (IsWindowUnicode(hwnd)) return NFR_UNICODE;
394 else return NFR_ANSI;
396 case WM_QUERYOPEN:
397 case WM_QUERYENDSESSION:
398 return 1;
400 case WM_HELP:
401 SendMessageW( GetParent(hwnd), msg, wParam, lParam );
402 break;
404 case WM_STYLECHANGED:
405 if (wParam == GWL_STYLE && (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED))
407 STYLESTRUCT *style = (STYLESTRUCT *)lParam;
408 if ((style->styleOld ^ style->styleNew) & (WS_CAPTION|WS_THICKFRAME|WS_VSCROLL|WS_HSCROLL))
409 NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER |
410 SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE );
412 break;
414 case WM_APPCOMMAND:
416 HWND parent = GetParent(hwnd);
417 if(!parent)
418 HOOK_CallHooks(WH_SHELL, HSHELL_APPCOMMAND, wParam, lParam, TRUE);
419 else
420 SendMessageW( parent, msg, wParam, lParam );
421 break;
424 case WM_INPUTLANGCHANGEREQUEST:
425 NtUserActivateKeyboardLayout( (HKL)lParam, 0 );
426 break;
428 case WM_INPUTLANGCHANGE:
430 struct user_thread_info *info = get_user_thread_info();
431 int count = 0;
432 HWND *win_array = WIN_ListChildren( hwnd );
433 info->kbd_layout = (HKL)lParam;
435 if (!win_array)
436 break;
437 while (win_array[count])
438 SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
439 HeapFree(GetProcessHeap(),0,win_array);
440 break;
443 default:
444 return NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, FALSE );
448 return 0;
451 static LPARAM DEFWND_GetTextA( WND *wndPtr, LPSTR dest, WPARAM wParam )
453 LPARAM result = 0;
455 __TRY
457 if (wndPtr->text)
459 if (!WideCharToMultiByte( CP_ACP, 0, wndPtr->text, -1,
460 dest, wParam, NULL, NULL )) dest[wParam-1] = 0;
461 result = strlen( dest );
463 else dest[0] = '\0';
465 __EXCEPT_PAGE_FAULT
467 return 0;
469 __ENDTRY
470 return result;
473 /***********************************************************************
474 * DefWindowProcA (USER32.@)
476 * See DefWindowProcW.
478 LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
480 LRESULT result = 0;
481 HWND full_handle;
483 if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
485 if (!IsWindow( hwnd )) return 0;
486 ERR( "called for other process window %p\n", hwnd );
487 return 0;
489 hwnd = full_handle;
491 SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
493 switch(msg)
495 case WM_NCCREATE:
496 if (lParam)
498 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
500 result = NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, TRUE );
502 if(cs->style & (WS_HSCROLL | WS_VSCROLL))
504 SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
505 SetScrollInfo( hwnd, SB_HORZ, &si, FALSE );
506 SetScrollInfo( hwnd, SB_VERT, &si, FALSE );
509 break;
511 case WM_GETTEXTLENGTH:
513 WND *wndPtr = WIN_GetPtr( hwnd );
514 if (wndPtr && wndPtr->text)
515 result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, lstrlenW(wndPtr->text),
516 NULL, 0, NULL, NULL );
517 WIN_ReleasePtr( wndPtr );
519 break;
521 case WM_GETTEXT:
522 if (wParam)
524 LPSTR dest = (LPSTR)lParam;
525 WND *wndPtr = WIN_GetPtr( hwnd );
527 if (!wndPtr) break;
528 result = DEFWND_GetTextA( wndPtr, dest, wParam );
530 WIN_ReleasePtr( wndPtr );
532 break;
534 case WM_SETTEXT:
535 result = NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, TRUE );
536 break;
538 case WM_IME_CHAR:
539 if (HIBYTE(wParam)) PostMessageA( hwnd, WM_CHAR, HIBYTE(wParam), lParam );
540 PostMessageA( hwnd, WM_CHAR, LOBYTE(wParam), lParam );
541 break;
543 case WM_IME_KEYDOWN:
544 result = PostMessageA( hwnd, WM_KEYDOWN, wParam, lParam );
545 break;
547 case WM_IME_KEYUP:
548 result = PostMessageA( hwnd, WM_KEYUP, wParam, lParam );
549 break;
551 case WM_IME_COMPOSITION:
552 if (lParam & GCS_RESULTSTR)
554 LONG size, i;
555 unsigned char lead = 0;
556 char *buf = NULL;
557 HIMC himc = ImmGetContext( hwnd );
559 if (himc)
561 if ((size = ImmGetCompositionStringA( himc, GCS_RESULTSTR, NULL, 0 )))
563 if (!(buf = HeapAlloc( GetProcessHeap(), 0, size ))) size = 0;
564 else size = ImmGetCompositionStringA( himc, GCS_RESULTSTR, buf, size );
566 ImmReleaseContext( hwnd, himc );
568 for (i = 0; i < size; i++)
570 unsigned char c = buf[i];
571 if (!lead)
573 if (IsDBCSLeadByte( c ))
574 lead = c;
575 else
576 SendMessageA( hwnd, WM_IME_CHAR, c, 1 );
578 else
580 SendMessageA( hwnd, WM_IME_CHAR, MAKEWORD(c, lead), 1 );
581 lead = 0;
584 HeapFree( GetProcessHeap(), 0, buf );
587 /* fall through */
588 case WM_IME_STARTCOMPOSITION:
589 case WM_IME_ENDCOMPOSITION:
590 case WM_IME_SELECT:
591 case WM_IME_NOTIFY:
592 case WM_IME_CONTROL:
594 HWND hwndIME = ImmGetDefaultIMEWnd( hwnd );
595 if (hwndIME)
596 result = SendMessageA( hwndIME, msg, wParam, lParam );
598 break;
599 case WM_IME_SETCONTEXT:
601 HWND hwndIME = ImmGetDefaultIMEWnd( hwnd );
602 if (hwndIME) result = ImmIsUIMessageA( hwndIME, msg, wParam, lParam );
604 break;
606 case WM_SYSCHAR:
608 CHAR ch = LOWORD(wParam);
609 WCHAR wch;
610 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
611 wParam = MAKEWPARAM( wch, HIWORD(wParam) );
613 /* fall through */
614 default:
615 result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
616 break;
619 SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
620 return result;
624 static LPARAM DEFWND_GetTextW( WND *wndPtr, LPWSTR dest, WPARAM wParam )
626 LPARAM result = 0;
628 __TRY
630 if (wndPtr->text)
632 lstrcpynW( dest, wndPtr->text, wParam );
633 result = lstrlenW( dest );
635 else dest[0] = '\0';
637 __EXCEPT_PAGE_FAULT
639 return 0;
641 __ENDTRY
643 return result;
646 /***********************************************************************
647 * DefWindowProcW (USER32.@) Calls default window message handler
649 * Calls default window procedure for messages not processed
650 * by application.
652 * RETURNS
653 * Return value is dependent upon the message.
655 LRESULT WINAPI DefWindowProcW(
656 HWND hwnd, /* [in] window procedure receiving message */
657 UINT msg, /* [in] message identifier */
658 WPARAM wParam, /* [in] first message parameter */
659 LPARAM lParam ) /* [in] second message parameter */
661 LRESULT result = 0;
662 HWND full_handle;
664 if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
666 if (!IsWindow( hwnd )) return 0;
667 ERR( "called for other process window %p\n", hwnd );
668 return 0;
670 hwnd = full_handle;
671 SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
673 switch(msg)
675 case WM_NCCREATE:
676 if (lParam)
678 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
680 result = NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, FALSE );
682 if(cs->style & (WS_HSCROLL | WS_VSCROLL))
684 SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
685 SetScrollInfo( hwnd, SB_HORZ, &si, FALSE );
686 SetScrollInfo( hwnd, SB_VERT, &si, FALSE );
689 break;
691 case WM_GETTEXTLENGTH:
693 WND *wndPtr = WIN_GetPtr( hwnd );
694 if (wndPtr && wndPtr->text) result = (LRESULT)lstrlenW(wndPtr->text);
695 WIN_ReleasePtr( wndPtr );
697 break;
699 case WM_GETTEXT:
700 if (wParam)
702 LPWSTR dest = (LPWSTR)lParam;
703 WND *wndPtr = WIN_GetPtr( hwnd );
705 if (!wndPtr) break;
706 result = DEFWND_GetTextW( wndPtr, dest, wParam );
707 WIN_ReleasePtr( wndPtr );
709 break;
711 case WM_IME_CHAR:
712 PostMessageW( hwnd, WM_CHAR, wParam, lParam );
713 break;
715 case WM_IME_KEYDOWN:
716 result = PostMessageW( hwnd, WM_KEYDOWN, wParam, lParam );
717 break;
719 case WM_IME_KEYUP:
720 result = PostMessageW( hwnd, WM_KEYUP, wParam, lParam );
721 break;
723 case WM_IME_SETCONTEXT:
725 HWND hwndIME = ImmGetDefaultIMEWnd( hwnd );
726 if (hwndIME) result = ImmIsUIMessageW( hwndIME, msg, wParam, lParam );
728 break;
730 case WM_IME_COMPOSITION:
731 if (lParam & GCS_RESULTSTR)
733 LONG size, i;
734 WCHAR *buf = NULL;
735 HIMC himc = ImmGetContext( hwnd );
737 if (himc)
739 if ((size = ImmGetCompositionStringW( himc, GCS_RESULTSTR, NULL, 0 )))
741 if (!(buf = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) size = 0;
742 else size = ImmGetCompositionStringW( himc, GCS_RESULTSTR, buf, size * sizeof(WCHAR) );
744 ImmReleaseContext( hwnd, himc );
746 for (i = 0; i < size / sizeof(WCHAR); i++)
747 SendMessageW( hwnd, WM_IME_CHAR, buf[i], 1 );
748 HeapFree( GetProcessHeap(), 0, buf );
751 /* fall through */
752 case WM_IME_STARTCOMPOSITION:
753 case WM_IME_ENDCOMPOSITION:
754 case WM_IME_SELECT:
755 case WM_IME_NOTIFY:
756 case WM_IME_CONTROL:
758 HWND hwndIME = ImmGetDefaultIMEWnd( hwnd );
759 if (hwndIME)
760 result = SendMessageW( hwndIME, msg, wParam, lParam );
762 break;
764 default:
765 result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
766 break;
768 SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
769 return result;