EnumChildWindows 中的 MoveWindow 对对话框内的 listview 的影响:为什么 ListView 标题未正确滚动

2023-12-04

我有一个listview控制(lvc),它在一个DialogBox(dbx) 并且 dbx 也有一个垂直滚动条。

每当滚动条滚动时EnumChildWindows调用以枚举 dbx 的所有子窗口。回调函数包含一个MoveWindow可以移动该 lvc 的函数。 lvc 滚动正常,但列标题滚动不正常,它们不随列表视图移动。

如果我注释掉MoveWindow回调函数内的函数则不会发生任何变化。 (当然lvc不会动!)这意味着EnumChildWindow没有问题,但是MoveWindow回调函数内部引起了问题,我确信这一点,因为调用MoveWindow回调函数外部的函数可以正常工作(因为在这个例子中只有一个控件,即 lvc,所以我不需要枚举所有子窗口)。

这是代码:

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"
{

}

in main.cpp你发现MoveWindow以及底部的其他相关功能。

以下图片很有用。

enter image description here enter image description here

还有滚动的逻辑MoveWindow出于说明的目的,再次是不同的。

最初,当我遇到这个问题时,我正在开发一个包含许多控件的项目。我对此进行了单独分析,发现了我上面写的内容。尽管我通过采用一种不同的方法向下滚动所有控件(不包括调用的方法)绕过了这个问题MoveWindow从内部EnumChildWindows),但我很想知道这个问题的原因和解决方案。

感谢您花时间阅读这篇长文章。任何建议或改进也将是惊人的!


来自评论部分EnumChildWindows()参考:

如果子窗口创建了自己的子窗口, EnumChildWindows 也枚举这些窗口。

因此,您在这里所做的就是滚动列表视图控件,然后分别滚动标题控件。结果是标题控件相对于列表视图控件移动,如第二个屏幕截图所示。

相反,您应该只移动对话框的直接子级,因为孙子级将自动与其父级一起移动。

可能的解决方案:

  • 检查父/子关系EnumChildWindows()回调(例如通过调用GetParent()放在孩子身上并将其与您的对话框句柄进行比较)。
  • 而不是打电话EnumChildWindows() and MoveWindow(), call ScrollWindowEx() with SW_SCROLLCHILDREN。这是实现滚动的最简单方法,所以我更喜欢这个解决方案。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EnumChildWindows 中的 MoveWindow 对对话框内的 listview 的影响:为什么 ListView 标题未正确滚动 的相关文章

  • Linq - 从表达式 创建表达式

    我有一个谓词Expression
  • 使用 Json.NET 序列化子类

    我正在尝试使用 Json NET 序列化子类 生成的 json 包含超类的序列化属性 但是not子类对象的属性 这似乎与我发现的一个问题有关这里就这样 https stackoverflow com q 5863496 498969 但必须
  • 自动映射器多对多 stackoverflowException

    我遇到以下映射的堆栈溢出 Mapper CreateMap
  • 将公历日期转换为儒略日期,然后再转换回来(随着时间)

    我正在编写一个程序 必须将当前的公历日期和时间转换为儒略日期 然后再转换回公历门 最终我需要添加能够添加年 月 日 小时 分钟和秒的功能 但我需要先解决这部分问题 现在我已经从公历日期转换为儒略日期 所以从逻辑上讲 我觉得我应该能够以某种方
  • 平滑手绘曲线

    我有一个允许用户绘制曲线的程序 但这些曲线看起来不太好 它们看起来摇摇欲坠 而且是手绘的 所以我想要一种能够自动平滑它们的算法 我知道平滑过程中存在固有的模糊性 因此它不会每次都完美 但这种算法似乎确实存在于多个绘图包中 并且它们工作得很好
  • 使用 C# 将多个音频样本混合到单个文件中

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个能够创建音频文件 mp3 或 wav 的库 NAudio http www codeple
  • 警告 C4800:“int”:强制值为 bool“true”或“false”(性能警告)

    我的代码中有这个问题 bool CBase isNumber return id MID NUMBER bool CBase isVar return id MID VARIABLE bool CBase isSymbol return i
  • 局部函数声明有什么用处吗?

    大多数像我这样的 C 程序员都曾犯过以下错误 class C int main C c declares a function c taking no arguments returning a C not as intended by m
  • Dapper 在执行时挂起

    我有一个 IDb连接 sql UPDATE 表名 SET json json lastupdate SYSDATE WHERE id id var param new DynamicParameters param Add json jso
  • 如何在C中同时运行两个子进程?

    所以我开始学习并发编程 但由于某种原因我什至无法掌握基础知识 我有一个名为 fork c 的文件 其中包含一个 main 方法 在此方法中 我将 main 分叉两次 分别进入子进程 1 和 2 在孩子 1 中 我打印了字符 A 50 次 在
  • Monotouch全局异常处理

    我在野外发现了一只令人讨厌的虫子 但我无法确定它的具体情况 有没有办法拥有全局 Try Catch 块 或者有办法处理 Monotouch 中未处理的任何异常 我可以包起来吗UIApplication Main args 在 try cat
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 如何让XmlReader读取C#中的属性?

    我有一个 XML Stream 其中包含以下 XML 内容
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 传递数组时在 C 中的函数参数中强制指定数组大小

    Context 在 C 中 我有一个以数组作为参数的函数 该参数用作该函数的输出 输出的大小始终相同 我会 让阅读代码的人清楚所需的大小 不过它已经在函数注释中了 理想情况下 编译会输出警告或错误 这样我就可以在编译时而不是运行时防止出现问
  • 如何同步nosql db(ravendb)中的更改

    我已经开始在 RavenDB 的示例上学习 NoSQL 我从一个最简单的模型开始 假设我们有由用户创建的主题 public class Topic public string Id get protected set public stri
  • 选择合适的IDE

    您会推荐使用以下哪种 IDE 语言来在 Windows 下开发涉及识别手势并与操作系统交互的项目 我将使用 OpenCV 库来执行图像处理任务 之后 我将使用 win32 API 或 NET 框架与操作系统交互 具体取决于您建议的工具 性能
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO

