Win32 TabControl resize flicker

Anonymous
2021-08-11T17:10:15.697+00:00

I made a GUI with a native splitter separating a ListView and TabControl. The TabControl has two child windows an input and output window. The main problem is when I try to move the splitter everything moves as intended however the TabControl flickers a lot. I have spent days looking up on how to fix this issue and have tried everything. I have tried double buffering the TabControl with WS_EX_COMPOSITED and it works but when I move the splitter I can see gray artifacts from what I assume is the hbrbackground on the main window class. After seeing this issue, I kept WS_EX_COMPOSITED on the TabControl and tried putting WS_EX_COMPOSITED on the main window as well and while it removed the gray artifacts from showing when I moved the splitter the TabControl starting flickering again. It seems I can not double buffer the main window and the TabControl at the same time. If you are going to compile this with visual studio make sure to add Comctl32.lib, UxTheme.lib to the linker (I am using visual studio). Can someone please help me fix this?

include <Windows.h>

include <commctrl.h>

include <windowsx.h>

include <process.h>

include <iostream>

include <Uxtheme.h>

struct _WINDOW_HANDLES
{
    HWND Main;
    HWND ListView;
    HWND TabControl;
    HWND OutputWindow;
    HWND InputWindow;
    HWND SplitterProc;
} wh;

HINSTANCE ghInst;

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TabControlProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SplitterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

static WNDPROC TabControlWndProc;
static WNDPROC TabOutputWndProc;
static WNDPROC SplitterWndProc;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)
{
    WNDCLASSW wc;
    memset(&wc, 0, sizeof(WNDCLASSW));
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hInstance = hInst;
    wc.lpszClassName = L"MainWindowClass";
    wc.lpfnWndProc = WindowProcedure;

    if (!RegisterClassW(&wc))
        return -1;

    wh.Main = CreateWindowExW(NULL, L"MainWindowClass", L"GUI", WS_OVERLAPPEDWINDOW | WS_EX_COMPOSITED, CW_USEDEFAULT, CW_USEDEFAULT, 1300, 700, NULL, NULL, hInst, NULL);
    ShowWindow(wh.Main, ncmdshow);

    MSG msg;
    memset(&msg, 0, sizeof(MSG));

    while (GetMessageW((&msg), NULL, NULL, NULL))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return 0;
}

VOID InitializeComponent(HWND hWnd)
{
    RECT rcMain;
    GetClientRect(hWnd, &rcMain);

    wh.ListView = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, rcMain.right, 180, hWnd, (HMENU)0, ghInst, NULL);
    ListView_SetExtendedListViewStyle(wh.ListView, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

    LVCOLUMN lvc;
    memset(&lvc, 0, sizeof(LVCOLUMN));
    lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    lvc.iSubItem = 0;
    lvc.cx = 125;
    lvc.pszText = (LPWSTR)L"Column 1";
    ListView_InsertColumn(wh.ListView, 0, &lvc);

    lvc.iSubItem = 1;
    lvc.cx = 125;
    lvc.pszText = (LPWSTR)L"Column 2";
    ListView_InsertColumn(wh.ListView, 1, &lvc);

    LVITEM lvi;
    memset(&lvi, 0, sizeof(LVITEM));
    lvi.mask = LVIF_TEXT;
    lvi.iItem = 0;
    lvi.iSubItem = 0;
    lvi.pszText = (LPWSTR)L"Item 1";
    ListView_InsertItem(wh.ListView, &lvi);

    ListView_SetItemText(wh.ListView, 0, 1, (LPWSTR)L"Item 2");



    wh.TabControl = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TABCONTROL, L"", WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 196, rcMain.right, rcMain.bottom - 196, hWnd, (HMENU)0, ghInst, NULL);

    TCITEM tie;
    tie.mask = TCIF_TEXT;
    tie.pszText = (LPWSTR)L"Tab";
    TabCtrl_InsertItem(wh.TabControl, 0, &tie);

    TabControlWndProc = (WNDPROC)SetWindowLongPtr(wh.TabControl, GWLP_WNDPROC, (LONG_PTR)TabControlProc);

    LOGFONT lf;
    GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
    HFONT hFont = CreateFont(
        19, 0,
        lf.lfEscapement, lf.lfOrientation, lf.lfWeight,
        lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut,
        lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,
        lf.lfQuality, lf.lfPitchAndFamily, NULL);
    SendMessage(wh.TabControl, WM_SETFONT, (WPARAM)hFont, TRUE);

    HFONT IFont = CreateFont(
        17, 0,
        lf.lfEscapement, lf.lfOrientation, lf.lfWeight,
        lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut,
        lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,
        lf.lfQuality, lf.lfPitchAndFamily, NULL);

    wh.OutputWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN, 0, 25, rcMain.right, rcMain.bottom - 251, wh.TabControl, NULL, ghInst, NULL);
    SendMessage(wh.OutputWindow, EM_SETREADONLY, TRUE, 0);
    SendMessage(wh.OutputWindow, WM_SETFONT, (WPARAM)hFont, TRUE);

    wh.InputWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE, 0, rcMain.bottom - 227, rcMain.right, 28, wh.TabControl, NULL, ghInst, NULL);
    SendMessage(wh.InputWindow, WM_SETFONT, (WPARAM)IFont, TRUE);

    wh.SplitterProc = CreateWindowEx(NULL, WC_STATIC, L"", WS_CHILD | WS_BORDER | WS_VISIBLE | SS_NOTIFY | SS_CENTER, 0, 181, rcMain.right, 17, hWnd, NULL, ghInst, NULL);
    SplitterWndProc = (WNDPROC)SetWindowLongPtr(wh.SplitterProc, GWLP_WNDPROC, (LONG_PTR)SplitterProc);
}

