Win32 Window resize bounce\shake

Anonymous
2021-09-06T01:57:50.997+00:00

This will be the last post I make on the Tab Control. When I have a child window of a tab control and move the splitter, the bottom of the child window jitters\shakes. I have tried everything to get rid of this and nothing works. The tab control is double buffered and so is the child window of the tab control. The tab control itself is fine, it is only the child window of the tab control that is having this problem. Can someone help me fix this please?

129416-resize.gif

#include <Windows.h>  
#include <commctrl.h>  
#include <windowsx.h>  
#include <process.h>  
#include <iostream>  
#include <Uxtheme.h>  
  
struct _WINDOW_HANDLES  
{  
	HWND MainWindow;  
	HWND ListViewWindow;  
	HWND SplitterWindow;  
  
	HWND TabMainWindow;  
	HWND TabChildWindow;  
  
} wh;  
  
HINSTANCE ghInst;  
  
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);  
LRESULT CALLBACK SplitterProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
  
LRESULT CALLBACK TabMainProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
  
LRESULT CALLBACK TabChildWindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
  
static WNDPROC SplitterWndProc;  
  
static WNDPROC TabMainWndProc;  
static WNDPROC TabChildWndProc;  
  
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)  
{  
	WNDCLASSW wc;  
	memset(&wc, 0, sizeof(WNDCLASSW));  
	wc.hbrBackground = NULL;  
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);  
	wc.hInstance = hInst;  
	wc.lpszClassName = L"MainWindowClass";  
	wc.lpfnWndProc = WindowProcedure;  
  
	if (!RegisterClassW(&wc))  
	{  
		return -1;  
	}  
  
	wh.MainWindow = CreateWindowExW(NULL, L"MainWindowClass", L"GUI", WS_OVERLAPPEDWINDOW | WS_EX_COMPOSITED, CW_USEDEFAULT, CW_USEDEFAULT, 1300, 700, NULL, NULL, hInst, NULL);  
	ShowWindow(wh.MainWindow, 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.ListViewWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, rcMain.right, 265, hWnd, (HMENU)0, ghInst, NULL);  
	ListView_SetExtendedListViewStyle(wh.ListViewWindow, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER);  
  
	SendMessage(wh.ListViewWindow, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0);  
  
	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.ListViewWindow, 0, &lvc);  
  
	lvc.iSubItem = 1;  
	lvc.cx = 125;  
	lvc.pszText = (LPWSTR)L"Column 2";  
	ListView_InsertColumn(wh.ListViewWindow, 1, &lvc);  
  
	LVITEM lvi;  
	memset(&lvi, 0, sizeof(LVITEM));  
	lvi.mask = LVIF_TEXT;  
	lvi.iItem = 0;  
	lvi.iSubItem = 0;  
	lvi.iImage = 0;  
	lvi.pszText = (LPWSTR)L"Item 1";  
	ListView_InsertItem(wh.ListViewWindow, &lvi);  
  
	ListView_SetItemText(wh.ListViewWindow, 0, 1, (LPWSTR)L"Item 2");	  
  
	wh.SplitterWindow = CreateWindowEx(NULL, WC_STATIC, L"", WS_CHILD | WS_BORDER | WS_VISIBLE | SS_NOTIFY | SS_CENTER, 0, 265, rcMain.right, 17, hWnd, NULL, ghInst, NULL);  
	SplitterWndProc = (WNDPROC)SetWindowLongPtr(wh.SplitterWindow, GWLP_WNDPROC, (LONG_PTR)SplitterProcedure);  
  
	LOGFONT lf;  
	GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);  
	HFONT GeneralFont = 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);  
  
	wh.TabMainWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TABCONTROL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, rcMain.left, 283, rcMain.right, 378, hWnd, NULL, ghInst, NULL);  
	TabMainWndProc = (WNDPROC)SetWindowLongPtr(wh.TabMainWindow, GWLP_WNDPROC, (LONG_PTR)TabMainProcedure);  
	SendMessage(wh.TabMainWindow, WM_SETFONT, (WPARAM)GeneralFont, TRUE);  
  
	TCITEM tie;  
	tie.mask = TCIF_TEXT;  
	tie.iImage = 0;  
	tie.pszText = (LPWSTR)L"Tab";  
	TabCtrl_InsertItem(wh.TabMainWindow, 0, &tie);  
  
	wh.TabChildWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | ES_MULTILINE | ES_WANTRETURN, rcMain.left, 25, rcMain.right, 348, wh.TabMainWindow, NULL, ghInst, NULL);  
	TabChildWndProc = (WNDPROC)SetWindowLongPtr(wh.TabChildWindow, GWLP_WNDPROC, (LONG_PTR)TabChildWindowProcedure);  
	SendMessage(wh.TabChildWindow, WM_SETFONT, (WPARAM)GeneralFont, TRUE);  
}  
  
