⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comboex.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
static LRESULT COMBOEX_NotifyFormat (COMBOEX_INFO *infoPtr, LPARAM lParam)
{
    if (lParam == NF_REQUERY) {
	INT i = SendMessageW(infoPtr->hwndNotify,
			 WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
	infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0;
    }
    return infoPtr->NtfUnicode ? NFR_UNICODE : NFR_ANSI;
}


static LRESULT COMBOEX_Size (COMBOEX_INFO *infoPtr, INT width, INT height)
{
    TRACE("(width=%d, height=%d)\n", width, height);

    MoveWindow (infoPtr->hwndCombo, 0, 0, width, height, TRUE);

    COMBOEX_AdjustEditPos (infoPtr);

    return 0;
}


static LRESULT COMBOEX_WindowPosChanging (COMBOEX_INFO *infoPtr, WINDOWPOS *wp)
{
    RECT cbx_wrect, cbx_crect, cb_wrect;
    INT width, height;

    GetWindowRect (infoPtr->hwndSelf, &cbx_wrect);
    GetClientRect (infoPtr->hwndSelf, &cbx_crect);
    GetWindowRect (infoPtr->hwndCombo, &cb_wrect);

    /* width is winpos value + border width of comboex */
    width = wp->cx
	    + (cbx_wrect.right-cbx_wrect.left)
            - (cbx_crect.right-cbx_crect.left);

    TRACE("winpos=(%d,%d %dx%d) flags=0x%08x\n",
	  wp->x, wp->y, wp->cx, wp->cy, wp->flags);
    TRACE("EX window=(%d,%d)-(%d,%d), client=(%d,%d)-(%d,%d)\n",
	  cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom,
	  cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom);
    TRACE("CB window=(%d,%d)-(%d,%d), EX setting=(0,0)-(%d,%d)\n",
	  cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom,
	  width, cb_wrect.bottom-cb_wrect.top);

    if (width) SetWindowPos (infoPtr->hwndCombo, HWND_TOP, 0, 0,
			     width,
			     cb_wrect.bottom-cb_wrect.top,
			     SWP_NOACTIVATE);

    GetWindowRect (infoPtr->hwndCombo, &cb_wrect);

    /* height is combo window height plus border width of comboex */
    height =   (cb_wrect.bottom-cb_wrect.top)
	     + (cbx_wrect.bottom-cbx_wrect.top)
             - (cbx_crect.bottom-cbx_crect.top);
    if (wp->cy < height) wp->cy = height;
    if (infoPtr->hwndEdit) {
	COMBOEX_AdjustEditPos (infoPtr);
	InvalidateRect (infoPtr->hwndCombo, 0, TRUE);
    }

    return 0;
}

static LRESULT WINAPI
COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndComboex = (HWND)GetPropW(hwnd, COMBOEX_SUBCLASS_PROP);
    COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwndComboex);
    NMCBEENDEDITW cbeend;
    WCHAR edit_text[260];
    COLORREF obkc;
    HDC hDC;
    RECT rect;
    LRESULT lret;

    TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx, info_ptr=%p\n",
	  hwnd, uMsg, wParam, lParam, infoPtr);

    if (!infoPtr) return 0;

    switch (uMsg)
    {

	case WM_CHAR:
	    /* handle (ignore) the return character */
	    if (wParam == VK_RETURN) return 0;
	    /* all other characters pass into the real Edit */
	    return CallWindowProcW (infoPtr->prevEditWndProc,
				   hwnd, uMsg, wParam, lParam);

	case WM_ERASEBKGND:
	    /*
	     * The following was determined by traces of the native
	     */
            hDC = (HDC) wParam;
	    obkc = SetBkColor (hDC, GetSysColor (COLOR_WINDOW));
            GetClientRect (hwnd, &rect);
            TRACE("erasing (%d,%d)-(%d,%d)\n",
		  rect.left, rect.top, rect.right, rect.bottom);
	    ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
            SetBkColor (hDC, obkc);
	    return CallWindowProcW (infoPtr->prevEditWndProc,
				   hwnd, uMsg, wParam, lParam);

	case WM_KEYDOWN: {
	    INT oldItem, selected, step = 1;
	    CBE_ITEMDATA *item;

	    switch ((INT)wParam)
	    {
	    case VK_ESCAPE:
		/* native version seems to do following for COMBOEX */
		/*
		 *   GetWindowTextW(Edit,&?, 0x104)             x
		 *   CB_GETCURSEL to Combo rets -1              x
		 *   WM_NOTIFY to COMBOEX parent (rebar)        x
		 *     (CBEN_ENDEDIT{A|W}
		 *      fChanged = FALSE                        x
		 *      inewSelection = -1                      x
		 *      txt="www.hoho"                          x
		 *      iWhy = 3                                x
		 *   CB_GETCURSEL to Combo rets -1              x
		 *   InvalidateRect(Combo, 0)                   x
		 *   WM_SETTEXT to Edit                         x
		 *   EM_SETSEL to Edit (0,0)                    x
		 *   EM_SETSEL to Edit (0,-1)                   x
		 *   RedrawWindow(Combo, 0, 0, 5)               x
		 */
		TRACE("special code for VK_ESCAPE\n");

		GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);

		infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
		cbeend.fChanged = FALSE;
		cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
						     CB_GETCURSEL, 0, 0);
		cbeend.iWhy = CBENF_ESCAPE;

		if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text)) return 0;
		oldItem = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0);
		InvalidateRect (infoPtr->hwndCombo, 0, 0);
		if (!(item = COMBOEX_FindItem(infoPtr, oldItem))) {
		    ERR("item %d not found. Problem!\n", oldItem);
		    break;
		}
		infoPtr->selected = oldItem;
		COMBOEX_SetEditText (infoPtr, item);
		RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE |
			      RDW_INVALIDATE);
		break;

	    case VK_RETURN:
		/* native version seems to do following for COMBOEX */
		/*
		 *   GetWindowTextW(Edit,&?, 0x104)             x
		 *   CB_GETCURSEL to Combo  rets -1             x
		 *   CB_GETCOUNT to Combo  rets 0
		 *   if >0 loop
		 *       CB_GETITEMDATA to match
		 * *** above 3 lines simulated by FindItem      x
		 *   WM_NOTIFY to COMBOEX parent (rebar)        x
		 *     (CBEN_ENDEDIT{A|W}                       x
		 *        fChanged = TRUE (-1)                  x
		 *        iNewSelection = -1 or selected        x
		 *        txt=                                  x
		 *        iWhy = 2 (CBENF_RETURN)               x
		 *   CB_GETCURSEL to Combo  rets -1             x
		 *   if -1 send CB_SETCURSEL to Combo -1        x
		 *   InvalidateRect(Combo, 0, 0)                x
		 *   SetFocus(Edit)                             x
		 *   CallWindowProc(406615a8, Edit, 0x100, 0xd, 0x1c0001)
		 */

		TRACE("special code for VK_RETURN\n");

		GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);

		infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
		selected = SendMessageW (infoPtr->hwndCombo,
					 CB_GETCURSEL, 0, 0);

		if (selected != -1) {
                    cmp_func_t cmptext = get_cmp_func(infoPtr);
		    item = COMBOEX_FindItem (infoPtr, selected);
		    TRACE("handling VK_RETURN, selected = %d, selected_text=%s\n",
			  selected, debugstr_txt(item->pszText));
		    TRACE("handling VK_RETURN, edittext=%s\n",
			  debugstr_w(edit_text));
		    if (cmptext (COMBOEX_GetText(infoPtr, item), edit_text)) {
			/* strings not equal -- indicate edit has changed */
			selected = -1;
		    }
		}

		cbeend.iNewSelection = selected;
		cbeend.fChanged = TRUE;
		cbeend.iWhy = CBENF_RETURN;
		if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text)) {
		    /* abort the change, restore previous */
		    TRACE("Notify requested abort of change\n");
		    COMBOEX_SetEditText (infoPtr, infoPtr->edit);
		    RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE |
				  RDW_INVALIDATE);
		    return 0;
		}
		oldItem = SendMessageW (infoPtr->hwndCombo,CB_GETCURSEL, 0, 0);
		if (oldItem != -1) {
		    /* if something is selected, then deselect it */
		    SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL,
				  (WPARAM)-1, 0);
		}
		InvalidateRect (infoPtr->hwndCombo, 0, 0);
		SetFocus(infoPtr->hwndEdit);
		break;

	    case VK_UP:
		step = -1;
	    case VK_DOWN:
		/* by default, step is 1 */
		oldItem = SendMessageW (infoPtr->hwndSelf, CB_GETCURSEL, 0, 0);
		if (oldItem >= 0 && oldItem + step >= 0)
		    SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, oldItem + step, 0);
	    	return 0;
	    default:
		return CallWindowProcW (infoPtr->prevEditWndProc,
				       hwnd, uMsg, wParam, lParam);
	    }
	    return 0;
            }

	case WM_SETFOCUS:
	    /* remember the focus to set state of icon */
	    lret = CallWindowProcW (infoPtr->prevEditWndProc,
				   hwnd, uMsg, wParam, lParam);
	    infoPtr->flags |= WCBE_EDITFOCUSED;
	    return lret;

	case WM_KILLFOCUS:
	    /*
	     * do NOTIFY CBEN_ENDEDIT with CBENF_KILLFOCUS
	     */
	    infoPtr->flags &= ~WCBE_EDITFOCUSED;
	    if (infoPtr->flags & WCBE_ACTEDIT) {
		infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);

		GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);
		cbeend.fChanged = FALSE;
		cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
						     CB_GETCURSEL, 0, 0);
		cbeend.iWhy = CBENF_KILLFOCUS;

		COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text);
	    }
	    /* fall through */

	default:
	    return CallWindowProcW (infoPtr->prevEditWndProc,
				   hwnd, uMsg, wParam, lParam);
    }
}


