static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { NMHDR *nmhdr = (NMHDR *) lParam; NMLVDISPINFOW *fill = (NMLVDISPINFO *) lParam; switch (uMsg) { case msgNOTIFY: switch (nmhdr->code) { case LVN_GETDISPINFO: tableGetCellText((void *) data, fill->item.iItem, fill->item.iSubItem, &(fill->item.pszText)); return 0; } return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); // see table.autoresize() in table_windows.go for the column autosize policy case WM_NOTIFY: // from the contained header control if (nmhdr->code == HDN_BEGINTRACK) tableStopColumnAutosize((void *) data); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, tableSubProc, id) == FALSE) xpanic("error removing Table subclass (which was for its own event handler)", GetLastError()); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); default: return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); } xmissedmsg("Button", "tableSubProc()", uMsg); return 0; // unreached }
static LRESULT CALLBACK checkboxSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { switch (uMsg) { case msgCOMMAND: if (HIWORD(wParam) == BN_CLICKED) { WPARAM check; // we didn't use BS_AUTOCHECKBOX (see controls_windows.go) so we have to manage the check state ourselves check = BST_CHECKED; if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED) check = BST_UNCHECKED; SendMessage(hwnd, BM_SETCHECK, check, 0); checkboxToggled((void *) data); return 0; } return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, checkboxSubProc, id) == FALSE) xpanic("error removing Checkbox subclass (which was for its own event handler)", GetLastError()); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); default: return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); } xmissedmsg("Checkbox", "checkboxSubProc()", uMsg); return 0; // unreached }
static LRESULT CALLBACK groupSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { LRESULT lResult; RECT r; if (sharedWndProc(hwnd, uMsg, wParam, lParam, &lResult)) return lResult; switch (uMsg) { case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: // don't use the WINDOWPOS rect here; the coordinates of the controls have to be in real client coordinates if (GetClientRect(hwnd, &r) == 0) xpanic("error getting client rect of Group for resizing its child Control", GetLastError()); groupResized((void *) data, r); // and chain up return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, groupSubProc, id) == FALSE) xpanic("error removing Group subclass (which was for its own event handler)", GetLastError()); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); default: return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); } xmissedmsg("Group", "groupSubProc()", uMsg); return 0; // unreached }
static LRESULT CALLBACK areaTextFieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { switch (uMsg) { case WM_KILLFOCUS: ShowWindow(hwnd, SW_HIDE); areaTextFieldDone((void *) data); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, areaTextFieldSubProc, id) == FALSE) xpanic("error removing Area TextField subclass (which was for handling WM_KILLFOCUS)", GetLastError()); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); default: return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); } xmissedmsg("Area TextField", "areaTextFieldSubProc()", uMsg); return 0; // unreached }
static LRESULT CALLBACK textfieldSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { switch (uMsg) { case msgCOMMAND: if (HIWORD(wParam) == EN_CHANGE) { textfieldChanged((void *) data); return 0; } return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, textfieldSubProc, id) == FALSE) xpanic("error removing TextField subclass (which was for its own event handler)", GetLastError()); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); default: return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); } xmissedmsg("TextField", "textfieldSubProc()", uMsg); return 0; // unreached }
static LRESULT CALLBACK buttonSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) { switch (uMsg) { case msgCOMMAND: if (HIWORD(wParam) == BN_CLICKED) { buttonClicked((void *) data); return 0; } return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); case WM_NCDESTROY: if ((*fv_RemoveWindowSubclass)(hwnd, buttonSubProc, id) == FALSE) xpanic("error removing Button subclass (which was for its own event handler)", GetLastError()); return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); default: return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); } xmissedmsg("Button", "buttonSubProc()", uMsg); return 0; // unreached }
static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { void *data; DWORD which; uintptr_t heldButtons = (uintptr_t) wParam; LRESULT lResult; data = getWindowData(hwnd, uMsg, wParam, lParam, &lResult); if (data == NULL) return lResult; switch (uMsg) { case WM_PAINT: paintArea(hwnd, data); return 0; case WM_ERASEBKGND: // don't draw a background; we'll do so when painting // this is to make things flicker-free; see http://msdn.microsoft.com/en-us/library/ms969905.aspx return 1; case WM_HSCROLL: scrollArea(hwnd, data, wParam, SB_HORZ); return 0; case WM_VSCROLL: scrollArea(hwnd, data, wParam, SB_VERT); return 0; case WM_SIZE: adjustAreaScrollbars(hwnd, data); return 0; case WM_ACTIVATE: // don't keep the double-click timer running if the user switched programs in between clicks areaResetClickCounter(data); return 0; case WM_MOUSEMOVE: areaMouseEvent(hwnd, data, 0, FALSE, heldButtons, lParam); return 0; case WM_LBUTTONDOWN: SetFocus(hwnd); areaMouseEvent(hwnd, data, 1, FALSE, heldButtons, lParam); return 0; case WM_LBUTTONUP: areaMouseEvent(hwnd, data, 1, TRUE, heldButtons, lParam); return 0; case WM_MBUTTONDOWN: SetFocus(hwnd); areaMouseEvent(hwnd, data, 2, FALSE, heldButtons, lParam); return 0; case WM_MBUTTONUP: areaMouseEvent(hwnd, data, 2, TRUE, heldButtons, lParam); return 0; case WM_RBUTTONDOWN: SetFocus(hwnd); areaMouseEvent(hwnd, data, 3, FALSE, heldButtons, lParam); return 0; case WM_RBUTTONUP: areaMouseEvent(hwnd, data, 3, TRUE, heldButtons, lParam); return 0; case WM_XBUTTONDOWN: SetFocus(hwnd); // values start at 1; we want them to start at 4 which = (DWORD) GET_XBUTTON_WPARAM(wParam) + 3; heldButtons = (uintptr_t) GET_KEYSTATE_WPARAM(wParam); areaMouseEvent(hwnd, data, which, FALSE, heldButtons, lParam); return TRUE; // XBUTTON messages are different! case WM_XBUTTONUP: which = (DWORD) GET_XBUTTON_WPARAM(wParam) + 3; heldButtons = (uintptr_t) GET_KEYSTATE_WPARAM(wParam); areaMouseEvent(hwnd, data, which, TRUE, heldButtons, lParam); return TRUE; case msgAreaKeyDown: return (LRESULT) areaKeyEvent(data, FALSE, wParam, lParam); case msgAreaKeyUp: return (LRESULT) areaKeyEvent(data, TRUE, wParam, lParam); case msgAreaSizeChanged: adjustAreaScrollbars(hwnd, data); repaintArea(hwnd, NULL); // this calls for an update return 0; case msgAreaGetScroll: getScrollPos(hwnd, (int *) wParam, (int *) lParam); return 0; case msgAreaRepaint: repaintArea(hwnd, (RECT *) lParam); return 0; case msgAreaRepaintAll: repaintArea(hwnd, NULL); return 0; default: return DefWindowProcW(hwnd, uMsg, wParam, lParam); } xmissedmsg("Area", "areaWndProc()", uMsg); return 0; // unreached }