none
Creating a window on the title bar produces strange results RRS feed

  • Question

  • Hi,

    I am currently trying to create a toolbar that looks like a menu and place it on the title bar/caption using an extended frame but for some reason drawing in the non-client area (which became the client area by extending) produces strange results. The label text is white and system button seem to have a strange dash coming from the toolbar window. There is no way to even see the menu items unless you highlight them by moving the cursor over them. (See screenshot below)

    MainMenu.cpp:

    VOID MainMenu::wCreate(HWND wMainWindow) {
    // CREATE MENU HOST

    WNDCLASS wc = { };

    wc.lpszClassName = L"MainMenuHost";
    wc.lpfnWndProc = DefWindowProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hbrBackground = GetStockBrush(BLACK_BRUSH);
    wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
    RegisterClass(&wc);

    HWND wMainMenuHost = CreateWindowEx(NULL,L"MainMenuHost", NULL, WS_CHILD | WS_VISIBLE,
    38, 
    0.6 * GetSystemMetrics(SM_CYCAPTION),
    GetSystemMetrics(SM_CXMAXIMIZED), 
    GetSystemMetrics(SM_CYMENU),
    wMainWindow, NULL, GetInstanceModule(NULL), NULL);

    HRESULT hr = GetLastError();
    // CREATE MENU
    HWND wMainMenu = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
    WS_CHILD | /*TBSTYLE_WRAPABLE |*/ TBSTYLE_FLAT | TBSTYLE_LIST,
    NULL, NULL, NULL, GetSystemMetrics(SM_CYMENU),
    wMainMenuHost, NULL, GetInstanceModule(NULL), NULL);

    TCHAR fileButtonS1[] = _T("File");
    TCHAR fileButtonS2[] = _T("Edit");
    TBBUTTON fileButton[] = { {I_IMAGENONE, NULL, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)fileButtonS1},
    {I_IMAGENONE, NULL, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)fileButtonS2} };
    SendMessage(wMainMenu, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessage(wMainMenu, TB_ADDBUTTONS, (WPARAM)2, (LPARAM)&fileButton);
    ShowWindow(wMainMenu, SW_SHOW);

    hr = GetLastError();

    }

    MainWindow.cpp Procedure:


    LRESULT CALLBACK MainWindow::wProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){

    struct metrics m;
    BOOL dwmHandled;
    LRESULT lResult;

    dwmHandled = DwmDefWindowProc(hwnd, uMsg, wParam, lParam, &lResult);
    getMetrics(&m, hwnd);

    switch (uMsg) {
    case WM_CREATE:
    {
    SetWindowPos(hwnd, NULL,
    m.windowRect.left, m.windowRect.top,
    m.windowRect.right - m.windowRect.left, m.windowRect.bottom - m.windowRect.top,
    SWP_FRAMECHANGED);
    MainMenu::wCreate(hwnd);  // <- Fuct
    break;
    }

    case WM_ACTIVATE:
    DwmExtendFrameIntoClientArea(hwnd, &(m.realNonclientInsets));
    break;

    case WM_NCCALCSIZE:
    {
    NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);

    pncsp->rgrc[0].left = pncsp->rgrc[0].left + 0;
    pncsp->rgrc[0].top = pncsp->rgrc[0].top + 0;
    pncsp->rgrc[0].right = pncsp->rgrc[0].right - 0;
    pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - 0;

    lResult = 0;

    // No need to pass the message on to the DefWindowProc.
    dwmHandled = true;

    }

    case WM_NCHITTEST:
    if (dwmHandled)
    return lResult;

    if (defWindowProcFirst) {
    lResult = DefWindowProcW(hwnd, uMsg, wParam, lParam);
    if (lResult != HTCLIENT) {
    return lResult;
    }
    }
    {
    POINT p;

    p.x = GET_X_LPARAM(lParam);
    p.y = GET_Y_LPARAM(lParam);

    lResult = HTNOWHERE;
    if (p.y >= m.windowRect.top && p.y < (m.windowRect.top + m.resizeFrameInsets.cyTopHeight))
    lResult = HTTOP;
    else if (p.y >= m.effectiveClientRect.bottom && p.y < m.windowRect.bottom)
    lResult = HTBOTTOM;

    if (p.x >= m.windowRect.left && p.x < m.effectiveClientRect.left)
    switch (lResult) {
    case HTNOWHERE:
    lResult = HTLEFT;
    break;
    case HT"white-space:pre;">lResult = HTTOPLEFT;
    break;
    case HTBOTTOM:
    lResult = HTBOTTOMLEFT;
    break;
    }
    else if (p.x >= m.effectiveClientRect.right && p.x < m.windowRect.right)
    switch (lResult) {
    case HTNOWHERE:
    lResult = HTRIGHT;
    break;
    case HT"white-space:pre;">lResult = HTTOPRIGHT;
    break;
    case HTBOTTOM:
    lResult = HTBOTTOMRIGHT;
    break;
    }

    if (lResult == HTNOWHERE)
    if (p.y >= (m.windowRect.top + m.resizeFrameInsets.cyTopHeight) && p.y < m.effectiveClientRect.top)
    lResult = HTCAPTION;
    if (lResult != HTNOWHERE)
    return lResult;
    }

    break;

    case WM_SIZE:
    InvalidateRect(hwnd, &(m.relativeClientRect), FALSE);
    break;

    case WM_PAINT:
    {
    break;
    }

    case WM_CLOSE:
    PostQuitMessage(0);
    break;
    }

    if (dwmHandled)
    return lResult;
    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
    }

    Thank you.

    Sunday, September 8, 2019 9:23 AM

