static Ihandle* winContainerWmCommandGetIhandle(Ihandle *ih, WPARAM wp, LPARAM lp) { /* WPARAM - if HIWORD is 0 if the message is from a menu. or HIWORD is 1 if the message is from an accelerator. or HIWORD is the notification code if the message is from a control. LOWORD is the identifier. LPARAM - the control sending the message or 0. */ Ihandle *child = NULL; if (HIWORD(wp)==0 && lp==0 && LOWORD(wp)>10) { Ihandle* dlg_menu = IupGetAttributeHandle(ih, "MENU"); if (dlg_menu) child = iupwinMenuGetItemHandle((HMENU)dlg_menu->handle, LOWORD(wp)); /* menu */ } else { if (lp==0) child = ih; /* native parent */ else { child = iupwinHandleGet((HWND)lp); /* control */ if (!child) child = iupwinHandleGet(GetParent((HWND)lp)); /* control */ } } return child; }
int iupdrvMenuPopup(Ihandle* ih, int x, int y) { HWND hWndActive = GetActiveWindow(); int tray_menu = 0; int menuId; if (!hWndActive) { /* search for a valid handle */ Ihandle* dlg = iupDlgListFirst(); do { if (dlg->handle) { hWndActive = dlg->handle; /* found a valid handle */ /* if not a "TRAY" dialog, keep searching, because TRAY is a special case */ if (iupAttribGetBoolean(dlg, "TRAY")) break; } dlg = iupDlgListNext(); } while (dlg); } /* Necessary to avoid tray dialogs to lock popup menus (they get sticky after the 1st time) */ if (hWndActive) { Ihandle* dlg = iupwinHandleGet(hWndActive); if (dlg && iupAttribGetBoolean(dlg, "TRAY")) { /* To display a context menu for a notification icon, the current window must be the foreground window. */ SetForegroundWindow(hWndActive); tray_menu = 1; } } /* stop processing here. messages will not go to the message loop */ menuId = TrackPopupMenu((HMENU)ih->handle, TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, x, y, 0, hWndActive, NULL); if (tray_menu) { /* You must force a task switch to the application that called TrackPopupMenu at some time in the near future. This is done by posting a benign message to the window. */ PostMessage(hWndActive, WM_NULL, 0, 0); } if (menuId) { Icallback cb; Ihandle* ih_item = iupwinMenuGetItemHandle((HMENU)ih->handle, menuId); if (!ih_item) return IUP_NOERROR; winItemCheckToggle(ih_item); cb = IupGetCallback(ih_item, "ACTION"); if (cb && cb(ih_item) == IUP_CLOSE) IupExitLoop(); } return IUP_NOERROR; }
void iupwinMenuDialogProc(Ihandle* ih_dialog, UINT msg, WPARAM wp, LPARAM lp) { /* called only from winDialogBaseProc */ switch (msg) { case WM_INITMENUPOPUP: { HMENU hMenu = (HMENU)wp; Ihandle *ih = iupwinMenuGetHandle(hMenu); if (ih) { Icallback cb = (Icallback)IupGetCallback(ih, "OPEN_CB"); if (!cb && ih->parent) cb = (Icallback)IupGetCallback(ih->parent, "OPEN_CB"); /* check also in the Submenu */ if (cb) cb(ih); } break; } case WM_UNINITMENUPOPUP: { HMENU hMenu = (HMENU)wp; Ihandle *ih = iupwinMenuGetHandle(hMenu); if (ih) { Icallback cb = (Icallback)IupGetCallback(ih, "MENUCLOSE_CB"); if (!cb && ih->parent) cb = (Icallback)IupGetCallback(ih->parent, "MENUCLOSE_CB"); /* check also in the Submenu */ if (cb) cb(ih); } break; } case WM_MENUSELECT: { HMENU hMenu = (HMENU)lp; Ihandle *ih; if (!lp) break; if ((HIWORD(wp) & MF_POPUP) || (HIWORD(wp) & MF_SYSMENU)) /* drop-down ih or submenu. */ { UINT menuindex = LOWORD(wp); HMENU hsubmenu = GetSubMenu(hMenu, menuindex); ih = iupwinMenuGetHandle(hsubmenu); /* returns the handle of a IupMenu */ if (ih) ih = ih->parent; /* gets the submenu */ } else /* ih item */ { UINT menuID = LOWORD(wp); ih = iupwinMenuGetItemHandle(hMenu, menuID); } if (ih) { Icallback cb = IupGetCallback(ih, "HIGHLIGHT_CB"); if (cb) cb(ih); } break; } case WM_MENUCOMMAND: { int menuId = GetMenuItemID((HMENU)lp, (int)wp); Icallback cb; Ihandle* ih; if (menuId >= IUP_MDI_FIRSTCHILD) break; ih = iupwinMenuGetItemHandle((HMENU)lp, menuId); if (!ih) break; winItemCheckToggle(ih); cb = IupGetCallback(ih, "ACTION"); if (cb && cb(ih) == IUP_CLOSE) IupExitLoop(); break; } case WM_ENTERMENULOOP: { /* Simulate WM_KILLFOCUS when the menu interaction is started */ Ihandle* lastfocus = (Ihandle*)iupAttribGet(ih_dialog, "_IUPWIN_LASTFOCUS"); if (lastfocus) iupCallKillFocusCb(lastfocus); break; } case WM_EXITMENULOOP: { /* Simulate WM_GETFOCUS when the menu interaction is stopped */ Ihandle* lastfocus = (Ihandle*)iupAttribGet(ih_dialog, "_IUPWIN_LASTFOCUS"); if (lastfocus) iupCallGetFocusCb(lastfocus); break; } } }
int iupwinBaseContainerMsgProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result) { /* All messages here are sent to the parent Window, but they are usefull for child controls. */ switch (msg) { case WM_COMMAND: { Ihandle* child = winContainerWmCommandGetIhandle(ih, wp, lp); if (child) { IFwmCommand cb = (IFwmCommand)IupGetCallback(child, "_IUPWIN_COMMAND_CB"); if (cb) cb(child, wp, lp); } break; } case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORSTATIC: { Ihandle* child = iupwinHandleGet((HWND)lp); if (child && winCheckParent(child, ih)) { IFctlColor cb = (IFctlColor)IupGetCallback(child, "_IUPWIN_CTLCOLOR_CB"); if (cb) return cb(child, (HDC)wp, result); } break; } case WM_DRAWITEM: /* for OWNERDRAW controls */ { Ihandle *child; DRAWITEMSTRUCT *drawitem = (LPDRAWITEMSTRUCT)lp; if (!drawitem) break; if (wp == 0) /* a menu */ child = iupwinMenuGetItemHandle((HMENU)drawitem->hwndItem, drawitem->itemID); else { child = iupwinHandleGet(drawitem->hwndItem); if (child && !winCheckParent(child, ih)) child = NULL; } if (child) { IFdrawItem cb = (IFdrawItem)IupGetCallback(child, "_IUPWIN_DRAWITEM_CB"); if (cb) { cb(child, (void*)drawitem); *result = TRUE; return 1; } } break; } case WM_HSCROLL: case WM_VSCROLL: { Ihandle *child = iupwinHandleGet((HWND)lp); if (child && winCheckParent(child, ih)) { IFni cb = (IFni)IupGetCallback(child, "_IUPWIN_CUSTOMSCROLL_CB"); if (cb) cb(child, LOWORD(wp)); } break; } case WM_NOTIFY: /* Currently, the following controls support custom draw functionality: Header, List-view, Rebar, Toolbar, ToolTip, Trackbar, Tree-view. And for Button if using Windows XP Style. */ { Ihandle *child; NMHDR* msg_info = (NMHDR*)lp; if (!msg_info) break; child = iupwinHandleGet(msg_info->hwndFrom); if (child && winCheckParent(child, ih)) { IFnotify cb = (IFnotify)IupGetCallback(child, "_IUPWIN_NOTIFY_CB"); if (cb) { int ret; if (cb(child, (void*)msg_info, &ret)) { *result = (LRESULT)ret; return 1; } } } break; } default: { /* sent to the list parent */ if (msg == WM_DRAGLISTMSG) { DRAGLISTINFO* lpDrag = (DRAGLISTINFO*) lp; Ihandle *child = iupwinHandleGet(lpDrag->hWnd); if (child && winCheckParent(child, ih)) { *result = iupwinListDND(child, lpDrag->uNotification, lpDrag->ptCursor); return 1; } } break; } } return iupwinBaseMsgProc(ih, msg, wp, lp, result); }
int iupwinBaseMsgProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result) { switch (msg) { case WM_INPUTLANGCHANGE: iupwinKeyInit(); break; case WM_GETDLGCODE: { *result = DLGC_WANTALLKEYS; return 1; } case WM_NOTIFY: /* usually sent only to parent, */ { /* but TIPs are configured to be handled here */ NMHDR* msg_info = (NMHDR*)lp; if (msg_info->code == TTN_GETDISPINFO) iupwinTipsGetDispInfo(lp); break; } case WM_DROPFILES: iupwinDropFiles((HDROP)wp, ih); break; case WM_LBUTTONDOWN: if(iupAttribGetBoolean(ih, "DRAGSOURCE")) { if (iupwinDragStart(ih)) { *result = 0; return 1; /* abort default processing */ } } break; case WM_HELP: { Ihandle* child; HELPINFO* help_info = (HELPINFO*)lp; if (help_info->iContextType == HELPINFO_MENUITEM) child = iupwinMenuGetItemHandle((HMENU)help_info->hItemHandle, (int)help_info->iCtrlId); else child = iupwinHandleGet((HWND)help_info->hItemHandle); if (child) { Icallback cb = (Icallback) IupGetCallback(child, "HELP_CB"); if (cb) { if (cb(child) == IUP_CLOSE) IupExitLoop(); *result = 0; return 1; /* abort default processing */ } } break; } case WM_MOUSELEAVE: { Icallback leave_cb = IupGetCallback(ih, "LEAVEWINDOW_CB"); if (leave_cb) leave_cb(ih); iupAttribSet(ih, "_IUPWIN_ENTERWIN", NULL); /* enable tracking again */ break; } case WM_MOUSEHOVER: { Icallback enter_cb = IupGetCallback(ih, "ENTERWINDOW_CB"); if (enter_cb) enter_cb(ih); break; } case WM_MOUSEMOVE: { /* set tracking only once, but only until track message is processed. */ if (!iupAttribGet(ih, "_IUPWIN_ENTERWIN")) { /* set tracking only if enter or leave callbacks are defined */ Icallback enter_cb = IupGetCallback(ih, "ENTERWINDOW_CB"); Icallback leave_cb = IupGetCallback(ih, "LEAVEWINDOW_CB"); if (enter_cb || leave_cb) { /* must be called so WM_MOUSEHOVER and WM_MOUSELEAVE will be called */ winTrackMouseHoverLeave(ih); iupAttribSet(ih, "_IUPWIN_ENTERWIN", "1"); } } break; } case WM_KEYDOWN: case WM_SYSKEYDOWN: if (!iupwinKeyEvent(ih, (int)wp, 1)) { *result = 0; return 1; /* abort default processing */ } break; case WM_SYSKEYUP: case WM_KEYUP: { int ret; if (wp == VK_SNAPSHOT) /* called only on key up */ { ret = iupwinKeyEvent(ih, (int)wp, 1); if (ret && iupObjectCheck(ih)) ret = iupwinKeyEvent(ih, (int)wp, 0); } else ret = iupwinKeyEvent(ih, (int)wp, 0); if (!ret) { *result = 0; return 1; /* abort default processing */ } break; } case WM_SETFOCUS: /* TODO: Not setting WS_TABSTOP still allows the control to receive the focus when clicked. But this code does make several controls with CANFOCUS=NO to stop working. So we use it inside some of the controls. */ /* if (!iupAttribGetBoolean(ih, "CANFOCUS")) { HWND previous = (HWND)wp; if (previous && previous != ih->handle) SetFocus(previous); break; } */ iupwinWmSetFocus(ih); break; case WM_KILLFOCUS: iupCallKillFocusCb(ih); break; case WM_SETCURSOR: { if (ih->handle == (HWND)wp && LOWORD(lp)==HTCLIENT) { HCURSOR hCur = (HCURSOR)iupAttribGet(ih, "_IUPWIN_HCURSOR"); if (hCur) { SetCursor(hCur); *result = 1; return 1; } else if (iupAttribGet(ih, "CURSOR")) { SetCursor(NULL); *result = 1; return 1; } } break; } case WM_TOUCH: /* TODO: - considering touch messages are greedy, one window got it all? - how this work? only for the dialog, or also for the children? - should a container forward to its children? */ if (LOWORD(wp)) iupwinTouchProcessInput(ih, (int)LOWORD(wp), (void*)lp); break; case WOM_CLOSE: case WOM_DONE: case WOM_OPEN: { IFni cb = (IFni)IupGetCallback(ih, "WOM_CB"); if (cb) { int v = -2; /* Error */ switch(msg) { case WOM_OPEN: v = 1; break; case WOM_DONE: v = 0; break; case WOM_CLOSE: v = -1; break; } cb(ih, v); } break; } } return 0; }