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

📄 fakemenu.c

📁 C语言编程的不错工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *
 *  FakeMenu.c
 *
 *  Copyright (c) 1997 Microsoft Corporation.  All rights reserved.
 *
 *       This source code is only intended as a supplement to
 *       Microsoft Development Tools, q.v. for detailed
 *       information regarding the Microsoft samples programs.
 *
 *  Abstract:
 *
 *      Sample program to demonstrate how a program can display a
 *      popup window which does not deactivate its parent.  This
 *      can be used for things like a magnifying glass window or
 *      a pseudo-menu.
 *
 *****************************************************************************/

#include "FakeMenu.h"
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>

/*****************************************************************************
 *
 *      Overview
 *
 *      Normally, pop-up windows receive activation, resulting in the
 *      owner window being de-activated.  To prevent the owner from
 *      being de-activated, the pop-up window should not receive
 *      activation.
 *
 *      Since the pop-up window is not active, input messages are not
 *      delivered to the pop-up.  Instead, the input messages must be
 *      explicitly inspected by the message loop.
 *
 *      Our sample program illustrates how you can create a pop-up
 *      window that contains a selection of colors.
 *
 *      Right-click in the window to change its background color
 *      via the fake menu popup.  Observe
 *
 *      -   The caption of the main application window remains
 *          highlighted even though the fake-menu is "active".
 *
 *      -   The current fake-menu item highlight follows the mouse.
 *
 *      -   The keyboard arrows can be used to move the highlight,
 *          ESC cancels the fake-menu, Enter accepts the fake-menu.
 *
 *      -   The fake-menu appears on the correct monitor (for
 *          multiple-monitor systems).
 *
 *****************************************************************************/

HINSTANCE   g_hinst;                /* My hinstance */
HBRUSH      g_hbrColor;             /* The selected color */

/*****************************************************************************
 *
 *      This is the array of predefined colors we put into the color
 *      picker.
 *
 *****************************************************************************/

#define CCLRPREDEF  16              /* 16 predefined colors */

const COLORREF c_rgclrPredef[CCLRPREDEF] = {
    RGB(0x00, 0x00, 0x00),          /* 0 = black    */
    RGB(0x80, 0x00, 0x00),          /* 1 = maroon   */
    RGB(0x00, 0x80, 0x00),          /* 2 = green    */
    RGB(0x80, 0x80, 0x00),          /* 3 = olive    */
    RGB(0x00, 0x00, 0x80),          /* 4 = navy     */
    RGB(0x80, 0x00, 0x80),          /* 5 = purple   */
    RGB(0x00, 0x80, 0x80),          /* 6 = teal     */
    RGB(0x80, 0x80, 0x80),          /* 7 = gray     */
    RGB(0xC0, 0xC0, 0xC0),          /* 8 = silver   */
    RGB(0xFF, 0x00, 0x00),          /* 9 = red      */
    RGB(0x00, 0xFF, 0x00),          /* A = lime     */
    RGB(0xFF, 0xFF, 0x00),          /* B = yelow    */
    RGB(0x00, 0x00, 0xFF),          /* C = blue     */
    RGB(0xFF, 0x00, 0xFF),          /* D = fuchsia  */
    RGB(0x00, 0xFF, 0xFF),          /* E = cyan     */
    RGB(0xFF, 0xFF, 0xFF),          /* F = white    */
};

/*****************************************************************************
 *
 *  COLORPICKSTATE
 *
 *      Structure that records the state of a color-picker pop-up.
 *
 *      A pointer to this state information is kept in the GWLP_USERDATA
 *      window long.
 *
 *      The iSel field is the index of the selected color, or the
 *      special value -1 to mean that no item is highlighted.
 *
 *****************************************************************************/

typedef struct COLORPICKSTATE {

    BOOL fDone;             /* Set when we should get out */
    int iSel;               /* Which color is selected? */
    int iResult;            /* Which color should be returned? */
    HWND hwndOwner;         /* Our owner window */

} COLORPICKSTATE, *PCOLORPICKSTATE;

#define CYCOLOR         16      /* Height of a single color pick */
#define CXFAKEMENU      100     /* Width of our fake menu */

