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);  
}  
Developer technologies | Windows Forms
Windows development | Windows API - Win32
Developer technologies | C++
{count} votes

3 answers

Sort by: Most helpful
  1. Castorix31 90,686 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,731 Reputation points Microsoft External Staff
    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,731 Reputation points Microsoft External Staff
    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

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.