All replies

  • A way to get right colors is to use a Layered Toolbar (WS_EX_LAYERED),

    but it needs a Manifest (Layered child controls for Windows >=8) 

    You can also draw in Custom Draw notifications (NM_CUSTOMDRAW)

    A test where I used both (Manifest + changing colors of second button (Blue on Red background) in CDDS_ITEMPREPAINT) =>

    Sunday, September 8, 2019 1:52 PM
  • Hello,

    Thank you for posting here.

    Your code seems to be only part of the complete. I'm sorry I can't reproduce your issue, and I can't see the cause of that line in the code. Could you provide a demo which can reproduce this issue?

    Best Regards,

    Suarez Zhou

    Monday, September 9, 2019 7:02 AM
  • Hello,

    I noticed that you used WM_NCHITTEST message. Why not delete the title bar and draw the system button on client area, then use WM_NCHITTEST to tell system that the top part is title bar. I think do these on client area will be more easy, and also can avoid your issue.

    Best Regards,

    Suarez Zhou

    Monday, September 9, 2019 7:26 AM
  • @Castorix31 The target is Windows 7+ so using WS_EX_LAYERED is not an option unfortunately. Custom drawing might do the trick but I don't have any experience with it. Does custom drawing also handle hover color?

    @Suarez-Zhou I don't want to mess with the title bar in any way, that's why. Plus drawing the system buttons is super hackish and looks ugly.

    Thanks for the replies.

    Monday, September 9, 2019 9:11 PM
  • Custom drawing might do the trick but I don't have any experience with it. Does custom drawing also handle hover color?

    Yes, with uItemState & CDIS_HOT

    (I had to use a 32-bpp DIB section (CreateDIBSection) + GDIPlus (Graphics::FillRectangle for example) to get right colors without a Manifest)


    • Edited by Castorix31 Tuesday, September 10, 2019 8:41 AM
    Tuesday, September 10, 2019 8:34 AM
  • @Castorix31 I did some research for the past two days about custom drawing it only made me more confused. There is no sample code of the WM_NOTIFY procedure anywhere for me to see what's going on. The only thing I want is actually set the text color to black instead of white and maybe modify the hover color.

    I know I'm asking stupid questions but what is the difference between owner-drawn and custom-drawn controls? I read that owner-drawing means drawing everything and custom-drawing means drawing only the things that you want to add/replace.

    Is owner drawing available for the toolbar buttons? Also are toolbar buttons and regular buttons the same class (do they send the same notifications)? If so can't I just handle the BN_PAINT message and set the text color to black?

    When custom drawing do I need to signal the toolbar via a style that it is custom-drawn or do I just  need to handle the message in the procedure?

    Should I do it via GDI's SetTextColor or via NNTBCUSTOMDRAW's clrText in pre-paint stage?

    Did I mention I have no experience with custom drawing? :))

    Thanks a lot.

    Thursday, September 12, 2019 8:48 PM
  • Custom Draw is explained in MSDN : About Custom Draw

    You can redraw just some parts, draw everything (return CDRF_SKIPDEFAULT), or also draw over the default drawing (in CDDS_ITEMPOSTPAINT)


    • Edited by Castorix31 Saturday, September 14, 2019 1:22 PM
    Saturday, September 14, 2019 1:22 PM
  • @Castorix31 Ok, I think I got something. By using a recycled MSDN function and setting the Toolbar Extended Style to TBSTYLE_EX_MIXEDBUTTONS (which means "don't show labels") I managed to paint the first menu.


    The first problem is the menu is kind of buggy and sometimes it will appear focused, sometimes don't. The second problem is it appears to only paint the first menu (it should paint "File" on every menu item).

    Anyways setting the host's background to black and changing the BitBlt flag to SRCPAINT seems to do the trick for the focus problem, but I want the host's background to be none.

    Can you please review my code and give me some suggestions?

    Also is there any way to get the menu text not to paint in a custom paint kind of way instead of using TBSTYLE_EX_MIXEDBUTTONS? The problem with this flag is that it makes all the buttons the same size regardless of the text.

    Here's my WM_NOTIFY:

    case WM_NOTIFY:
    
    if (((LPNMHDR)lParam)->code == NM_CUSTOMDRAW) {
    LPNMTBCUSTOMDRAW toolbarDraw = (LPNMTBCUSTOMDRAW)lParam;
    
    switch (toolbarDraw->nmcd.dwDrawStage) {
    
    case CDDS_PREPAINT:
    return CDRF_NOTIFYITEMDRAW;
    
    case CDDS_ITEMPREPAINT:
    toolbarDraw->nmcd.rc.bottom = GetSystemMetrics(SM_CYMENU);
    toolbarDraw->rcText = toolbarDraw->nmcd.rc;
    wPaintMenu(toolbarDraw->nmcd.hdc, toolbarDraw->rcText);
    
    return CDRF_DODEFAULT;
    }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);

    And here's the function:

    VOID MainMenu::wPaintMenu(HDC hdc, RECT rect){
    
    HTHEME hTheme = OpenThemeData(NULL, L"WINDOW");
    HDC hdcPaint = CreateCompatibleDC(hdc);
    int cx = RECTWIDTH(rect);
    int cy = RECTHEIGHT(rect);
    
    BITMAPINFO dib = { 0 };
    dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    dib.bmiHeader.biWidth = cx;
    dib.bmiHeader.biHeight = -cy;
    dib.bmiHeader.biPlanes = 1;
    dib.bmiHeader.biBitCount = 32;
    dib.bmiHeader.biCompression = BI_RGB;
    HBITMAP hbm = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcPaint, hbm);
    
    // Setting any kind of flag here doesn't seem to make any difference. I could just pass NULL.
    DTTOPTS DttOpts = { sizeof(DTTOPTS) }; 
    DttOpts.dwFlags = DTT_COMPOSITED;
    
    LOGFONT lgFont;
    HFONT hFontOld = NULL;
    GetThemeSysFont(hTheme, 803, &lgFont); // 803 = TMT_MENU
    HFONT hFont = CreateFontIndirect(&lgFont);
    hFontOld = (HFONT)SelectObject(hdcPaint, hFont);
    
    DrawThemeTextEx(hTheme,
    hdcPaint,
    0, 0,
    L"&File",
    -1,
    DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_WORD_ELLIPSIS | DT_NOCLIP,
    &rect,
    &DttOpts); //Again, I could just pass NULL.
    
    BitBlt(hdc, 0, 0, cx, cy, hdcPaint, 0, 0, SRCCOPY); //This flag seems to work the best. The others behave strangely.
    
    DeleteObject(hbm);
    DeleteDC(hdcPaint);
    CloseThemeData(hTheme);
    }

    Thanks a lot.




    • Edited by Artimonier Thursday, September 19, 2019 7:43 AM
    Thursday, September 19, 2019 6:51 AM
  • I did a simplified test with "Button" theme (based on DWM MSDN code) =>

    #include <Windowsx.h>
    #include <windows.h>
    #include <tchar.h>
    
    #include <dwmapi.h>
    #pragma comment(lib,"Dwmapi")
    
    #include <commctrl.h>
    #pragma comment(lib, "comctl32")
    
    #include <uxtheme.h>
    #pragma comment(lib, "uxtheme")
    
    //#include <gdiplus.h>
    //using namespace Gdiplus;
    //#pragma comment(lib, "Gdiplus")
    
    #include <vssym32.h>
    
    #pragma comment(linker,"\"/manifestdependency:type='win32' \
    name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
    processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    
    // https://docs.microsoft.com/en-us/windows/desktop/dwm/customframe
    
    HINSTANCE hInst;
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int nWidth = 600, nHeight = 400;
    #define IDC_STATIC 10
    #define ID_TOOLBAR 11
    
    #define RECTWIDTH(rc)            (rc.right - rc.left)
    #define RECTHEIGHT(rc)            (rc.bottom - rc.top)
    
    const int TOPEXTENDWIDTH = 32;
    const int LEFTEXTENDWIDTH = 8;
    const int RIGHTEXTENDWIDTH = 8;
    const int BOTTOMEXTENDWIDTH = 8;
    
    LRESULT HitTestNCA(HWND hWnd, WPARAM wParam, LPARAM lParam);
    
    #include <vector>
    #define TB_NB_BUTTONS 5
    WCHAR* const tbbString[TB_NB_BUTTONS] = { L"Copy", L"Cut", L"Paste", L"Undo", L"Redo" };
    std::vector<TBBUTTON> tbb(TB_NB_BUTTONS);
    void AddToolbarButton(HWND hToolbar, TBBUTTON& tbb, int bmp, int cmd, WCHAR* wsString, BYTE style, DWORD_PTR data, BYTE state)
    {
    	tbb.iBitmap = bmp;
    	tbb.idCommand = cmd;
    	tbb.fsStyle = style;
    	tbb.dwData = data;
    	tbb.fsState = state;
    	tbb.iString = SendMessage(hToolbar, TB_ADDSTRING, 0, (LPARAM)wsString);
    }
    
    int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
    	hInst = hInstance;
    	WNDCLASSEX wcex =
    	{
    		sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION),
    		LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), NULL, TEXT("WindowClass"), NULL,
    		//LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL,		
    	};
    	if (!RegisterClassEx(&wcex))
    		return MessageBox(NULL, L"Cannot register class !", L"Error", MB_ICONERROR | MB_OK);
    	//GdiplusStartupInput gdiplusStartupInput;
    	//ULONG_PTR           gdiplusToken;
    	//GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
    	int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;
    	HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("Test"), WS_OVERLAPPEDWINDOW, nX, nY, nWidth, nHeight, NULL, NULL, hInst, NULL);
    	if (!hWnd)
    		return MessageBox(NULL, L"Cannot create window !", L"Error", MB_ICONERROR | MB_OK);
    
    	ShowWindow(hWnd, SW_SHOWNORMAL);
    	UpdateWindow(hWnd);
    	MSG msg;
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return (int)msg.wParam;
    }
    
    LRESULT CustomCaptionProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool* pfCallDWP)
    {
    	LRESULT lRet = 0;
    	HRESULT hr = S_OK;
    	bool fCallDWP = true; // Pass on to DefWindowProc?
    	static HICON hIcon = NULL;
    	static HWND hWndToolbar = NULL;
    
    	fCallDWP = !DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
    	if (message == WM_CREATE)
    	{
    		RECT rcClient;
    		GetWindowRect(hWnd, &rcClient);
    		//// Inform the application of the frame change.
    		SetWindowPos(hWnd, NULL, rcClient.left, rcClient.top, RECTWIDTH(rcClient), RECTHEIGHT(rcClient), SWP_FRAMECHANGED);
    
    		HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, (LPWSTR)NULL,
    			WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_CUSTOMERASE
    			 | CCS_TOP | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | TBSTYLE_TRANSPARENT,
    			//	| CCS_TOP | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE,
    			10, 4, 300, 24, hWnd, (HMENU)100, (HINSTANCE)HINST_COMMCTRL, NULL);
    		SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
    		SendMessage(hWndToolbar, TB_SETIMAGELIST, 0, NULL);	
    		//SetWindowTheme(hWndToolbar, L"", L"");
    		SendMessage(hWndToolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(50, 50));
    		AddToolbarButton(hWndToolbar, tbb[0], STD_COPY, 0, tbbString[0], TBSTYLE_BUTTON, 0, TBSTATE_ENABLED);
    		AddToolbarButton(hWndToolbar, tbb[1], STD_CUT, 1, tbbString[1], TBSTYLE_BUTTON, 0, TBSTATE_ENABLED);
    		AddToolbarButton(hWndToolbar, tbb[2], STD_PASTE, 2, tbbString[2], TBSTYLE_BUTTON, 0, TBSTATE_ENABLED);
    		AddToolbarButton(hWndToolbar, tbb[3], STD_UNDO, 3, tbbString[3], TBSTYLE_BUTTON, 0, 0);
    		AddToolbarButton(hWndToolbar, tbb[4], STD_REDOW, 4, tbbString[4], TBSTYLE_BUTTON, 0, TBSTATE_ENABLED);
    		SendMessage(hWndToolbar, TB_ADDBUTTONS, (WPARAM)TB_NB_BUTTONS, (LPARAM)&tbb[0]);
    
    		SetWindowPos(hWndToolbar, NULL, 10, 4, 50 * TB_NB_BUTTONS, 24, SWP_FRAMECHANGED);
    		ShowWindow(hWndToolbar, SW_SHOWNORMAL);
    
    		fCallDWP = true;
    		lRet = 0;
    	}
    	// Handle window activation.
    	if (message == WM_ACTIVATE)
    	{
    		// Extend the frame into the client area.
    		MARGINS margins;
    		margins.cxLeftWidth = LEFTEXTENDWIDTH; 
    		margins.cxRightWidth = RIGHTEXTENDWIDTH;
    		margins.cyBottomHeight = BOTTOMEXTENDWIDTH;
    		margins.cyTopHeight = TOPEXTENDWIDTH;
    		hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
    		if (!SUCCEEDED(hr))
    		{
    			// Handle error.
    		}
    
    		fCallDWP = true;
    		lRet = 0;
    	}
    	if (message == WM_NOTIFY) 
    	{
    		LPNMHDR pnmhdr = (LPNMHDR)lParam;
    		LPNMTBCUSTOMDRAW pnmToolbar = (LPNMTBCUSTOMDRAW)lParam;
    		switch (pnmhdr->code)
    		{
    		case NM_CUSTOMDRAW:
    		{
    			LPNMTBCUSTOMDRAW pnmtb = (LPNMTBCUSTOMDRAW)pnmhdr;
    			DWORD nItem = pnmtb->nmcd.dwItemSpec;
    			if (pnmtb->nmcd.dwDrawStage == CDDS_PREPAINT)				
    				lRet = CDRF_NOTIFYITEMDRAW;
    			else if (pnmtb->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
    			{
    				HTHEME hTheme;
    				hTheme = OpenThemeData(NULL, L"Button");
    				bool bHot = pnmtb->nmcd.uItemState & CDIS_HOT;
    				bool bPressed = pnmtb->nmcd.uItemState & CDIS_SELECTED;
    				bool bDisabled = pnmtb->nmcd.uItemState & CDIS_DISABLED;
    				int nState = 0;
    				if (bHot)
    					nState |= PBS_HOT;
    				if (bPressed)
    					nState |= PBS_PRESSED;	
    				if (bDisabled)
    					nState = PBS_DISABLED;
    				DrawThemeBackground(hTheme, pnmtb->nmcd.hdc, BP_PUSHBUTTON, nState, &pnmtb->nmcd.rc, NULL);				
    				
    				DTTOPTS option = { sizeof(DTTOPTS) };
    				//option.dwFlags = DTT_COMPOSITED | DTT_GLOWSIZE | DTT_TEXTCOLOR;
    				option.dwFlags = DTT_COMPOSITED | DTT_TEXTCOLOR;
    				option.crText = RGB(0, 0, 0);
    				WCHAR wsText[255] = L"";
    				SendMessage(pnmhdr->hwndFrom, TB_GETBUTTONTEXT, (WPARAM)pnmtb->nmcd.dwItemSpec, (LPARAM)wsText);				
    				int nLenght = lstrlen(wsText);
    				if (nState == PBS_DISABLED)
    					option.crText = RGB(128, 128, 128);
    				DrawThemeTextEx(hTheme, pnmtb->nmcd.hdc, BP_PUSHBUTTON, nState, wsText, nLenght, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX, &pnmtb->nmcd.rc, &option);
    				CloseThemeData(hTheme);
    				//lRet = CDRF_NOTIFYSUBITEMDRAW | CDRF_NOTIFYPOSTPAINT;
    				lRet = CDRF_SKIPDEFAULT;
    			}
    			//else if (pnmtb->nmcd.dwDrawStage == (CDDS_SUBITEM | CDDS_ITEMPREPAINT))
    			//{
    			//	
    			//}
    		}
    		break;
    		}
    		fCallDWP = false;
    		//lRet = 0;
    	}
    
    	// Handle the non-client size message.
    	if ((message == WM_NCCALCSIZE) && (wParam == TRUE))
    	{
    		// Calculate new NCCALCSIZE_PARAMS based on custom NCA inset.
    		/*NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
    
    		pncsp->rgrc[0].left = pncsp->rgrc[0].left + 0;
    		pncsp->rgrc[0].top = pncsp->rgrc[0].top + 0;
    		pncsp->rgrc[0].right = pncsp->rgrc[0].right - 0;
    		pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - 0;*/
    
    		lRet = 0;
    		// No need to pass the message on to the DefWindowProc.
    		fCallDWP = false;
    	}
    
    	// Handle hit testing in the NCA if not handled by DwmDefWindowProc.
    	if ((message == WM_NCHITTEST) && (lRet == 0))
    	{
    		lRet = HitTestNCA(hWnd, wParam, lParam);
    
    		if (lRet != HTNOWHERE)
    		{
    			fCallDWP = false;
    		}
    	}
    	if (message == WM_DESTROY)
    		PostQuitMessage(0);
    
    	*pfCallDWP = fCallDWP;
    
    	return lRet;
    }
    
    // Hit test the frame for resizing and moving.
    LRESULT HitTestNCA(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
    	// Get the point coordinates for the hit test.
    	POINT ptMouse = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
    
    	// Get the window rectangle.
    	RECT rcWindow;
    	GetWindowRect(hWnd, &rcWindow);
    
    	// Get the frame rectangle, adjusted for the style without a caption.
    	RECT rcFrame = { 0 };
    	AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
    
    	// Determine if the hit test is for resizing. Default middle (1,1).
    	USHORT uRow = 1;
    	USHORT uCol = 1;
    	bool fOnResizeBorder = false;
    
    	// Determine if the point is at the top or bottom of the window.
    	if (ptMouse.y >= rcWindow.top && ptMouse.y < rcWindow.top + TOPEXTENDWIDTH)
    	{
    		fOnResizeBorder = (ptMouse.y < (rcWindow.top - rcFrame.top));
    		uRow = 0;
    	}
    	else if (ptMouse.y < rcWindow.bottom && ptMouse.y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
    	{
    		uRow = 2;
    	}
    
    	// Determine if the point is at the left or right of the window.
    	if (ptMouse.x >= rcWindow.left && ptMouse.x < rcWindow.left + LEFTEXTENDWIDTH)
    	{
    		uCol = 0; // left side
    	}
    	else if (ptMouse.x < rcWindow.right && ptMouse.x >= rcWindow.right - RIGHTEXTENDWIDTH)
    	{
    		uCol = 2; // right side
    	}
    
    	// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
    	LRESULT hitTests[3][3] =
    	{
    		{ HTTOPLEFT,    fOnResizeBorder ? HTTOP : HTCAPTION,    HTTOPRIGHT },
    		{ HTLEFT,       HTNOWHERE,     HTRIGHT },
    		{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
    	};
    
    	return hitTests[uRow][uCol];
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	bool fCallDWP = true;
    	BOOL fDwmEnabled = FALSE;
    	LRESULT lRet = 0;
    	HRESULT hr = S_OK;
    
    	// Winproc worker for custom frame issues.
    	hr = DwmIsCompositionEnabled(&fDwmEnabled);
    	if (SUCCEEDED(hr))
    	{
    		lRet = CustomCaptionProc(hWnd, message, wParam, lParam, &fCallDWP);
    	}
    
    	// Winproc worker for the rest of the application.
    	if (fCallDWP)
    	{
    		//	lRet = AppWinProc(hWnd, message, wParam, lParam);
    		lRet = DefWindowProc(hWnd, message, wParam, lParam);
    	}
    	return lRet;
    }
    
    

    • Proposed as answer by Seetharam Friday, September 27, 2019 1:15 PM
    Thursday, September 19, 2019 8:58 AM
  • @Castorix31 You are a gem! Thank you.
    Friday, September 27, 2019 7:36 AM
  • Hello

    If your issue is solved, please "Mark as answer" or "Vote as helpful" post to the appropriate answer , so that it will help other members to find solution quickly if they faces similar issue.

    Best Regards,

    Suarez Zhou

    Monday, October 7, 2019 6:34 AM