HOWTO: Override Full Drag

ID: Q121541

The information in this article applies to:

SUMMARY

Windows NT version 3.5 introduces full drag, which allows you to see the entire window moving or resizing instead of seeing just an outline of the window moving or resizing. The sample application below demonstrates how to enable full drag by running the Desktop Control Panel applet and selecting the Full Drag check box.

MORE INFORMATION

When you resize a window with full drag enabled, the application will receive numerous messages indicating that the window is resizing. (You can verify this with Spy.) If this has undesirable effects on your application, you will need to override the full drag feature in your application.

When the moving or resizing starts, the application receives this message:

   WM_ENTERSIZEMOVE (0231)

When the moving or resizing finishes, the application receives this message:

   WM_EXITSIZEMOVE (0232)

The above messages act as a notification that the window is entering and exiting a sizing or moving operation. If you want, you can use these notifications to set a flag to prevent the program from handling a WM_PAINT message during the move or size operation to override full drag.

Sample Code

   /***********************************************************************
    *
    · Fulldrag.c
     *
    · Copyright (c) 1997 Microsoft Corporation.
     *
    · Abstract:
     *
    · Sample program that demonstrates how a program can override
    · Full Drag.
     *

   ***********************************************************************/ 

    #define STRICT
    #include <windows.h>

   /***********************************************************************
     *
    · Globals
     *
    · g_fMoveSize
     *
    · Set while you are in a move/size loop. The WM_ENTERSIZEMOVE
    · and WM_EXITSIZEMOVE messages tell you when these things happen.
     *
    · g_fPaintDeferred
     *
    · Set if you deferred a paint that occurred while you were
    · busy doing a Move/Size. When the Move/Size completes
    · and you discover that a paint was deferred, you force
    · a full repaint to complete the deferred paint.
     *
     *
    · Note:
     *
    · In a real (that is, non-sample) program, these would not be global
    · variables. They would be per-window variables.
     *

   ***********************************************************************/ 

    BOOL g_fDragging;
    BOOL g_fPaintDeferred;

   /***********************************************************************
     *
    · Hilbert
     *
    · Draws a segment of the hilbert curve.
     *
    · The math is not important. What is important is that drawing
    · a hilbert curve takes a long time.
     *

   ***********************************************************************/ 

    #define MAXDEPTH 8      /* Bigger depth takes longer to draw. */ 
    void
    Hilbert(HDC hdc, int x, int y, int vx, int vy, int wx, int wy, int n)
    {
    if (n >= MAXDEPTH) {
    LineTo(hdc, x + (vx+wx)/2, y + (vy+wy)/2);
    } else {
    n++;
    Hilbert(hdc, x, y, wx/2, wy/2, vx/2, vy/2, n);
    Hilbert(hdc, x+vx/2, y+vy/2, vx/2, vy/2, wx/2, wy/2, n);
    Hilbert(hdc, x+vx/2+wx/2, y+vy/2+wy/2, vx/2, vy/2, wx/2, wy/2, n);
    Hilbert(hdc, x+vx/2+wx, y+vy/2+wy, -wx/2, -wy/2, -vx/2, -vy/2, n);
        }
    }

   /***********************************************************************
     *
    · Hilbert_OnPaint
     *
    · Handle the WM_PAINT message.
     *
    · If the user is dragging the window, then don't do painting,
    · because that would make the dragging very jerky. Instead, just
    · remember that there was a paint message that you ignored. After
    · the size/move is complete, you will perform one big paint to do
    · the things that you ignored.
     *

   ***********************************************************************/ 

    void
    Hilbert_OnPaint(HWND hwnd)
    {
    PAINTSTRUCT ps;
    RECT rc;
    HDC hdc;

    hdc = BeginPaint(hwnd, &ps);
    if (hdc) {
    if (g_fDragging) {
    g_fPaintDeferred = TRUE;
    } else {
    HBRUSH hbrOld;
    HPEN hpenOld;
    HCURSOR hcurOld;

    hcurOld = SetCursor(LoadCursor(0, IDC_WAIT));
    hbrOld = SelectObject(hdc, GetStockObject(BLACK_BRUSH)); hpenOld =
    SelectObject(hdc, GetStockObject(BLACK_PEN));
    MoveToEx(hdc, 0, 0, 0);
    Hilbert(hdc, 0, 0, GetSystemMetrics(SM_CXFULLSCREEN), 0,
    0, GetSystemMetrics(SM_CYFULLSCREEN), 0);
    SelectObject(hdc, hpenOld);
    SelectObject(hdc, hbrOld);
    SetCursor(hcurOld);
            }
    EndPaint(hwnd, &ps);
        }
    }

   /***********************************************************************
     *
    · Hilbert_WndProc
     *
    · Window procedure.
     *

   ***********************************************************************/ 

    LRESULT CALLBACK
    Hilbert_WndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
    {
    switch (wm) {
    case WM_PAINT:
    Hilbert_OnPaint(hwnd);
    break;

    case WM_DESTROY:
    PostQuitMessage(0); break;

        /*
    · When you begin a Size/Move operation, remember that you are
    · performing a Size/Move operation so you don't paint during the
    . Size/Move.
         */ 
    case WM_ENTERSIZEMOVE:
    g_fDragging = TRUE; break;

        /*
    · When you finish a Size/Move operation, remember that you are
    · performing a Size/Move operation so you will resume painting,
    . and if there were any deferred paint messages, re-invalidate
    . yourself they will be regenerated.
         */ 
    case WM_EXITSIZEMOVE:
    g_fDragging = FALSE;
    if (g_fPaintDeferred) {
    g_fPaintDeferred = FALSE;
    InvalidateRect(hwnd, 0, TRUE);
            }
    break;

        }

    return DefWindowProc(hwnd, wm, wp, lp);
    }

   /***********************************************************************
     *
    · WinMain
     *
    · Program entry point.
     *
    · Register the class, create the window, and go into a message loop.
     *

   ***********************************************************************/ 

    int WINAPI
    WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine, int
    nCmdShow)
    {
    HWND hwnd;
    MSG msg;
    WNDCLASS wc = {
    0,
    Hilbert_WndProc,
    0,
    0,
    hinst,
    LoadIcon(0, IDI_APPLICATION),
    LoadCursor(0, IDC_ARROW),
    (HBRUSH)(COLOR_WINDOW+1),
    0,
    "Hilbert"
        };

    RegisterClass(&wc);
    hwnd = CreateWindow("Hilbert", "Hilbert", WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hinst, 0);
    ShowWindow(hwnd, nCmdShow);
    while (GetMessage(&msg, 0, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
        }

    return 0;
    }

Additional query words:
Keywords          : kbNTOS kbGrpUser kbWinOS kbWndw 
Issue type        : kbhowto

Last Reviewed: December 26, 1998