LRESULT CALLBACK SplitterProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
	static BOOL bSplitterMoving;  
  
	RECT rcMain;  
	GetClientRect(wh.MainWindow, &rcMain);  
  
	switch (message)  
	{  
		case WM_SETCURSOR:  
		{  
			SetCursor(LoadCursor(NULL, IDC_SIZENS));  
			SetWindowLongPtr(hWnd, DWLP_MSGRESULT, TRUE);  
			return TRUE;  
		}  
  
		case WM_LBUTTONDOWN:  
		{  
			bSplitterMoving = TRUE;  
			SetCapture(wh.SplitterWindow);  
			return 0;  
		}  
  
		case WM_LBUTTONUP:  
		{  
			ReleaseCapture();  
			bSplitterMoving = FALSE;  
			return 0;  
		}  
  
		case WM_MOUSEMOVE:  
		{  
			if (bSplitterMoving)  
			{  
				POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };  
				ClientToScreen(wh.SplitterWindow, &pt);  
				ScreenToClient(wh.MainWindow, &pt);  
  
				auto newSplitterPos = pt.y;  
				if (newSplitterPos <= 105 || newSplitterPos >= 265)  
				{  
					return 0;  
				}  
  
				else  
				{  
					HDWP hdwp = BeginDeferWindowPos(3);  
  
					DeferWindowPos(hdwp, wh.ListViewWindow, NULL, rcMain.left, rcMain.left, rcMain.right, newSplitterPos, NULL);  
					DeferWindowPos(hdwp, wh.SplitterWindow, NULL, rcMain.left, newSplitterPos, rcMain.right, 17, NULL);  
					DeferWindowPos(hdwp, wh.TabMainWindow, NULL, rcMain.left, newSplitterPos + 18, rcMain.right, rcMain.bottom - (newSplitterPos + 18), NULL);  
					EndDeferWindowPos(hdwp);  
  
					MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom - (newSplitterPos + 48), TRUE);  
  
					UpdateWindow(wh.ListViewWindow);  
					UpdateWindow(wh.SplitterWindow);  
					UpdateWindow(wh.TabMainWindow);  
				}  
				return 0;  
			}  
		}  
	}  
	return CallWindowProc(SplitterWndProc, hWnd, message, wParam, lParam);  
}  
  