/*****************************************************************************
 *
 *  ColorPick_GetColorRect
 *
 *      Returns the rectangle that encloses the specified color.
 *
 *****************************************************************************/

void
ColorPick_GetColorRect(LPRECT prc, int iColor)
{
    /*
     *  Build the "menu" item rect.
     */
    prc->left = 0;
    prc->right = CXFAKEMENU;
    prc->top = iColor * CYCOLOR;
    prc->bottom = prc->top + CYCOLOR;

}

/*****************************************************************************
 *
 *  ColorPick_OnCreate
 *
 *      Stash away our state.
 *
 *****************************************************************************/

LRESULT
ColorPick_OnCreate(HWND hwnd, LPCREATESTRUCT pcs)
{
    SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)(pcs->lpCreateParams));

    return 0;
}

/*****************************************************************************
 *
 *  ColorPick_OnPaint
 *
 *      Draw the color bars, and put a border around the selected
 *      color.
 *
 *****************************************************************************/

void
ColorPick_OnPaint(PCOLORPICKSTATE pcps, HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc;

    hdc = BeginPaint(hwnd, &ps);
    if (hdc) {
        RECT rcClient;
        int iColor;

        GetClientRect(hwnd, &rcClient);

        /*
         *  For each of our predefined colors, draw it in a little
         *  rectangular region, leaving some border so the user can
         *  see if the item is highlighted or not.
         */
        for (iColor = 0; iColor < CCLRPREDEF; iColor++) {
            RECT rc;
            HBRUSH hbr;

            /*
             *  Build the "menu" item rect.
             */
            ColorPick_GetColorRect(&rc, iColor);

            /*
             *  If the item is highlighted, then draw a highlighted
             *  background.
             */
            if (iColor == pcps->iSel) {
                FillRect(hdc, &rc, GetSysColorBrush(COLOR_HIGHLIGHT));
            }

            /*
             *  Now shrink the rectangle by an edge and fill the
             *  rest with the color of the item itself.
             */
            InflateRect(&rc, -GetSystemMetrics(SM_CXEDGE),
                             -GetSystemMetrics(SM_CYEDGE));

            hbr = CreateSolidBrush(c_rgclrPredef[iColor]);
            FillRect(hdc, &rc, hbr);
            DeleteObject(hbr);
        }

        EndPaint(hwnd, &ps);
    }
}

/*****************************************************************************
 *
 *  ColorPick_ChangeSel
 *
 *      Change the selection to the specified item.
 *
 *****************************************************************************/

void
ColorPick_ChangeSel(PCOLORPICKSTATE pcps, HWND hwnd, int iSel)
{
    /*
     *  If the selection changed, then
     *  repaint the items that need repainting.
     */
    if (pcps->iSel != iSel) {
        RECT rc;

        if (pcps->iSel >= 0) {
            ColorPick_GetColorRect(&rc, pcps->iSel);
            InvalidateRect(hwnd, &rc, TRUE);
        }

        pcps->iSel = iSel;
        if (pcps->iSel >= 0) {
            ColorPick_GetColorRect(&rc, pcps->iSel);
            InvalidateRect(hwnd, &rc, TRUE);
        }

    }
}

/*****************************************************************************
 *
 *  ColorPick_OnMouseMove
 *
 *      Track the mouse to see if it is over any of our colors.
 *
 *****************************************************************************/

void
ColorPick_OnMouseMove(PCOLORPICKSTATE pcps, HWND hwnd, int x, int y)
{
    int iSel;

    if (x >= 0 && x < CXFAKEMENU &&
        y >= 0 && y < CCLRPREDEF * CYCOLOR) {
        iSel = y / CYCOLOR;
    } else {
        iSel = -1;
    }

    ColorPick_ChangeSel(pcps, hwnd, iSel);

}

/*****************************************************************************
 *
 *  ColorPick_OnLButtonUp
 *
 *      When the button comes up, we are done.
 *
 *****************************************************************************/

