Giter VIP home page Giter VIP logo

Comments (4)

Bringer-of-Light avatar Bringer-of-Light commented on June 2, 2024

@jiakuan I believe you can show these system menu using shortcut "Alt+Space". But I‘m not sure how to add the same support using mouse right click.

from qt-nice-frameless-window.

pzhlkj6612 avatar pzhlkj6612 commented on June 2, 2024

Hi there!

When we click the top left corner of a standard application window, it normally shows a system menu like this:
...

... But I‘m not sure how to add the same support using mouse right click.

I think the OP was talking about the menu displayed when we left click the top left corner.

from qt-nice-frameless-window.

LochlanPerry-Scott avatar LochlanPerry-Scott commented on June 2, 2024

Howdy All.
@jiakuan @Bringer-of-Light

Here is my findings on this one.
Looking at the General WinAPI For Custom Framing, there looks to be a message case called WM_NCRBUTTONDOWN.
using this allows us to receive a Right click when working in the window.

As a simple example of using this could be

// End case WM_NCHITTEST
case WM_NCRBUTTONDOWN:
{
	// Get Mouse pos
	long x = GET_X_LPARAM(msg->lParam);
	long y = GET_Y_LPARAM(msg->lParam);
	
	// Support highdpi
	double dpr = this->devicePixelRatioF();
	QPoint pos = m_titlebar->mapFromGlobal(QPoint(x / dpr, y / dpr));
	
	// Is the mouse within the titlebar pos?
	if (!m_titlebar->rect().contains(pos))
	    return false;
	
	// Get Win Handle
	HWND pHndl = HWND(winId());
	// Get SysMenu handle
	HMENU pSysMenu = ::GetSystemMenu(pHndl, FALSE);
	
	// If it exists
	if (pSysMenu)
	{
		// Open the system menu, Aligning menu to the top left corner, at mouse pos.
		TrackPopupMenu(pSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, x, y, NULL, pHndl, 0);
	}
	return false;
}

This is a simple Case and does not support the MenuControls such as 'Close' or other functions.
This also has a bug that allows the user to display the menu even when in resize area.

Fixing this bug should be a simple fix but requires more editing of the already implamented functions.
Adding in a bool m_bInBorder and setting this bool to true when the Cursor changes,
Then setting the bool back to false when not changing the Cursor can fix this issue.

i.e.

//top border
if (y >= winrect.top && y < winrect.top + border_width)
{
	m_bInBorder = true;
	*result = HTTOP;
}

with this we can now check to see if the cursor is 'm_bInBorder'.
And if it is NOT we can continue to process the above, like so:

//end case WM_NCHITTEST
case WM_NCRBUTTONDOWN:
{
	// Check if the mouse is NOT within the Resize area.
	if (!m_bInBorder)
	{
		// Get Mouse pos
		long x = GET_X_LPARAM(msg->lParam);
		long y = GET_Y_LPARAM(msg->lParam);
		
		// Support highdpi - Needed for determining the pos of mouse, reletive to the dpi/monitor.
		double dpr = this->devicePixelRatioF();
		QPoint pos = m_titlebar->mapFromGlobal(QPoint(x / dpr, y / dpr));
	
		// Is the mouse within the titlebar pos?
		if (!m_titlebar->rect().contains(pos))
			return false;
	
		// Get Win Handle
		HWND pHndl = HWND(winId());
		// Get SysMenu handle
		HMENU pSysMenu = ::GetSystemMenu(pHndl, FALSE);
	
		// If it exists
		if (pSysMenu)
		{
			// Open the system menu, Aligning menu to the top left corner, at mouse pos (dpi not included here).
			TrackPopupMenu(pSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, x, y, NULL, pHndl, 0);
		}
		return false;
	}
}

Now all that is needed is to connect the Functions of the Menu..
This is a bit of a tougher case.

It looks like I was able to find a Solution for the SysMenu buttons too, after a bit of digging.
Following along with the WinAPI it looks like the message Case WM_COMMAND is the message used to receive the menuInputs.
Filtering the wParam of this message will determine the case used.
For Example, adding the below under the above code will allow you to 'Close' the Popup Dialog and Debug print to console.

//end case WM_NCRBUTTONDOWN
case WM_COMMAND:     // "Sent when the user selects a command item from a menu" - https://learn.microsoft.com/en-us/windows/win32/menurc/wm-command
{
	// Check if the wParam is the Close Param
	if (msg->wParam == SC_CLOSE)
	{
		// If so Debug and Close Popup.
		qDebug() << "Test";
		::EndDialog(HWND(winId()), TRUE);
		return false;
	}
}

From here you can simply close the Widget Window itself.
There may be a need to do further troubleshooting on this as I have not fully tested the menu Functions.
Like for instance it seems the 'Restore' button has issues with detecting if fullscreen or not, but this can be fixed by troubleshooting.

More info can be found via:
https://learn.microsoft.com/en-us/windows/win32/menurc/wm-syscommand
https://learn.microsoft.com/en-us/windows/win32/dwm/customframe#appendix-c-hittestnca-function

I hope this helps anyone that comes across this :)

from qt-nice-frameless-window.

LochlanPerry-Scott avatar LochlanPerry-Scott commented on June 2, 2024

@jiakuan
If you wish to make the prompt appear when selecting an Icon or Button then just place the before mentioned code into a button signal.
Just make sure this is OS dependent.

from qt-nice-frameless-window.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.