static LRESULT WINAPI
COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndComboex = (HWND)GetPropW(hwnd, COMBOEX_SUBCLASS_PROP);
    COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwndComboex);
    NMCBEENDEDITW cbeend;
    NMMOUSE nmmse;
    COLORREF obkc;
    HDC hDC;
    HWND focusedhwnd;
    RECT rect;
    POINT pt;
    WCHAR edit_text[260];

    TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx, info_ptr=%p\n",
	  hwnd, uMsg, wParam, lParam, infoPtr);

    if (!infoPtr) return 0;

    switch (uMsg)
    {

    case WM_DRAWITEM:
	    /*
	     * The only way this message should come is from the
	     * child Listbox issuing the message. Flag this so
	     * that ComboEx knows this is listbox.
	     */
	    ((DRAWITEMSTRUCT *)lParam)->itemState |= ODS_COMBOEXLBOX;
	    return CallWindowProcW (infoPtr->prevComboWndProc,
				   hwnd, uMsg, wParam, lParam);

    case WM_ERASEBKGND:
	    /*
	     * The following was determined by traces of the native
	     */
            hDC = (HDC) wParam;
	    obkc = SetBkColor (hDC, GetSysColor (COLOR_WINDOW));
            GetClientRect (hwnd, &rect);
            TRACE("erasing (%d,%d)-(%d,%d)\n",
		  rect.left, rect.top, rect.right, rect.bottom);
	    ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
            SetBkColor (hDC, obkc);
	    return CallWindowProcW (infoPtr->prevComboWndProc,
				   hwnd, uMsg, wParam, lParam);

    case WM_SETCURSOR:
	    /*
	     *  WM_NOTIFY to comboex parent (rebar)
	     *   with NM_SETCURSOR with extra words of 0,0,0,0,0x02010001
	     *  CallWindowProc (previous)
	     */
	    nmmse.dwItemSpec = 0;
	    nmmse.dwItemData = 0;
	    nmmse.pt.x = 0;
	    nmmse.pt.y = 0;
	    nmmse.dwHitInfo = lParam;
	    COMBOEX_Notify (infoPtr, NM_SETCURSOR, (NMHDR *)&nmmse);
	    return CallWindowProcW (infoPtr->prevComboWndProc,
				   hwnd, uMsg, wParam, lParam);

    case WM_LBUTTONDOWN:
	    GetClientRect (hwnd, &rect);
	    rect.bottom = rect.top + SendMessageW(infoPtr->hwndSelf,
			                          CB_GETITEMHEIGHT, -1, 0);
	    rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);
	    pt.x = (short)LOWORD(lParam);
	    pt.y = (short)HIWORD(lParam);
	    if (PtInRect(&rect, pt))
		return CallWindowProcW (infoPtr->prevComboWndProc,
				        hwnd, uMsg, wParam, lParam);
	    infoPtr->flags |= WCBE_MOUSECAPTURED;
	    SetCapture(hwnd);
	    break;

    case WM_LBUTTONUP:
	    if (!(infoPtr->flags & WCBE_MOUSECAPTURED))
		return CallWindowProcW (infoPtr->prevComboWndProc,
				        hwnd, uMsg, wParam, lParam);
	    ReleaseCapture();
	    infoPtr->flags &= ~WCBE_MOUSECAPTURED;
	    if (infoPtr->flags & WCBE_MOUSEDRAGGED) {
		infoPtr->flags &= ~WCBE_MOUSEDRAGGED;
	    } else {
		SendMessageW(hwnd, CB_SHOWDROPDOWN, TRUE, 0);
	    }
	    break;

    case WM_MOUSEMOVE:
	    if ( (infoPtr->flags & WCBE_MOUSECAPTURED) &&
		!(infoPtr->flags & WCBE_MOUSEDRAGGED)) {
		GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);
		COMBOEX_NotifyDragBegin(infoPtr, edit_text);
		infoPtr->flags |= WCBE_MOUSEDRAGGED;
	    }
	    return CallWindowProcW (infoPtr->prevComboWndProc,
			            hwnd, uMsg, wParam, lParam);

    case WM_COMMAND:
	    switch (HIWORD(wParam)) {

	    case EN_UPDATE:
		/* traces show that COMBOEX does not issue CBN_EDITUPDATE
		 * on the EN_UPDATE
		 */
		return 0;

	    case EN_KILLFOCUS:
		/*
		 * Native does:
		 *
		 *  GetFocus() retns AA
		 *  GetWindowTextW(Edit)
		 *  CB_GETCURSEL(Combo) (got -1)
		 *  WM_NOTIFY(CBEN_ENDEDITA) with CBENF_KILLFOCUS
		 *  CB_GETCURSEL(Combo) (got -1)
		 *  InvalidateRect(Combo, 0, 0)
		 *  WM_KILLFOCUS(Combo, AA)
		 *  return 0;
		 */
		focusedhwnd = GetFocus();
		if (infoPtr->flags & WCBE_ACTEDIT) {
		    GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);
		    cbeend.fChanged = (infoPtr->flags & WCBE_EDITCHG);
		    cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
							 CB_GETCURSEL, 0, 0);
		    cbeend.iWhy = CBENF_KILLFOCUS;

		    infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
		    if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text)) return 0;
		}
		/* possible CB_GETCURSEL */
		InvalidateRect (infoPtr->hwndCombo, 0, 0);
		if (focusedhwnd)
		    SendMessageW (infoPtr->hwndCombo, WM_KILLFOCUS,
				  (WPARAM)focusedhwnd, 0);
		return 0;

	    case EN_SETFOCUS: {
		/*
		 * For EN_SETFOCUS this issues the same calls 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -