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

📄 fakemenu.c

📁 C语言编程的不错工具
💻 C
📖 第 1 页 / 共 2 页
字号:
     */

    /*
     *  If too high, then slide down.
     */
    if (ppt->y < minf.rcMonitor.top) {
        ppt->y = minf.rcMonitor.top;
    }

    /*
     *  If too far left, then slide right.
     */
    if (ppt->x < minf.rcMonitor.left) {
        ppt->x = minf.rcMonitor.left;
    }

    /*
     *  If too low, then slide up.
     */
    if (ppt->y > minf.rcMonitor.bottom - cy) {
        ppt->y = minf.rcMonitor.bottom - cy;
    }

    /*
     *  If too far right, then flip left.
     */
    if (ppt->x > minf.rcMonitor.right - cx) {
        ppt->x = ppt->x - cx;
    }
}

/*****************************************************************************
 *
 *  ColorPick_Popup
 *
 *      Display a fake menu to allow the user to select the color.
 *
 *      Return the color index the user selected, or -1 if no color
 *      was selected.
 *
 *****************************************************************************/

int
ColorPick_Popup(HWND hwndOwner, int x, int y)
{
    COLORPICKSTATE cps;
    HWND hwndPopup, hwndActive;
    RECT rc;
    DWORD dwStyle, dwExStyle;
    MSG msg;
    POINT pt;
    int cx, cy;

    /*
     *  Early check:  We must be on same thread as the owner
     *  so we can see its mouse and keyboard messages when we
     *  set capture to it.
     */
    if (GetCurrentThreadId() != GetWindowThreadProcessId(hwndOwner, NULL)) {
        /*
         *  Error: Menu must be on same thread as parent window.
         */
        return -1;
    }

    cps.fDone = FALSE;          /* Not done yet */
    cps.iSel = -1;              /* No initial selection */
    cps.iResult = -1;           /* No result */
    cps.hwndOwner = hwndOwner;  /* Owner window */

    /*
     *  The style and extended style we want to use.
     */

    dwStyle = WS_POPUP | WS_BORDER;
    dwExStyle = WS_EX_TOOLWINDOW |      /* So it doesn't show up in taskbar */
                WS_EX_DLGMODALFRAME |   /* Get the edges right */
                WS_EX_WINDOWEDGE |
                WS_EX_TOPMOST;          /* So it isn't obscured */

    /*
     *  We want a client area of size (CXFAKEMENU, CCLRPREDEF * CYCOLOR),
     *  so use AdjustWindowRectEx to figure out what window rect will
     *  give us a client rect of that size.
     */
    rc.left = 0;
    rc.top = 0;
    rc.right = CXFAKEMENU;
    rc.bottom = CCLRPREDEF * CYCOLOR;
    AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);

    /*
     *  Now find a proper home for the window that won't go off
     *  the screen or straddle two monitors.
     */
    cx = rc.right - rc.left;
    cy = rc.bottom - rc.top;
    ColorPick_ChooseLocation(hwndOwner, x, y, cx, cy, &pt);

    hwndPopup = CreateWindowEx(
        dwExStyle,                      /* Extended style */
        "ColorPick",                    /* Class Name */
        "",                             /* Title */
        dwStyle,                        /* Style */
        pt.x, pt.y,                     /* Position */
        cx, cy,                         /* Size */
        hwndOwner,                      /* Parent */
        NULL,                           /* No menu */
        g_hinst,                        /* Instance */
        &cps);                          /* Starting parameters */

    /*
     *  Show the window but don't activate it!
     */
    ShowWindow(hwndPopup, SW_SHOWNOACTIVATE);

    /*
     *  We want to receive all mouse messages, but since
     *  only the active window can capture the mouse,
     *  we have to set the capture to our owner window,
     *  and then steal the mouse messages out from under him.
     */
    SetCapture(hwndOwner);

    /*
     *  Go into a message loop that filters all the messages
     *  it receives and routes the interesting ones to the
     *  color picker window.
     */
    while (GetMessage(&msg, NULL, 0, 0)) {

        /*
         *  Something may have happened that caused us to stop.
         *  If so, then stop.
         */
        if (cps.fDone) break;

        /*
         *  If our owner stopped being the active window
         *  (e.g., the user Alt+Tab'd to another window
         *  in the meantime), then stop.
         */
        hwndActive = GetActiveWindow();
        if (hwndActive != hwndOwner &&
            !IsChild(hwndActive, hwndOwner)) break;
        if (GetCapture() != hwndOwner) break;

        /*
         *  At this point, we get to snoop at all input messages
         *  before they get dispatched.  This allows us to
         *  route all input to our popup window even if really
         *  belongs to somebody else.
         *
         *  All mouse messages are remunged and directed at our
         *  popup menu.  If the mouse message arrives as client
         *  coordinates, then we have to convert it from the
         *  client coordinates of the original target to the
         *  client coordinates of the new target.
         */

        switch (msg.message) {

        /*
         *  These mouse messages arrive in client coordinates,
         *  so in addition to stealing the message, we also
         *  need to convert the coordinates.
         */
        case WM_MOUSEMOVE:
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_LBUTTONDBLCLK:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
        case WM_RBUTTONDBLCLK:
        case WM_MBUTTONDOWN:
        case WM_MBUTTONUP:
        case WM_MBUTTONDBLCLK:
            pt.x = (short)LOWORD(msg.lParam);
            pt.y = (short)HIWORD(msg.lParam);
            MapWindowPoints(msg.hwnd, hwndPopup, &pt, 1);
            msg.lParam = MAKELPARAM(pt.x, pt.y);
            msg.hwnd = hwndPopup;
            break;

        /*
         *  These mouse messages arrive in screen coordinates,
         *  so we just need to steal the message.
         */
        case WM_NCMOUSEMOVE:
        case WM_NCLBUTTONDOWN:
        case WM_NCLBUTTONUP:
        case WM_NCLBUTTONDBLCLK:
        case WM_NCRBUTTONDOWN:
        case WM_NCRBUTTONUP:
        case WM_NCRBUTTONDBLCLK:
        case WM_NCMBUTTONDOWN:
        case WM_NCMBUTTONUP:
        case WM_NCMBUTTONDBLCLK:
            msg.hwnd = hwndPopup;
            break;

        /*
         *  Steal all keyboard messages, too.
         */
        case WM_KEYDOWN:
        case WM_KEYUP:
        case WM_CHAR:
        case WM_DEADCHAR:
        case WM_SYSKEYDOWN:
        case WM_SYSKEYUP:
        case WM_SYSCHAR:
        case WM_SYSDEADCHAR:
            msg.hwnd = hwndPopup;
            break;

        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);

        /*
         *  Something may have happened that caused us to stop.
         *  If so, then stop.
         */
        if (cps.fDone) break;

        /*
         *  If our owner stopped being the active window
         *  (e.g., the user Alt+Tab'd to another window
         *  in the meantime), then stop.
         */
        hwndActive = GetActiveWindow();
        if (hwndActive != hwndOwner &&
            !IsChild(hwndActive, hwndOwner)) break;
        if (GetCapture() != hwndOwner) break;

    }

    /*
     *  Clean up the capture we created.
     */
    ReleaseCapture();

    DestroyWindow(hwndPopup);

    /*
     *  If we got a WM_QUIT message, then re-post it so the caller's
     *  message loop will see it.
     */
    if (msg.message == WM_QUIT) {
        PostQuitMessage((int)msg.wParam);
    }

    return cps.iResult;
}

/*****************************************************************************
 *
 *  FakeMenuDemo_OnEraseBkgnd
 *
 *      Erase the background in the selected color.
 *
 *****************************************************************************/

void
FakeMenuDemo_OnEraseBkgnd(HWND hwnd, HDC hdc)
{
    RECT rc;

    GetClientRect(hwnd, &rc);
    FillRect(hdc, &rc, g_hbrColor);
}

/*****************************************************************************
 *
 *  FakeMenuDemo_OnContextMenu
 *
 *      Display the color-picker pseudo-menu so the user can change
 *      the color.
 *
 *****************************************************************************/

void
FakeMenuDemo_OnContextMenu(HWND hwnd, int x, int y)
{
    int iColor;

    /*
     *  If the coordinates are (-1, -1), then the user typed Shift+F10,
     *  so we should pretend the user clicked at client (0, 0).
     */
    if (x == -1 && y == -1) {
        POINT pt;
        pt.x = 0;
        pt.y = 0;
        ClientToScreen(hwnd, &pt);
        x = pt.x;
        y = pt.y;
    }

    iColor = ColorPick_Popup(hwnd, x, y);

    /*
     *  If the user picked a color, then change to that color.
     */
    if (iColor >= 0) {
        DeleteObject(g_hbrColor);
        g_hbrColor = CreateSolidBrush(c_rgclrPredef[iColor]);
        InvalidateRect(hwnd, NULL, TRUE);
    }
}

/*****************************************************************************
 *
 *  FakeMenuDemo_WndProc
 *
 *      Window procedure for the fake menu demo.
 *
 *****************************************************************************/

LRESULT CALLBACK
FakeMenuDemo_WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uiMsg) {

    case WM_ERASEBKGND:
        FakeMenuDemo_OnEraseBkgnd(hwnd, (HDC)wParam);
        return TRUE;

    case WM_CONTEXTMENU:
        FakeMenuDemo_OnContextMenu(hwnd, (short)LOWORD(lParam),
                                         (short)HIWORD(lParam));
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}

/*****************************************************************************
 *
 *  InitClasses
 *
 *      Register our window classes.
 *
 *      "FakeMenuDemo" is the class for the main window.
 *
 *      "ColorPick" is the class for our color-picker pseudo-menu.
 *
 *****************************************************************************/

void
InitClasses(void)
{
    WNDCLASS wc;

    wc.style = 0;
    wc.lpfnWndProc = ColorPick_WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "ColorPick";

    RegisterClass(&wc);

    wc.style = 0;
    wc.lpfnWndProc = FakeMenuDemo_WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL;            /* Background color is dynamic */
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "FakeMenuDemo";

    RegisterClass(&wc);

}

/*****************************************************************************
 *
 *  WinMain
 *
 *      Program entry point.
 *
 *      Demonstrate pseudo-menus.
 *
 *****************************************************************************/

int WINAPI
WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine, int nCmdShow)
{
    MSG msg;
    HWND hwnd;

    g_hinst = hinst;

    InitClasses();

    /*
     *  Start out white.
     */
    g_hbrColor = CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF));

    hwnd = CreateWindow(
        "FakeMenuDemo",                 /* Class Name */
        "Fake Menu Demo - Right-click in window to change color", /* Title */
        WS_OVERLAPPEDWINDOW,            /* Style */
        CW_USEDEFAULT, CW_USEDEFAULT,   /* Position */
        CW_USEDEFAULT, CW_USEDEFAULT,   /* Size */
        NULL,                           /* Parent */
        NULL,                           /* No menu */
        hinst,                          /* Instance */
        0);                             /* No special parameters */

    ShowWindow(hwnd, nCmdShow);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

⌨️ 快捷键说明

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