LRESULT CALLBACK SplitterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static BOOL bSplitterMoving;

    RECT rcMain, rcListView;
    GetClientRect(wh.Main, &rcMain);
    GetClientRect(wh.ListView, &rcListView);

    switch (message)
    {
        case WM_SETCURSOR:
        {
            SetCursor(LoadCursor(NULL, IDC_SIZENS));
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
            return TRUE;
        }

        case WM_LBUTTONDOWN:
        {
            bSplitterMoving = TRUE;
            SetCapture(wh.SplitterProc);
            return 0;
        }
        break;

        case WM_LBUTTONUP:
        {
            ReleaseCapture();
            bSplitterMoving = FALSE;
            return 0;
        }

        case WM_MOUSEMOVE:
        {

            POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };
            ClientToScreen(wh.SplitterProc, &pt);
            ScreenToClient(wh.Main, &pt);

            auto newSplitterPos = pt.y;
            if (newSplitterPos <= 125 || newSplitterPos >= 350)
            {
                return 0;
            }

            if (bSplitterMoving)
            {
                POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };
                ClientToScreen(wh.SplitterProc, &pt);
                ScreenToClient(wh.Main, &pt);

                auto newSplitterPos = pt.y;

                MoveWindow(wh.SplitterProc, 0, newSplitterPos, rcMain.right, 17, TRUE);
                MoveWindow(wh.ListView, 0, 0, rcMain.right, newSplitterPos, TRUE); 

                MoveWindow(wh.TabControl, rcMain.left, newSplitterPos + 15, rcMain.right, rcMain.bottom - (newSplitterPos + 15), TRUE); 
                MoveWindow(wh.OutputWindow, 0, 25, rcMain.right, rcMain.bottom - (newSplitterPos + 71), TRUE); 
                MoveWindow(wh.InputWindow, rcMain.left, rcMain.bottom - (newSplitterPos + 46), rcMain.right, 28, TRUE); 
            }
            return 0;
        }
    }
    return CallWindowProc(SplitterWndProc, hwnd, message, wParam, lParam);
}