LRESULT CALLBACK TabMainProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
	switch (message)  
	{  
		PAINTSTRUCT ps;  
		RECT rc;  
		HDC hdc, hdcMem;  
		HBITMAP hbmMem, hbmOld;  
  
		case WM_PAINT:  
		{  
			hdc = BeginPaint(hWnd, &ps);  
			GetClientRect(hWnd, &rc);  
			hdcMem = CreateCompatibleDC(hdc);  
			hbmMem = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);  
			hbmOld = ((HBITMAP)SelectObject(hdcMem, hbmMem));  
			FillRect(hdcMem, &rc, (HBRUSH)GetSysColorBrush(COLOR_3DFACE));  
			CallWindowProc(TabMainWndProc, hWnd, message, ((WPARAM)hdcMem), lParam);  
			BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMem, 0, 0, SRCCOPY);  
			SelectObject(hdcMem, hbmOld);  
			DeleteObject(hbmMem);  
			DeleteDC(hdcMem);  
			EndPaint(hWnd, &ps);  
  
			return 0;  
		}  
  
		case WM_ERASEBKGND:  
		{  
			return (LRESULT)1;  
		}  
  
		case WM_CTLCOLORSTATIC:  
		{  
	  
			HDC hdcStatic = (HDC)wParam;  
			SetBkColor(hdcStatic, RGB(0, 0, 0));   
			return (LRESULT)GetStockObject(BLACK_BRUSH);   
			  
		}  
	}  
  
	return CallWindowProc(TabMainWndProc, hWnd, message, wParam, lParam);  
}  
  
