winapi

时间:2015-12-01 06:28:25

标签: winapi dialog scrollbar

我创建了一个库,允许通过DialogBoxIndirectParam动态创建对话框。并提供来自DlgProc和控件的任何消息。 现在我有任务要显示这个库的很多控件,所以它们应放在任何可滚动的区域。

我通过InitCommonControlsEx提供的标准控件和控件搜索简单的决定,但是没有找到。

我通过CreateWindow和RegisterClass创建具有可滚动区域的测试应用程序。效果很好。

test application with scrollable area

然后我尝试在我的库中重复创建这样的窗口。

我在WM_INITDIALOG中调用RegisterClass和CreateWindow,但CreateWindow返回NULL,GetLastError返回0.

Upd:添加registerclass的代码

WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style          = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc    = (WNDPROC) DlgProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance      = GetModuleHandle(NULL);
wcex.hIcon          = NULL;
wcex.hCursor        = NULL;
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName   = NULL;
wcex.lpszClassName  = "XMYSCROLL";
wcex.hIconSm        = NULL;

if (! RegisterClassEx(&wcex) ){
    // message box with error
}

1 个答案:

答案 0 :(得分:0)

我在内部调用DlgProc制作单独的WndProc:

WNDCLASSEX wcex;

wcex.lpfnWndProc    = (WNDPROC) WndProc;
wcex.hInstance      = GetModuleHandle(NULL);
wcex.lpszClassName  = "XMYSCROLL";
...
if (! RegisterClassEx(&wcex) ){
    ...
}

....

在WndProc中,我们不知道对话句柄,所以 我们需要将它保存到WM_INITDIALOG的GWL_USERDATA。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message==WM_VSCROLL || message==WM_HSCROLL ){
        HWND dialog = (HWND)GetWindowLong(hWnd,GWL_USERDATA);
        if (dialog && IsWindow(dialog) ){
            if (DlgProc(dialog, message, wParam, (DWORD)hWnd) ){
                return 0;
            }
        }
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

同样在WM_INITDIALOG,我们需要直接为DialogBoxIndirectParam中创建的所有子节点设置SetParent。其他“xmyscroll”窗口隐藏了它的所有孩子。

我们还需要在使用滚动时将对话框控件的大小转换为“xmyscroll”窗口。但是有some problem with GetDialogBaseUnits,所以我在MapDialogRect中使用虚拟值来获取对话框尺寸和“xmyscroll”窗口尺寸之间的实际转换系数。

所以,在代码(RSL)中,使用库我编写了下一个来处理滚动消息(MapDWY执行多个对话框单元,其中koeff为高度):

scroll_visible_height = dialog.MapDWY( scroll_height_in_dialog_units );
scroll_inner_height = dialog.MapDWY( (total_controls+1)*controls_step_in_dialog_units );
controls_step = dialog.MapDWY( controls_step_in_dialog_units );

var page = scroll_visible_height + controls_step;

yMaxScroll = max(scroll_inner_height - page, 0);
yCurrentScroll = min(yCurrentScroll, yMaxScroll);
dialog.Set_ScrollInfo(scroll_control_id,
            SB_VERT,
            SIF_RANGE + SIF_PAGE + SIF_POS,
            yMinScroll,
            scroll_inner_height,
            page,
            yCurrentScroll
        );

通过这个,您可以看到写出重要“scroll_inner_height”参数的正确定义的关键时刻。