0

Windows、C/C++ では、システムに複数のモニターがある場合、WM_WINDOWPOSCHANGING メッセージで「最大化イベント」を検出するにはどうすればよいですか? つまり、どのディスプレイでもウィンドウが最大化されたときですか?

(他のオペレーティング システムのコードも大歓迎です!)

4

2 に答える 2

1

まず、 EnumDisplayDevicesEnumDisplaySettingsExを使用してすべてのディスプレイを検出する必要があります。

// C/C++ solution for enumerating display settings.

// Struct for display properties
struct DisplayProps
{
    int x, y;   // only display position is needed..
};

DISPLAY_DEVICE disp;
DISPLAY_DEVICE adapter;
DEVMODE mode;
DisplayProps the_displays[32];  // Array to store the results.
int i = 0, j = 0, display_count = 0;

// Initialize win32 structs.
memset(&disp, 0, sizeof(DISPLAY_DEVICE));
disp.cb = sizeof(DISPLAY_DEVICE);
memset(&args.adapter, 0, sizeof(DISPLAY_DEVICE));
adapter.cb = sizeof(DISPLAY_DEVICE);
memset(&mode, 0, sizeof(DEVMODE));
mode.dmSize = sizeof(DEVMODE);

memset(the_displays, 0, sizeof(the_displays));

// adapter loop:
while(EnumDisplayDevices(NULL, i, &adapter, 0))
{   // multiple displays on single adapter loop:
    j = 0;
    while(EnumDisplayDevices((TCHAR*)&adapter.DeviceName, j, &disp, 0))
    {   
        // The device must be active, attached to desktop and not a mirroring device.
        if((disp.StateFlags & DISPLAY_DEVICE_ACTIVE)
            && (disp.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
            && !(disp.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
        {
            // read display settings.
            if(EnumDisplaySettingsEx((TCHAR*)&adapter.DeviceName, ENUM_CURRENT_SETTINGS, &mode, 0))
            {
                the_displays[display_count].x = mode.dmPosition.x;
                the_displays[display_count].y = mode.dmPosition.y;
                ++display_count;
            }

        }
        // Reset
        memset(&args.disp, 0, sizeof(DISPLAY_DEVICE));
        disp.cb = sizeof(DISPLAY_DEVICE);
        ++j;
    }
    // Reset
    memset(&args.adapter, 0, sizeof(DISPLAY_DEVICE));
    adapter.cb = sizeof(DISPLAY_DEVICE);
    ++i;
}

次に、ウィンドウ プロシージャの WM_WINDOWPOSCHANGING メッセージで、実際にイベントを検出する必要があります。これには、おそらく文書化されていない値 SWP_STATECHANGED (0x8000) とAdjustWindowRectExの使用が必要です。

WINDOWPOS * wp = (WINDOWPOS*)lParam;
if( (wp->flags & (SWP_STATECHANGED | SWP_FRAMECHANGED)) != 0)
{
    // Figuring next part was a bit of luck involved: I noticed that AdjustWindowRectEx rect.left
    // matches window position (x and y) on default display when window is maximized
    RECT styleadj = {0, 0, 0, 0};
    // Can't cache/save this because user can change the theme.
    AdjustWindowRectEx(&styleadj,
    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, /* your window dwStyle */
    false, /* not using menu? */
    WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); /* your window dwExStyle */ 

    for(int i = 0; i < the_display_count; ++i)
    {
        if((wp->x == the_displays[i].x + styleadj.left) && (wp->y == the_displays[i].y + styleadj.left))
        {
            // Event is detected, do what ever you want!
            MessageBox(NULL, "A Maximize event Detected.", "Event Detected!", MB_OK);
        }
    }
}

このコードは複数のディスプレイ (私は 2 つ持っています) で動作し、Windows 7 の Aero Glass テーマ、Aero Basic テーマ、および古い Win 2000 テーマで動作することを確認していますWinXp と 8 はテストされていません。実際、 AdjustWindowRectExは、異なるテーマで異なる値を返します。

于 2013-07-16T05:03:17.033 に答える