Efecto de MoveWindow en EnumChildWindows sobre la vista de lista dentro del cuadro de diálogo: Por qué el encabezado ListView no se desplaza correctamente

Tengo unlistview control (lvc) y está dentro de unaDialogBox (dbx) y ese dbx también tiene una barra de desplazamiento vertical.

Cuando se desplaza la barra de desplazamientoEnumChildWindowse llama a @ para enumerar toda la ventana secundaria de dbx. La función de devolución de llamada contiene unMoveWindow función que movería ese lvc. lvc se desplaza bien pero no sus encabezados de columna, no se mueven con la vista de lista.

Si comento elMoveWindow función dentro de la función de devolución de llamada, entonces nada cambia. (¡Lvc fuera de curso no se moverá!) Eso significaEnumChildWindow no tiene ningún problema, peroMoveWindow dentro de la función de devolución de llamada está causando problemas y estoy seguro de esto porque llamar aMoveWindowa función @ desde fuera de la función de devolución de llamada funciona correctamente (porque en este ejemplo, solo hay un control, es decir, lvc, por lo que no necesito enumerar toda la ventana secundaria).

aquí está el Código:

main.cpp

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif

#include <tchar.h>
#define _WIN32_IE 0x0700
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <vector>
#include "res.h"
#define btn 0
#include <iostream>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK diaproc(HWND hwmd, UINT msg, WPARAM wp, LPARAM lp);
BOOL CALLBACK edc(HWND hwmd,LPARAM lp);
HINSTANCE gi;
int iPrevVscroll=0;
/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    gi = wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS ;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
    case WM_CREATE:
        CreateWindow(WC_BUTTON, "CLICK", WS_CHILD | BS_DEFPUSHBUTTON | WS_VISIBLE, 10, 10, 80, 30, hwnd, (HMENU)btn, gi, NULL  );

    break;
    case WM_COMMAND:{
        if( LOWORD(wParam) == btn && HIWORD(wParam) == BN_CLICKED ) DialogBox(gi, MAKEINTRESOURCE(dia), hwnd,(DLGPROC)diaproc);
        DWORD err = GetLastError();
        std::cout<<err<<std::endl<<dia;
    }
    break;
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

BOOL CALLBACK diaproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lp)
{

    static HWND lv_hwnd;
    static int sci;
    switch(msg)
    {
    case WM_INITDIALOG:
        {

            INITCOMMONCONTROLSEX is;
            is.dwSize = sizeof(INITCOMMONCONTROLSEX);
            is.dwICC = ICC_LISTVIEW_CLASSES;
            InitCommonControlsEx(&is);

            int col_fmt[5] = { LVCFMT_CENTER, LVCFMT_LEFT, LVCFMT_CENTER, LVCFMT_CENTER, LVCFMT_CENTER };
            int col_wid[5] = { 30, 90, 50, 30, 70 };
            std::vector<TCHAR*> col_nam(5);
            col_nam[0] = _T("S.No"); col_nam[1] = _T("Description"); col_nam[2] = _T("HSN"); col_nam[3] = _T("QTY"); col_nam[4] = _T("Rate");

            lv_hwnd = CreateWindow(
                                        WC_LISTVIEW,
                                        _T(""),
                                        WS_CHILD | LVS_REPORT | LVS_EDITLABELS | WS_VISIBLE,
                                        10, 0, 300, 200,
                                        hwnd,
                                        NULL,
                                        (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                                        NULL
                                        );
            ListView_SetExtendedListViewStyle(lv_hwnd, LVS_EX_FLATSB | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP );
            LVCOLUMN lvc;
            lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_TEXT;
            for(int i =0; i < 5; i++)
            {
                lvc.fmt = col_fmt[i];
                lvc.cx = col_wid[i];
                lvc.pszText = col_nam[i];
                lvc.iSubItem =  i;
                ListView_InsertColumn(lv_hwnd, i, &lvc);
            }

            SetScrollRange(hwnd, SB_VERT, 0, 225, TRUE);
            SetScrollPos(hwnd, SB_VERT, 0, TRUE);
        } return FALSE;

        case WM_VSCROLL:
        {
            RECT rc; GetWindowRect(lv_hwnd, &rc);
            POINT pt1 = {rc.left, rc.top}; ScreenToClient(hwnd, &pt1);
            POINT pt2 = {rc.right, rc.bottom}; ScreenToClient(hwnd, &pt2);
            std::cout<<"rc.top : "<< rc.top<<"\nrc.bottom: "<< rc.bottom <<"\nrc.right : "<<rc.right<<"\nrc.left : "<<rc.left<<"\n\n";
            std::cout<<"pt1.y : "<< pt1.y<<"\npt2.y: "<< pt2.y<<"\npt2.x : "<<pt2.x<<"\npt1.x : "<<pt1.x<<"\n\n\n";

            switch(LOWORD(wParam))
            {
            case SB_PAGEDOWN:
            case SB_LINEDOWN:
                sci += 10; break;
            case SB_PAGEUP:
            case SB_LINEUP:
                sci -= 10; break;
            case SB_THUMBTRACK:
                sci = HIWORD(wParam); break;
            };
            sci = sci < 0 ? 0 : sci > 225 ? 225 : sci;
            SetScrollPos(hwnd, SB_VERT, sci, FALSE);
            //MoveWindow(lv_hwnd, pt1.x, pt1.y - sci + iPrevVscroll, pt2.x - pt1.x, pt2.y - pt1.y, TRUE);
            EnumChildWindows(hwnd, edc, (LPARAM)sci);
        }; return TRUE;
            case WM_COMMAND:
                if(LOWORD(wParam) == IDCANCEL) EndDialog(hwnd, wParam); return TRUE;

        default: return FALSE;
    }
}

BOOL CALLBACK edc(HWND hwnd, LPARAM lp)
{
    long s = (long) lp;

    RECT rc; GetWindowRect(hwnd, &rc);
    POINT pt1 = {rc.left, rc.top}; ScreenToClient(hwnd, &pt1);
    POINT pt2 = {rc.right, rc.bottom}; ScreenToClient(hwnd, &pt2);
    MoveWindow(hwnd, pt1.x, pt1.y + s - iPrevVscroll, pt2.x - pt1.x, pt2.y - pt1.y, TRUE);

}

res.h

#define lv 1
#define dia 2

res.rc

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "res.h"

dia DIALOGEX 0,0,500,300
CAPTION "New Invoice"
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_THICKFRAME | WS_VSCROLL

FONT 8, "Ms Shell Dlg"
{

}

inmain.cpp encuentras elMoveWindow y otras funciones relacionadas en la parte inferior.

Las siguientes imágenes son útiles.

también que la lógica de desplazamiento en ambosMoveWindow es diferente, de nuevo, con fines ilustrativos.

Inicialmente estaba trabajando en un proyecto con muchos controles cuando encontré este problema. Analicé esto por separado y descubrí lo que he escrito anteriormente. Aunque evité este problema mediante la adopción de un método diferente para desplazar hacia abajo todos los controles (el que no incluye llamar aMoveWindow desde adentroEnumChildWindows), pero tengo curiosidad por saber el motivo y la solución de este problema.

Gracias por tu tiempo en esta larga publicación. ¡Cualquier sugerencia o mejora también sería increíble!

Respuestas a la pregunta(1)

Su respuesta a la pregunta