internal override IntPtr DefWndProc(ref Message msg) {
switch ((Msg)msg.Msg) {
case Msg.WM_IME_COMPOSITION:
string s = Keyboard.GetCompositionString ();
foreach (char c in s)
SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
return IntPtr.Zero;
case Msg.WM_IME_CHAR:
// On Windows API it sends two WM_CHAR messages for each byte, but
// I wonder if it is worthy to emulate it (also no idea how to
// reconstruct those bytes into chars).
SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
return IntPtr.Zero;
case Msg.WM_PAINT: {
Hwnd hwnd;
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
if (hwnd != null) {
hwnd.expose_pending = false;
}
return IntPtr.Zero;
}
case Msg.WM_NCPAINT: {
Hwnd hwnd;
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
if (hwnd != null) {
hwnd.nc_expose_pending = false;
}
return IntPtr.Zero;
}
case Msg.WM_NCCALCSIZE: {
Hwnd hwnd;
if (msg.WParam == (IntPtr)1) {
hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
XplatUIWin32.NCCALCSIZE_PARAMS ncp;
ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
// Add all the stuff X is supposed to draw.
Control ctrl = Control.FromHandle (hwnd.Handle);
if (ctrl != null) {
Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
ncp.rgrc1.top += rect.top;
ncp.rgrc1.bottom -= rect.bottom;
ncp.rgrc1.left += rect.left;
ncp.rgrc1.right -= rect.right;
Marshal.StructureToPtr (ncp, msg.LParam, true);
}
}
return IntPtr.Zero;
}
case Msg.WM_CONTEXTMENU: {
Hwnd hwnd;
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
if ((hwnd != null) && (hwnd.parent != null)) {
SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
}
return IntPtr.Zero;
}
case Msg.WM_MOUSEWHEEL: {
Hwnd hwnd;
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
if ((hwnd != null) && (hwnd.parent != null)) {
SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
if (msg.Result == IntPtr.Zero) {
return IntPtr.Zero;
}
}
return IntPtr.Zero;
}
case Msg.WM_SETCURSOR: {
Hwnd hwnd;
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
if (hwnd == null)
break; // not sure how this happens, but it does
// Pass to parent window first
while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
hwnd = hwnd.parent;
msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
}
if (msg.Result == IntPtr.Zero) {
IntPtr handle;
switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
AudibleAlert(AlertType.Default);
}
handle = Cursors.Default.handle;
break;
case HitTest.HTHELP: handle = Cursors.Help.handle; break;
case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
#if SameAsDefault
case HitTest.HTGROWBOX:
case HitTest.HTSIZE:
case HitTest.HTZOOM:
case HitTest.HTVSCROLL:
case HitTest.HTSYSMENU:
case HitTest.HTREDUCE:
case HitTest.HTNOWHERE:
case HitTest.HTMAXBUTTON:
case HitTest.HTMINBUTTON:
case HitTest.HTMENU:
case HitTest.HSCROLL:
case HitTest.HTBOTTOM:
case HitTest.HTCAPTION:
case HitTest.HTCLIENT:
case HitTest.HTCLOSE:
#endif
default: handle = Cursors.Default.handle; break;
}
SetCursor(msg.HWnd, handle);
}
return (IntPtr)1;
}
}
return IntPtr.Zero;
}