question

Default-1573 avatar image
0 Votes"
Default-1573 asked Castorix31 commented

Win32 TabControl resize flicker

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-apic++windows-forms
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Castorix31 avatar image
0 Votes"
Castorix31 answered Castorix31 commented

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

· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you for your response, it still flickers but in a different way.

Here is what it looks like:

https://imgur.com/a/m8m4ipj

0 Votes 0 ·

From my test, there was nearly no flickering (I colored the main window background in red to see it better)
I also did some tests with BeginDeferWindowPos, ...
To remove completely flickering, it can be done with GridSplitter Class, but it is with C++/CLI so the code is a bit different...

122521-test-splitter-flickering.gif


0 Votes 0 ·

Thank you, the solution I'm probably going to implement is using DrawFocusRect on the splitter and move it whatever designated position then perform a MoveWindow operation once I let go of the left button on the mouse. The reason I think there is a flicker and jitter of the windows on the TabControl is because when moving the splitter there is a lot of redrawing and re-positioning happening.

The only other problem is that when trying to resize the whole GUI window from the top left corner a lot of jitter happens from all the windows. If you try to resize from the top left corner long enough the window will break. I can't find a fix or solution for this though.

0 Votes 0 ·
Show more comments
XiaopoYang-MSFT avatar image
0 Votes"
XiaopoYang-MSFT answered

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);
 }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.