LRESULT CALLBACK TabChildWindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
	switch (message)  
	{  
		PAINTSTRUCT ps;  
		RECT rc;  
		HDC hdc, hdcMem;  
		HBITMAP hbmMem, hbmOld;  
  
		case WM_PAINT:  
		{  
			hdc = BeginPaint(hWnd, &ps);  
			GetClientRect(hWnd, &rc);  
			hdcMem = CreateCompatibleDC(hdc);  
			hbmMem = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);  
			hbmOld = ((HBITMAP)SelectObject(hdcMem, hbmMem));  
			FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));  
			CallWindowProc(TabChildWndProc, hWnd, message, ((WPARAM)hdcMem), lParam);  
			BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMem, 0, 0, SRCCOPY);  
			SelectObject(hdcMem, hbmOld);  
			DeleteObject(hbmMem);  
			DeleteDC(hdcMem);  
			EndPaint(hWnd, &ps);  
  
			return 0;  
		}  
  
		case WM_ERASEBKGND:  
		{  
			return (LRESULT)1;  
		}  
	}  
  
	return CallWindowProc(TabChildWndProc, hWnd, message, wParam, lParam);  
}  
  
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)  
{  
	LPMINMAXINFO lpMMI = (LPMINMAXINFO)lp;  
  
	RECT rcMain, rcListView;  
	GetClientRect(hWnd, &rcMain);  
	GetClientRect(wh.ListViewWindow, &rcListView);  
  
	HMENU hMenu;  
  
	switch (msg)  
	{  
		case WM_DESTROY:  
		{  
			PostQuitMessage(0);  
			return 0;  
		}  
  
		case WM_CREATE:  
		{  
			InitializeComponent(hWnd);  
			return 0;  
		}  
  
		case WM_ERASEBKGND:  
		{  
			HDC hdc = (HDC)wp;  
			RECT rect;  
			GetClientRect(hWnd, &rect);  
			FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));  
			return 1;  
		}  
  
		case WM_GETMINMAXINFO:  
		{  
			lpMMI->ptMinTrackSize.x = 1300;  
			lpMMI->ptMinTrackSize.y = 700;  
			break;  
		}  
  
		case WM_SIZE:  
		{  
			POINT  pt{ GET_X_LPARAM(lp),GET_Y_LPARAM(lp) };  
			ClientToScreen(wh.SplitterWindow, &pt);  
			ScreenToClient(wh.MainWindow, &pt);  
			int newSplitterPos = pt.y;  
  
			HDWP hdwp = BeginDeferWindowPos(3);  
			DeferWindowPos(hdwp, wh.ListViewWindow, NULL, rcMain.left, rcMain.left, rcMain.right, (newSplitterPos - rcMain.bottom) - 1, SWP_NOMOVE);  
			DeferWindowPos(hdwp, wh.SplitterWindow, NULL, rcMain.left, (newSplitterPos - rcMain.bottom) - 1, rcMain.right, 17, SWP_NOMOVE);  
			DeferWindowPos(hdwp, wh.TabMainWindow, NULL, rcMain.left, (newSplitterPos - rcMain.bottom) + 17, rcMain.right, rcMain.bottom - (rcListView.bottom + 22), SWP_NOMOVE);  
			EndDeferWindowPos(hdwp);  
  
			MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom - (rcListView.bottom + 52), TRUE);  
		  
			ListView_SetColumnWidth(wh.ListViewWindow, 1, LVSCW_AUTOSIZE_USEHEADER);  
			SetWindowText(wh.SplitterWindow, L"...");  
			return 0;  
		}  
	}  
	return DefWindowProcW(hWnd, msg, wp, lp);  
}  
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,865 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,483 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,600 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Castorix31 82,501 Reputation points
    2021-09-07T14:01:11.607+00:00

    The "child " controls in a Tab control must not be child of the Tab control, but of the main window

    I did a few changes and it seems to work correctly =>

    #include <Windows.h>
    #include <commctrl.h>
    #include <windowsx.h>
    #include <process.h>
    #include <iostream>
    #include <Uxtheme.h>
    
    struct _WINDOW_HANDLES
    {
        HWND MainWindow;
        HWND ListViewWindow;
        HWND SplitterWindow;
    
        HWND TabMainWindow;
        HWND TabChildWindow;
    
    } wh;
    
    HINSTANCE ghInst;
    
    LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK SplitterProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    
    LRESULT CALLBACK TabMainProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    
    LRESULT CALLBACK TabChildWindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    
    static WNDPROC SplitterWndProc;
    
    static WNDPROC TabMainWndProc;
    static WNDPROC TabChildWndProc;
    
    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)
    {
        WNDCLASSW wc;
        memset(&wc, 0, sizeof(WNDCLASSW));
        wc.hbrBackground = NULL;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hInstance = hInst;
        wc.lpszClassName = L"MainWindowClass";
        wc.lpfnWndProc = WindowProcedure;
    
        if (!RegisterClassW(&wc))
        {
            return -1;
        }
    
        //wh.MainWindow = CreateWindowExW(WS_EX_COMPOSITED, L"MainWindowClass", L"GUI", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1300, 700, NULL, NULL, hInst, NULL);
        wh.MainWindow = CreateWindowExW(0, L"MainWindowClass", L"GUI", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1300, 700, NULL, NULL, hInst, NULL);
        ShowWindow(wh.MainWindow, 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.ListViewWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, rcMain.right, 265, hWnd, (HMENU)0, ghInst, NULL);
        ListView_SetExtendedListViewStyle(wh.ListViewWindow, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER);
    
        SendMessage(wh.ListViewWindow, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0);
    
        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.ListViewWindow, 0, &lvc);
    
        lvc.iSubItem = 1;
        lvc.cx = 125;
        lvc.pszText = (LPWSTR)L"Column 2";
        ListView_InsertColumn(wh.ListViewWindow, 1, &lvc);
    
        LVITEM lvi;
        memset(&lvi, 0, sizeof(LVITEM));
        lvi.mask = LVIF_TEXT;
        lvi.iItem = 0;
        lvi.iSubItem = 0;
        lvi.iImage = 0;
        lvi.pszText = (LPWSTR)L"Item 1";
        ListView_InsertItem(wh.ListViewWindow, &lvi);
    
        ListView_SetItemText(wh.ListViewWindow, 0, 1, (LPWSTR)L"Item 2");
    
        wh.SplitterWindow = CreateWindowEx(NULL, WC_STATIC, L"", WS_CHILD | WS_BORDER | WS_VISIBLE | SS_NOTIFY | SS_CENTER, 0, 265, rcMain.right, 17, hWnd, NULL, ghInst, NULL);
        SplitterWndProc = (WNDPROC)SetWindowLongPtr(wh.SplitterWindow, GWLP_WNDPROC, (LONG_PTR)SplitterProcedure);
    
        LOGFONT lf;
        GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
        HFONT GeneralFont = 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);
    
        wh.TabMainWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TABCONTROL, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, rcMain.left, 283, rcMain.right, 378, hWnd, NULL, ghInst, NULL);
        //TabMainWndProc = (WNDPROC)SetWindowLongPtr(wh.TabMainWindow, GWLP_WNDPROC, (LONG_PTR)TabMainProcedure);
        SendMessage(wh.TabMainWindow, WM_SETFONT, (WPARAM)GeneralFont, TRUE);
    
        TCITEM tie;
        tie.mask = TCIF_TEXT;
        tie.iImage = 0;
        tie.pszText = (LPWSTR)L"Tab";
        TabCtrl_InsertItem(wh.TabMainWindow, 0, &tie);
    
        //wh.TabChildWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | ES_MULTILINE | ES_WANTRETURN, rcMain.left, 25, rcMain.right, 348, wh.TabMainWindow, NULL, ghInst, NULL);
        wh.TabChildWindow = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | ES_MULTILINE | ES_WANTRETURN, rcMain.left, 25, rcMain.right, 348, hWnd, NULL, ghInst, NULL);
        //TabChildWndProc = (WNDPROC)SetWindowLongPtr(wh.TabChildWindow, GWLP_WNDPROC, (LONG_PTR)TabChildWindowProcedure);
        SendMessage(wh.TabChildWindow, WM_SETFONT, (WPARAM)GeneralFont, TRUE);
    }
    
    LRESULT CALLBACK SplitterProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static BOOL bSplitterMoving;
    
        RECT rcMain;
        GetClientRect(wh.MainWindow, &rcMain);
    
        switch (message)
        {
        case WM_SETCURSOR:
        {
            SetCursor(LoadCursor(NULL, IDC_SIZENS));
            SetWindowLongPtr(hWnd, DWLP_MSGRESULT, TRUE);
            return TRUE;
        }
    
        case WM_LBUTTONDOWN:
        {
            bSplitterMoving = TRUE;
            SetCapture(wh.SplitterWindow);
            return 0;
        }
    
        case WM_LBUTTONUP:
        {
            ReleaseCapture();
            bSplitterMoving = FALSE;
            return 0;
        }
    
        case WM_MOUSEMOVE:
        {
            if (bSplitterMoving)
            {
                POINT  pt{ GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam) };
                ClientToScreen(wh.SplitterWindow, &pt);
                ScreenToClient(wh.MainWindow, &pt);
    
                auto newSplitterPos = pt.y;
                if (newSplitterPos <= 105 || newSplitterPos >= 265)
                {
                    return 0;
                }
    
                else
                {
                    HDWP hdwp = BeginDeferWindowPos(4);
    
                    DeferWindowPos(hdwp, wh.ListViewWindow, NULL, rcMain.left, rcMain.left, rcMain.right, newSplitterPos, NULL);
                    DeferWindowPos(hdwp, wh.SplitterWindow, NULL, rcMain.left, newSplitterPos, rcMain.right, 17, NULL);
                    DeferWindowPos(hdwp, wh.TabMainWindow, NULL, rcMain.left, newSplitterPos + 18, rcMain.right, rcMain.bottom - (newSplitterPos + 18), NULL);
                    RECT rcTab;
                    SetRect(&rcTab, rcMain.left, newSplitterPos + 18, rcMain.right, rcMain.bottom - rcMain.top);
                    TabCtrl_AdjustRect(wh.TabMainWindow, FALSE, &rcTab);
                    DeferWindowPos(hdwp,
                        wh.TabChildWindow, HWND_TOP, rcTab.left, rcTab.top,
                        rcTab.right - rcTab.left, rcTab.bottom - rcTab.top, 0
                    );
                    EndDeferWindowPos(hdwp);  
    
                    //MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom - (newSplitterPos + 48), TRUE);
    
                    //UpdateWindow(wh.ListViewWindow);
                    // UpdateWindow(wh.SplitterWindow);
                   //  UpdateWindow(wh.TabMainWindow);
                }
                return 0;
            }
        }
        }
        return CallWindowProc(SplitterWndProc, hWnd, message, wParam, lParam);
    }
    
    LRESULT CALLBACK TabMainProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            PAINTSTRUCT ps;
            RECT rc;
            HDC hdc, hdcMem;
            HBITMAP hbmMem, hbmOld;
    
        case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            GetClientRect(hWnd, &rc);
            hdcMem = CreateCompatibleDC(hdc);
            hbmMem = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);
            hbmOld = ((HBITMAP)SelectObject(hdcMem, hbmMem));
            FillRect(hdcMem, &rc, (HBRUSH)GetSysColorBrush(COLOR_3DFACE));
            CallWindowProc(TabMainWndProc, hWnd, message, ((WPARAM)hdcMem), lParam);
            BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMem, 0, 0, SRCCOPY);
            SelectObject(hdcMem, hbmOld);
            DeleteObject(hbmMem);
            DeleteDC(hdcMem);
            EndPaint(hWnd, &ps);
    
            return 0;
        }
    
        case WM_ERASEBKGND:
        {
            return (LRESULT)1;
        }
    
        case WM_CTLCOLORSTATIC:
        {
    
            HDC hdcStatic = (HDC)wParam;
            SetBkColor(hdcStatic, RGB(0, 0, 0));
            return (LRESULT)GetStockObject(BLACK_BRUSH);
    
        }
        }
    
        return CallWindowProc(TabMainWndProc, hWnd, message, wParam, lParam);
    }
    
    LRESULT CALLBACK TabChildWindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            PAINTSTRUCT ps;
            RECT rc;
            HDC hdc, hdcMem;
            HBITMAP hbmMem, hbmOld;
    
        case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            GetClientRect(hWnd, &rc);
            hdcMem = CreateCompatibleDC(hdc);
            hbmMem = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);
            hbmOld = ((HBITMAP)SelectObject(hdcMem, hbmMem));
            FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
            CallWindowProc(TabChildWndProc, hWnd, message, ((WPARAM)hdcMem), lParam);
            BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMem, 0, 0, SRCCOPY);
            SelectObject(hdcMem, hbmOld);
            DeleteObject(hbmMem);
            DeleteDC(hdcMem);
            EndPaint(hWnd, &ps);
    
            return 0;
        }
    
        case WM_ERASEBKGND:
        {
            return (LRESULT)1;
        }
        }
    
        return CallWindowProc(TabChildWndProc, hWnd, message, wParam, lParam);
    }
    
    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
    {
        int newSplitterPos = 0;
        LPMINMAXINFO lpMMI = (LPMINMAXINFO)lp;
    
        RECT rcMain, rcListView;
        GetClientRect(hWnd, &rcMain);
        GetClientRect(wh.ListViewWindow, &rcListView);
    
        HMENU hMenu;
    
        switch (msg)
        {
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
        case WM_CREATE:
        {
            InitializeComponent(hWnd);
            return 0;
        }
        //case WM_ERASEBKGND:
        //{
        //    HDC hdc = (HDC)wp;
        //    RECT rect;
        //    GetClientRect(hWnd, &rect);
        //    FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
        //    return 1;
        //}
        case WM_ERASEBKGND:
        {  
            return 1;
        }
    
        case WM_GETMINMAXINFO:
        {
            lpMMI->ptMinTrackSize.x = 1300;
            lpMMI->ptMinTrackSize.y = 700;
            break;
        }
        // For Read-Only Edit control
        case WM_CTLCOLORSTATIC:
        {
            if (lp == (LPARAM)wh.TabChildWindow)
            {
                HDC hdcStatic = (HDC)wp;
                SetBkColor(hdcStatic, RGB(0, 0, 0));
                return (LRESULT)GetStockObject(BLACK_BRUSH);
            }
        }
        break;
        case WM_SIZE:
        {
            POINT  pt{ GET_X_LPARAM(lp),GET_Y_LPARAM(lp) };
            ClientToScreen(wh.SplitterWindow, &pt);
            ScreenToClient(wh.MainWindow, &pt);
            newSplitterPos = pt.y;
    
            HDWP hdwp = BeginDeferWindowPos(4);
            DeferWindowPos(hdwp, wh.ListViewWindow, NULL, rcMain.left, rcMain.left, rcMain.right, (newSplitterPos - rcMain.bottom) - 1, SWP_NOMOVE);
            DeferWindowPos(hdwp, wh.SplitterWindow, NULL, rcMain.left, (newSplitterPos - rcMain.bottom) - 1, rcMain.right, 17, SWP_NOMOVE);
            DeferWindowPos(hdwp, wh.TabMainWindow, NULL, rcMain.left, (newSplitterPos - rcMain.bottom) + 17, rcMain.right, rcMain.bottom - (rcListView.bottom + 22), SWP_NOMOVE);
            RECT rcTab;
            SetRect(&rcTab, rcMain.left, (newSplitterPos - rcMain.bottom) + 17, rcMain.right, rcMain.bottom - rcMain.top);
            TabCtrl_AdjustRect(wh.TabMainWindow, FALSE, &rcTab);
            DeferWindowPos(hdwp,
                wh.TabChildWindow, HWND_TOP, rcTab.left, rcTab.top,
                rcTab.right - rcTab.left, rcTab.bottom - rcTab.top, 0
            );
            EndDeferWindowPos(hdwp);
            //MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom - (rcListView.bottom + 52), TRUE);
    
            ListView_SetColumnWidth(wh.ListViewWindow, 1, LVSCW_AUTOSIZE_USEHEADER);
            SetWindowText(wh.SplitterWindow, L"...");
            return 0;
        }
        }
        return DefWindowProcW(hWnd, msg, wp, lp);
    }
    
    1 person found this answer helpful.
    0 comments No comments

  2. Xiaopo Yang - MSFT 12,066 Reputation points Microsoft Vendor
    2021-09-06T09:52:02.447+00:00

    When I change the 178 line, MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom - (newSplitterPos + 48), TRUE); , to MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom, TRUE);, the bounce\shake is disappeared.
    MoveWindow reference.


  3. Xiaopo Yang - MSFT 12,066 Reputation points Microsoft Vendor
    2021-09-16T03:15:07.1+00:00

    After researching, we found that using SWP_NOREDRAW when moving wh.TabMainWindow will also address the issue:

                HDWP hdwp = BeginDeferWindowPos(3);
    
                DeferWindowPos(hdwp, wh.ListViewWindow, NULL, rcMain.left, rcMain.left, rcMain.right, newSplitterPos, NULL);
                DeferWindowPos(hdwp, wh.SplitterWindow, NULL, rcMain.left, newSplitterPos, rcMain.right, 17, NULL);
                DeferWindowPos(hdwp, wh.TabMainWindow, NULL, rcMain.left, newSplitterPos + 18, rcMain.right, rcMain.bottom - (newSplitterPos + 18), SWP_NOREDRAW);
                EndDeferWindowPos(hdwp);
    
                MoveWindow(wh.TabChildWindow, rcMain.left, 25, rcMain.right, rcMain.bottom - (newSplitterPos + 48), TRUE);
    
                RedrawWindow(wh.TabMainWindow, nullptr, nullptr, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
                RedrawWindow(wh.MainWindow, nullptr, nullptr, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
    
                UpdateWindow(wh.ListViewWindow);
                UpdateWindow(wh.SplitterWindow);
    

    SWP_NOREDRAW prevents the redrawing of the edit control.
    RedrawWindow(wh.TabMainWindow,…) to have the tab control repaint including its non-client area. Without it, the area not drawn due to SWP_NOREDRAW will not be repainted.
    RedrawWindow(wh.MainWindow,…) to have the main window repaint with WM_ERASEBKGND. Without it, the area not drawn due to SWP_NOREDRAW will not be repainted. This is not needed if the child controls completely cover the main window, but that is not the case with the code.

    0 comments No comments