1

I create library that allows creating dialog boxes dynamically by DialogBoxIndirectParam. And provides any messages from DlgProc and to controls. Now I have task to show a lot of controls by this library, so they should be placed on any scrollable area.

I searched simple decision from standart controls and controls, available by InitCommonControlsEx, but didn't found.

I create test application with scrollable area by CreateWindow and RegisterClass. It works well.

test application with scrollable area

Then I try to repeate creating such window in my library.

I call RegisterClass and CreateWindow inside WM_INITDIALOG, but CreateWindow returns NULL and GetLastError returns 0.

Upd: add code of 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
}
Solo.dmitry
  • 690
  • 8
  • 15
  • Why are you calling `RegisterClass()` in `WM_INITDIALOG`? Do you unregister the class when the dialog ends? It sounds like you're trying to register the same class multiple times. Other than that, we would need to see code. – andlabs Dec 01 '15 at 06:47
  • You are right, RegisterClass I should place in LoadLibrary and Unregister in UnLoad.. But it does not help. – Solo.dmitry Dec 01 '15 at 07:56
  • 1
    [Casting `DlgProc` to `WNDPROC` is wrong.](http://blogs.msdn.com/b/oldnewthing/archive/2004/01/15/58973.aspx) Write a window procedure for your window class; don't use a dialog procedure. Changing the function signature for `DlgProc` will not work either, as dialog procedures and window procedures work completely differently, and especially since a window procedure will not receive messages such as `WM_INITDIALOG` and return returns differently; you need to go through and change all the dialog gunk to window gunk. If you're using the same `DlgProc` for the outer dialog, you must split them. – andlabs Dec 01 '15 at 16:19

1 Answers1

0

I make separate WndProc with call of DlgProc inside:

WNDCLASSEX wcex;

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

....

In WndProc we don't know a handle of dialog, so we need to save it to GWL_USERDATA at WM_INITDIALOG.

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);
}

Also at WM_INITDIALOG we need to SetParent directly for all children created in DialogBoxIndirectParam. Else "xmyscroll" window hides all its childs.

And also we need to convert the dialog control's sizes to our "xmyscroll" window at working with scroll. But there is some problem with GetDialogBaseUnits, so I used dummy values in MapDialogRect to get the real conversion coefficients between the dimensions of dialogue box and the dimensions of "xmyscroll" window.

so, in code (RSL), that uses library i wrote the next to process the scroll messages (MapDWY does multiple dialog units with koeff for height):

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
        );

From this you can see the key moments to write the correct definition of the important "scroll_inner_height" parameter.

Community
  • 1
  • 1
Solo.dmitry
  • 690
  • 8
  • 15