void
ColorPick_OnLButtonUp(PCOLORPICKSTATE pcps, HWND hwnd, int x, int y)
{
    /*
     *  First track to the final location, in case the user
     *  moves the mouse REALLY FAST and immediately lets go.
     */
    ColorPick_OnMouseMove(pcps, hwnd, x, y);

    /*
     *  Set the result to the current selection.
     */
    pcps->iResult = pcps->iSel;

    /*
     *  And tell the message loop that we're done.
     */
    pcps->fDone = TRUE;
}

/*****************************************************************************
 *
 *  ColorPick_OnKeyDown
 *
 *      If the ESC key is pressed, then abandon the fake menu.
 *
 *      If the Enter key is pressed, then accept the current selection.
 *
 *      If an arrow key is pressed, the move the selection.
 *
 *****************************************************************************/

void
ColorPick_OnKeyDown(PCOLORPICKSTATE pcps, HWND hwnd, WPARAM vk)
{
    switch (vk) {

    case VK_ESCAPE:
        pcps->fDone = TRUE;         /* Abandoned */
        break;

    case VK_RETURN:
        pcps->iResult = pcps->iSel; /* Accept current selection */
        pcps->fDone = TRUE;
        break;

    case VK_UP:
        if (pcps->iSel > 0) {
            ColorPick_ChangeSel(pcps, hwnd, pcps->iSel - 1);
        } else {
            ColorPick_ChangeSel(pcps, hwnd, CCLRPREDEF - 1);
        }
        break;

    case VK_DOWN:
        if (pcps->iSel + 1 < CCLRPREDEF) {
            ColorPick_ChangeSel(pcps, hwnd, pcps->iSel + 1);
        } else {
            ColorPick_ChangeSel(pcps, hwnd, 0);
        }
        break;


    }
}

/*****************************************************************************
 *
 *  ColorPick_WndProc
 *
 *      Window procedure for the color picker popup.
 *
 *****************************************************************************/

LRESULT CALLBACK
ColorPick_WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    PCOLORPICKSTATE pcps = (PCOLORPICKSTATE)GetWindowLongPtr(hwnd, GWLP_USERDATA);

    switch (uiMsg) {

    case WM_CREATE:
        return ColorPick_OnCreate(hwnd, (LPCREATESTRUCT)lParam);

    case WM_MOUSEMOVE:
        ColorPick_OnMouseMove(pcps, hwnd, (short)LOWORD(lParam),
                                          (short)HIWORD(lParam));
        break;

    case WM_LBUTTONUP:
        ColorPick_OnLButtonUp(pcps, hwnd, (short)LOWORD(lParam),
                                          (short)HIWORD(lParam));
        break;

    case WM_SYSKEYDOWN:
    case WM_KEYDOWN:
        ColorPick_OnKeyDown(pcps, hwnd, wParam);
        break;

    /*
     *  Do not activate when somebody clicks on me.
     */
    case WM_MOUSEACTIVATE:
        return MA_NOACTIVATE;

    case WM_PAINT:
        ColorPick_OnPaint(pcps, hwnd);
        return 0;

    }

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

/*****************************************************************************
 *
 *  ColorPick_ChooseLocation
 *
 *      Find a place to put the window so it won't go off the screen
 *      or straddle two monitors.
 *
 *      x, y = location of mouse click (preferred upper-left corner)
 *      cx, cy = size of window being created
 *
 *      We use the same logic that real menus use.
 *
 *      -   If (x, y) is too high or too far left, then slide onto screen.
 *      -   Use (x, y) if all fits on the monitor.
 *      -   If too low, then slide up.
 *      -   If too far right, then flip left.
 *
 *****************************************************************************/

void
ColorPick_ChooseLocation(HWND hwnd, int x, int y, int cx, int cy, LPPOINT ppt)
{
    HMONITOR hmon;
    MONITORINFO minf;

    /*
     *  First get the dimensions of the monitor that contains (x, y).
     */
    ppt->x = x;
    ppt->y = y;

    hmon = MonitorFromPoint(*ppt, MONITOR_DEFAULTTONULL);

    /*
     *  If (x, y) is not on any monitor, then use the monitor that
     *  the owner window is on.
     */
    if (hmon == NULL) {
        hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
    }

    minf.cbSize = sizeof(minf);
    GetMonitorInfo(hmon, &minf);

    /*
     *  Now slide things around until they fit.

⌨️ 快捷键说明

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