随机推荐

  • 组装 - 在 bochs 中运行引导加载程序时出现问题

    我目前正在尝试在 bochs 中编译并运行一个简单的引导加载程序 目前 这是我的 bootloader asm 文件 BITS 16 ORG 0x7C00 Where the code gets mapped top jmp top Loo
  • 在销毁之前锁定对象的互斥量,它将释放内存或其他一些意外的事情

    这是一个好的和safe练习之前锁定c 对象的互斥体delete这个对象 无需解锁 我这样做是为了保护其他线程在这一毫秒内可能使用对象 概率非常低 之后内存会未分配吗 这是一个好的做法吗 例子 ptr to delete gt MUTEX l
  • 从 Android 服务器播放 Mp4 视频

    我想以流模式从服务器播放 mp4 格式和大小 4 5Mb 的视频 我使用的是 sdk 版本 2 3 在模拟器上 只提供声音但不提供任何图像 我还在 Samsung android sdk ver 2 1 和 LG optimus andro
  • Windows Phone 8 图像绑定

    我想将 image url 绑定到 Windows Phone 8 应用程序中的图像控件 代码如下
  • 我们可以替换 System.out.println() 中的“out”吗?

    首先 我很遗憾 因为我问了一个非常基本和特殊的问题 但我对 Java 和编程都是新手 我研究了system out println 中的 out 是系统类的一个对象 out 可以用系统类的任何其他对象替换吗 如果是的话 成员是什么以及如何
  • iPad modalPresentationStyle UIModalPresentationFormSheet 方向问题

    我在使用 modalPresentationStyle 时遇到问题 我在 tabbarcontroller 的第一个视图控制器的 viewDidload 中调用以下函数以便在应用程序启动时显示登录视图控制器 但问题是 当我在横向模式下启动应
  • CORS:凭据模式为“包含”

    是的 我知道你在想什么 又一个 CORS 问题 但这一次我被难住了 首先 实际的错误消息 XMLHttpRequest 无法加载 http localhost Foo API token 这 响应中 Access Control Allow
  • 如何找到数组元素的索引数组?

    我想用一个例子来展示我想要的 A 5 1 2 4 3 of distinct values B 3 3 1 5 2 我能找到一个在 MATLAB 中实现的库函数吗 C 5 5 2 3 1 someFun A B i e C i find A
  • 在微前端场景中如何共享状态?

    第一个想法是cookie 但你很快就会耗尽空间 有多种方法可以在微前端中进行通信 正如已经指出的 不同的微前端应该是松散耦合的 所以你永远不会直接从一个微前端到另一个微前端进行对话 关键问题是 您的微前端解决方案是基于服务器端 or 客户端
  • YouTube Streaming API 表示用户无法进行直播

    我在用着Google 的 YouTube API 资源管理器 备用 查找信息任意流媒体广播属于别人 无论我投入什么id场 我总是回来 error errors domain youtube liveBroadcast reason live
  • 从嵌套字典创建 Dataframe

    我正在尝试从具有嵌套字典的值列表创建一个数据框所以这是我的数据 d user 200 p val a 10 b 200 f val a 20 b 300 life 8 user 202 p val a 100 b 200 f val a 2
  • 如何找到某个邮政编码所属的州? [关闭]

    Closed 这个问题是无关 目前不接受答案 我有大约 30 000 个邮政编码 我需要提取州 我怎样才能实现这个目标 Copy thiscsv 文件来自this网站到您的工作簿中 然后使用VLOOKUP从邮政编码查找州
  • Bash:测试多个变量的相互相等性?

    测试多个变量是否都相等的正确方法是什么 if var1 var2 var3 syntax error 有必要写下面这样的东西吗 if var1 var2 var1 var3 var2 var3 cumbersome if var1 var2
  • 在 Three.js 中将 Geometry 转换为 BufferGeometry 是否会增加顶点数量?

    我一直在使用 fromGeometry 方法从常规 Geometry 对象创建 BufferGeometry 对象 并且我发现转换过程中顶点数量似乎有所增加 例如 如果我做类似的事情 var geometry new THREE BoxGe
  • Nodejs Mongoose 保存模型未定义不是一个函数

    我使用 Nodejs Express 路由和 Mongoose 来保存数据 我完成了核心路由 CRUD 操作 没有任何问题 但是 当我尝试对模型的其中一个字段执行一些操作 然后尝试使用 model save 保存模型时 它会说 save 方
  • 使用视图代替 INSERT 触发器和标识列

    我正在构建一个数据库来存储公司的客户数据 数据库中的表已标准化 因此我有多个使用外键约束链接在一起的表 Microsoft Access 将用于与数据库交互 作为前端 为了使事情变得更简单 我创建了一个视图 将所有必需的表连接在一起 以便最
  • 如何实现独立克隆TADODataSet?

    场景是这样的 我们有一些 SQL 表 我们正在该表上执行 SQL 查询 并且我们在 TADOQuery 对象中得到结果 var qryOryginal qryClone TADOQuery begin setup all the thing
  • 如何针对需要身份验证令牌的 API 验证协议?

    我正在使用Pact我的合同测试套件的宝石 并且喜欢它 我正在测试的 API 服务需要所有请求的授权令牌 我知道如何为我的用户生成 API 令牌 但我不知道将该令牌放置在 Pact 工作流程中的何处 我搜索了 Pact 文档和存储库中的示例
  • UNIX Case 语句中的模式匹配

    我正在使用一个 shell 脚本 我需要在其中区分tar gz gz bz etc 我首先提取文件的扩展名 然后尝试使用它来匹配它case我的第一个案例是 tar 应该将文件与tar在它们的扩展中 因为可以使用相同的命令提取它们 问题是我试
  • EnumChildWindows 中的 MoveWindow 对对话框内的 listview 的影响:为什么 ListView 标题未正确滚动

    我有一个listview控制 lvc 它在一个DialogBox dbx 并且 dbx 也有一个垂直滚动条 每当滚动条滚动时EnumChildWindows调用以枚举 dbx 的所有子窗口 回调函数包含一个MoveWindow可以移动该 l