LRESULT CALLBACK TabControlProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CTLCOLORSTATIC:
        {
            HDC hdcStatic = (HDC)wParam;
            SetTextColor(hdcStatic, RGB(255, 255, 255));
            SetBkColor(hdcStatic, RGB(0, 0, 0));
            HBRUSH hbrBkgnd = CreateSolidBrush(RGB(0, 0, 0));
            return (INT_PTR)hbrBkgnd;
        }

        case WM_CTLCOLOREDIT:
        {
            HDC hdcStatic = (HDC)wParam;
            SetTextColor(hdcStatic, RGB(255, 255, 255));
            SetBkColor(hdcStatic, RGB(0, 0, 0));
            HBRUSH hbrBkgnd = CreateSolidBrush(RGB(0, 0, 0));
            return (INT_PTR)hbrBkgnd;
        }
    }
    return CallWindowProc(TabControlWndProc, hDlg, message, wParam, lParam);
}

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    RECT rcMain, rcListView, rcTabControl;
    GetClientRect(hWnd, &rcMain);
    GetClientRect(wh.ListView, &rcListView);
    GetClientRect(wh.TabControl, &rcTabControl);

    switch (msg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        case WM_CREATE:
        {
            InitializeComponent(hWnd);
            break;
        }

        case WM_SIZE:
        {
            POINT  pt{ GET_X_LPARAM(lp),GET_Y_LPARAM(lp) };
            ClientToScreen(wh.SplitterProc, &pt);
            ScreenToClient(wh.Main, &pt);
            int newSplitterPos = pt.y;

            SetWindowPos(wh.ListView, NULL, rcMain.left, rcMain.left, rcMain.right, newSplitterPos - rcMain.bottom - 1, SWP_NOMOVE);
            ListView_SetColumnWidth(wh.ListView, 1, LVSCW_AUTOSIZE_USEHEADER);
            SetWindowPos(wh.TabControl, NULL, rcMain.left, newSplitterPos - (9 + rcTabControl.bottom + rcListView.bottom), rcMain.right, rcMain.bottom - (rcListView.bottom + 19), SWP_NOMOVE);
            MoveWindow(wh.OutputWindow, 0, 25, rcMain.right, rcMain.bottom - (rcListView.bottom + 75), TRUE);
            MoveWindow(wh.InputWindow, rcMain.left, rcMain.bottom - (rcListView.bottom + 51), rcMain.right, 28, TRUE);
            SetWindowPos(wh.SplitterProc, NULL, rcMain.left, newSplitterPos - (24 + rcTabControl.bottom + rcListView.bottom), LOWORD(lp), 17, SWP_NOMOVE);
            SetWindowText(wh.SplitterProc, L"...");

            break;
        }
    }
    return DefWindowProcW(hWnd, msg, wp, lp);
}
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,863 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,471 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,591 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Castorix31 82,321 Reputation points
    2021-08-11T17:49:52.14+00:00

    The flickering is often because of background repainting

    A test to reduce it, by adding in the TabControlProc :
    (to be improved, I just shifted the rectangle for 1 Tab Item for testing)

    case WM_ERASEBKGND:
    {     
        RECT rc;
        TabCtrl_GetItemRect(hDlg, 0, &rc);
        HDC hdc = (HDC)wParam;
        RECT rect;
        GetClientRect(hDlg, &rect);
        SetRect(&rect, rc.right - rc.left + 4, rect.top, rect.right, rect.bottom);      
        FillRect(hdc, &rect, GetSysColorBrush(COLOR_3DFACE));
        return 1;
    }
    

  2. Xiaopo Yang - MSFT 11,746 Reputation points Microsoft Vendor
    2021-08-18T06:53:47.373+00:00

    I have check out the code and @Castorix31 ‘s code. I found that the problem is at MoveWindow(wh.TabControl.... The parameter passed to MoveWindow which is only different with @Castorix31 ‘s MoveWindow and causes flickering is puzzling.
    The following is code. Commenting the others in WM_MOUSEMOVE and Uncommenting the Main_SizeChildren2 will cause TabControl flickering.

    #include "framework.h"  
    #include <Windows.h>  
    #include <commctrl.h>  
    #include <windowsx.h>  
    #include <process.h>  
    #include <iostream>  
    #include <Uxtheme.h>  
    #pragma comment(lib,"Comctl32.lib")  
    #pragma comment(lib,"UxTheme.lib")  
      
    #define SPLIT_WIDTH 2  
    #define SPLIT_MIN 50  
    #define GAP_SIZE    3  
    #define MIN_SIZE    10  
    UINT g_uPosition;  
    struct _WINDOW_HANDLES  
    {  
        HWND Main;  
        HWND ListView;  
        HWND TabControl;  
        HWND OutputWindow;  
        HWND InputWindow;  
        HWND SplitterProc;  
    } wh;  
    HINSTANCE ghInst;  
    LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);  
    LRESULT CALLBACK TabControlProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);  
    LRESULT CALLBACK SplitterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);  
    static WNDPROC TabControlWndProc;  
    static WNDPROC TabOutputWndProc;  
    static WNDPROC SplitterWndProc;  
    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)  
    {  
        WNDCLASSW wc;  
        memset(&wc, 0, sizeof(WNDCLASSW));  
        wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);  
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);  
        wc.hInstance = hInst;  
        wc.lpszClassName = L"MainWindowClass";  
        wc.lpfnWndProc = WindowProcedure;  
        if (!RegisterClassW(&wc))  
            return -1;  
        wh.Main = CreateWindowExW(NULL, L"MainWindowClass", L"GUI", WS_OVERLAPPEDWINDOW | WS_EX_COMPOSITED, CW_USEDEFAULT, CW_USEDEFAULT, 1300, 700, NULL, NULL, hInst, NULL);  
        ShowWindow(wh.Main, ncmdshow);  
        MSG msg;  
        memset(&msg, 0, sizeof(MSG));  
        while (GetMessageW((&msg), NULL, NULL, NULL))  
        {  
            TranslateMessage(&msg);  
            DispatchMessageW(&msg);  
        }  
        return 0;  
    }  
    VOID InitializeComponent(HWND hWnd)  
    {  
        RECT rcMain;  
        GetClientRect(hWnd, &rcMain);  
      
        wh.ListView = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, rcMain.right, 180, hWnd, (HMENU)0, ghInst, NULL);  
        ListView_SetExtendedListViewStyle(wh.ListView, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);  
        LVCOLUMN lvc;  
        memset(&lvc, 0, sizeof(LVCOLUMN));  
        lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;  
        lvc.iSubItem = 0;  
        lvc.cx = 125;  
        lvc.pszText = (LPWSTR)L"Column 1";  
        ListView_InsertColumn(wh.ListView, 0, &lvc);  
        lvc.iSubItem = 1;  
        lvc.cx = 125;  
        lvc.pszText = (LPWSTR)L"Column 2";  
        ListView_InsertColumn(wh.ListView, 1, &lvc);  
        LVITEM lvi;  
        memset(&lvi, 0, sizeof(LVITEM));  
        lvi.mask = LVIF_TEXT;  
        lvi.iItem = 0;  
        lvi.iSubItem = 0;  
        lvi.pszText = (LPWSTR)L"Item 1";  
        ListView_InsertItem(wh.ListView, &lvi);  
        ListView_SetItemText(wh.ListView, 0, 1, (LPWSTR)L"Item 2");  
      
        wh.TabControl = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TABCONTROL, L"", WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 196, rcMain.right, rcMain.bottom - 196, hWnd, (HMENU)0, ghInst, NULL);  
        TCITEM tie;  
        tie.mask = TCIF_TEXT;  
        tie.pszText = (LPWSTR)L"Tab";  
        TabCtrl_InsertItem(wh.TabControl, 0, &tie);  
      
        //TabControlWndProc = (WNDPROC)SetWindowLongPtr(wh.TabControl, GWLP_WNDPROC, (LONG_PTR)TabControlProc);  
      
        /*LOGFONT lf;  
        GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);  
        HFONT hFont = CreateFont(  
            19, 0,  
            lf.lfEscapement, lf.lfOrientation, lf.lfWeight,  
            lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut,  
            lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,  
            lf.lfQuality, lf.lfPitchAndFamily, NULL);  
        SendMessage(wh.TabControl, WM_SETFONT, (WPARAM)hFont, TRUE);  
        HFONT IFont = CreateFont(  
            17, 0,  
            lf.lfEscapement, lf.lfOrientation, lf.lfWeight,  
            lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut,  
            lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,  
            lf.lfQuality, lf.lfPitchAndFamily, NULL);*/  
      
        wh.OutputWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN, 0, 25, rcMain.right, rcMain.bottom - 251, wh.TabControl, NULL, ghInst, NULL);  
        SendMessage(wh.OutputWindow, EM_SETREADONLY, TRUE, 0);  
        //SendMessage(wh.OutputWindow, WM_SETFONT, (WPARAM)hFont, TRUE);  
        wh.InputWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE, 0, rcMain.bottom - 227, rcMain.right, 28, wh.TabControl, NULL, ghInst, NULL);  
        //SendMessage(wh.InputWindow, WM_SETFONT, (WPARAM)IFont, TRUE);  
      
        wh.SplitterProc = CreateWindowEx(NULL, WC_STATIC, L"", WS_CHILD | WS_BORDER | WS_VISIBLE | SS_NOTIFY | SS_CENTER, 0, 181, rcMain.right, 17, hWnd, NULL, ghInst, NULL);  
        //SplitterWndProc = (WNDPROC)SetWindowLongPtr(wh.SplitterProc, GWLP_WNDPROC, (LONG_PTR)SplitterProc);  
    }  
    LRESULT CALLBACK SplitterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
    {  
        static BOOL bSplitterMoving;  
        RECT rcMain, rcListView;  
        GetClientRect(wh.Main, &rcMain);  
        GetClientRect(wh.ListView, &rcListView);  
        switch (message)  
        {  
        /*case WM_SETCURSOR:  
        {  
            SetCursor(LoadCursor(NULL, IDC_SIZENS));  
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);  
            return TRUE;  
        }*/  
        case WM_LBUTTONDOWN:  
        {  
            bSplitterMoving = TRUE;  
            SetCapture(wh.SplitterProc);  
            return 0;  
        }  
        break;  
        case WM_LBUTTONUP:  
        {  
            ReleaseCapture();  
            bSplitterMoving = FALSE;  
            return 0;  
        }  
        case WM_MOUSEMOVE:  
        {  
            POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };  
            ClientToScreen(wh.SplitterProc, &pt);  
            ScreenToClient(wh.Main, &pt);  
            auto newSplitterPos = pt.y;  
            if (newSplitterPos <= 125 || newSplitterPos >= 350)  
            {  
                return 0;  
            }  
      
            if (bSplitterMoving)  
            {  
                POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };  
                ClientToScreen(wh.SplitterProc, &pt);  
                ScreenToClient(wh.Main, &pt);  
                auto newSplitterPos = pt.y;  
      
                //MoveWindow(wh.SplitterProc, 0, newSplitterPos, rcMain.right, 17, TRUE);  
                //MoveWindow(wh.ListView, 0, 0, rcMain.right, newSplitterPos, TRUE);  
                MoveWindow(wh.TabControl, rcMain.left, newSplitterPos + 15, rcMain.right, rcMain.bottom - (newSplitterPos + 15), TRUE);  
                //MoveWindow(wh.OutputWindow, 0, 25, rcMain.right, rcMain.bottom - (newSplitterPos + 71), TRUE);  
                //MoveWindow(wh.InputWindow, rcMain.left, rcMain.bottom - (newSplitterPos + 46), rcMain.right, 28, TRUE);  
            }  
            return 0;  
        }  
        }  
        return CallWindowProc(SplitterWndProc, hwnd, message, wParam, lParam);  
    }  
    LRESULT CALLBACK TabControlProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)  
    {  
        switch (message)  
        {  
        case WM_CTLCOLORSTATIC:  
        {  
            HDC hdcStatic = (HDC)wParam;  
            SetTextColor(hdcStatic, RGB(255, 255, 255));  
            SetBkColor(hdcStatic, RGB(0, 0, 0));  
            HBRUSH hbrBkgnd = CreateSolidBrush(RGB(0, 0, 0));  
            return (INT_PTR)hbrBkgnd;  
        }  
        case WM_CTLCOLOREDIT:  
        {  
            HDC hdcStatic = (HDC)wParam;  
            SetTextColor(hdcStatic, RGB(255, 255, 255));  
            SetBkColor(hdcStatic, RGB(0, 0, 0));  
            HBRUSH hbrBkgnd = CreateSolidBrush(RGB(0, 0, 0));  
            return (INT_PTR)hbrBkgnd;  
        }  
        }  
        return CallWindowProc(TabControlWndProc, hDlg, message, wParam, lParam);  
    }  
      
    void Main_SizeChildren2(HWND hwndParent, WPARAM wParam, LPARAM lParam)  
    {  
        RECT rcMain;  
        GetClientRect(wh.Main, &rcMain);  
        POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };  
        ClientToScreen(wh.SplitterProc, &pt);  
        ScreenToClient(wh.Main, &pt);  
        auto newSplitterPos = pt.y;  
      
        MoveWindow(wh.TabControl, rcMain.left, newSplitterPos + 15, rcMain.right, rcMain.bottom - (newSplitterPos + 15), TRUE);  
    }  
      
    void Main_SizeChildren(HWND hwndParent)  
    {  
        RECT  rc;  
        GetClientRect(hwndParent, &rc);  
        if (!g_uPosition)  
        {  
            g_uPosition = rc.bottom / 3;  
        }  
        MoveWindow(wh.ListView,  
            0,  
            0,  
            rc.right - rc.left,  
            g_uPosition - GAP_SIZE,  
            TRUE);  
        //MoveWindow(GetDlgItem(hwndParent, IDC_EDIT2),  
        MoveWindow(wh.TabControl,  
            0,  
            g_uPosition,  
            rc.right - rc.left,  
            rc.bottom,  
            TRUE);  
    }  
      
    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  
    {  
        static BOOL bSplitterMoving;  
        RECT rcMain, rcListView, rcTabControl;  
        GetClientRect(hWnd, &rcMain);  
        GetClientRect(wh.ListView, &rcListView);  
        GetClientRect(wh.TabControl, &rcTabControl);  
        switch (msg)  
        {  
        case WM_DESTROY:  
            PostQuitMessage(0);  
            break;  
      
        case WM_CREATE:  
        {  
            InitializeComponent(hWnd);  
            break;  
        }  
        /*case WM_SIZE:  
        {  
            Main_SizeChildren(hWnd);  
        }  
        break;*/  
        case WM_LBUTTONDOWN:  
            SetCapture(hWnd);  
            SetCursor(LoadCursor(NULL, IDC_SIZENS));  
            return 0;  
      
        case WM_LBUTTONUP:  
            ReleaseCapture();  
            return 0;  
        case WM_MOUSEMOVE:  
            //if the left button is down  
            if (GetKeyState(VK_LBUTTON) & 0x8000)  
            {  
                RECT  rc;  
                GetClientRect(hWnd, &rc);  
      
                //don't do anything if we are already at the minimum size  
                if ((g_uPosition == MIN_SIZE) && (HIWORD(lParam) <= MIN_SIZE))  
                    break;  
      
                //don't do anything if we are already at the maximum size  
                if (((rc.bottom - g_uPosition) == MIN_SIZE) && (HIWORD(lParam) >= g_uPosition))  
                    break;  
      
                g_uPosition = HIWORD(lParam);  
      
                //check for min and max  
                if (g_uPosition < MIN_SIZE)  
                    g_uPosition = MIN_SIZE;  
      
                if ((rc.bottom - g_uPosition) < MIN_SIZE)  
                    g_uPosition = rc.bottom - MIN_SIZE;  
      
                Main_SizeChildren(hWnd);  
            }  
            else if ((g_uPosition <= (HIWORD(lParam) + GAP_SIZE))  
                && (g_uPosition >= (HIWORD(lParam) - GAP_SIZE)))  
            {  
                SetCursor(LoadCursor(NULL, IDC_SIZENS));  
            }  
            else  
            {  
                SetCursor(LoadCursor(NULL, IDC_ARROW));  
            }  
            //Main_SizeChildren2(hWnd, wParam, lParam); //Commenting the others in WM_MOUSEMOVE and Uncommenting the line will cause TabControl flickering  
            break;  
        //case WM_SIZE:  
        //{  
        //    POINT  pt{ GET_X_LPARAM(lp),GET_Y_LPARAM(lp) };  
        //    ClientToScreen(wh.SplitterProc, &pt);  
        //    ScreenToClient(wh.Main, &pt);  
        //    int newSplitterPos = pt.y;  
      
        //    //SetWindowPos(wh.ListView, NULL, rcMain.left, rcMain.left, rcMain.right, newSplitterPos - rcMain.bottom - 1, SWP_NOMOVE);  
        //    ListView_SetColumnWidth(wh.ListView, 1, LVSCW_AUTOSIZE_USEHEADER);  
        //    //SetWindowPos(wh.TabControl, NULL, rcMain.left, newSplitterPos - (9 + rcTabControl.bottom + rcListView.bottom), rcMain.right, rcMain.bottom - (rcListView.bottom + 19), SWP_NOMOVE);  
        //    MoveWindow(wh.OutputWindow, 0, 25, rcMain.right, rcMain.bottom - (rcListView.bottom + 75), TRUE);  
        //    MoveWindow(wh.InputWindow, rcMain.left, rcMain.bottom - (rcListView.bottom + 51), rcMain.right, 28, TRUE);  
        //    //SetWindowPos(wh.SplitterProc, NULL, rcMain.left, newSplitterPos - (24 + rcTabControl.bottom + rcListView.bottom), LOWORD(lp), 17, SWP_NOMOVE);  
        //    SetWindowText(wh.SplitterProc, L"...");  
        //    break;  
        //}  
        }  
        return DefWindowProcW(hWnd, msg, wParam, lParam);  
    }
    
    0 comments No comments