How to make Qt app visible on top on all screens? - macos

How can I make a Qt window (keyboard launcher) show up on all spaces like e.g. Spotlight or iterm2 hotkey window.
I need to achieve the following: The launcher window has to be able to show up on every screen, even full screen apps, no dock item, not window switcher item, no main menu, this should work without any further implications (see below). Nice to have would be if the settings window would be still a regular window.
I tried to use qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "1"); but using this the window accepts no keyboard input anymore. I also tried
WId windowObject = this->winId();
objc_object * nsviewObject = reinterpret_cast<objc_object *>(windowObject);
objc_object * nsWindowObject = ((objc_object* (*)(id, SEL))objc_msgSend)(nsviewObject, sel_registerName("window"));
int NSWindowCollectionBehaviorMoveToActiveSpace = 1 << 1;
int NSWindowCollectionBehaviorTransient = 1 << 3;
int NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8;
int total = NSWindowCollectionBehaviorMoveToActiveSpace
|NSWindowCollectionBehaviorTransient
| NSWindowCollectionBehaviorFullScreenAuxiliary;
((objc_object* (*)(id, SEL, int))objc_msgSend)(nsWindowObject, sel_registerName("setCollectionBehavior:"), total);
but this way the window does not show over fullscreen apps and also has still a dock item and main menu.

Related

PyQt5 control windows

In the above imange the background window is the main window of the screen. Then follows one Form that opens from the menu of the Main Window
and at the top you can see a QMessageBox like this:
box = QMessageBox()
box.setIcon(QMessageBox.Question)
box.setWindowTitle('Αποθήκευση αλλαγών')
box.setText('Θέλετε να αποθηκεύσετε τις αλλαγές σας;')
box.setStandardButtons(QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
buttonY = box.button(QMessageBox.Yes)
buttonY.setText('Ναι')
buttonN = box.button(QMessageBox.No)
buttonN.setText('Οχι')
buttonC = box.button(QMessageBox.Cancel)
buttonC.setText('Ακύρωση')
box.exec_()
if box.clickedButton() == buttonY:
self.save_and_close(True)
self.main_self.manage_microphone_window_is_open = False
event.accept()
elif box.clickedButton() == buttonN:
self.main_self.manage_microphone_window_is_open = False
event.accept()
elif box.clickedButton() == buttonC:
event.ignore()
I want in the bottom the Windows (bottom bottom there that start menu of windows and clock are) to show only one program.
Any ideas?
With the help of musicmante i did the following:
I change Form Window to QDialog and set MainWindow as parent
I set a parent to box: box = QMessageBox(dlg)
Note than in step 1 when you copy paste the QWidgets from Form to new Dialog (in QtDesigner), you may change the title of window the icon of window the style of the window and perhaps any other window settings.

UWP app with multiple views with different sizes

I have a UWP app. I want to be ale to create new windows from the app, but any subsequent window needs to be a specific smaller size compared to the main window. I don't do anything with regards to sizing the main window and let the OS take care of sizing it for me.
I bring up a new window like this:
auto window = CoreApplication::CreateNewView();
window->show();
void NewWindow::show() {
auto currView = ApplicationView::GetForCurrentView();
currView->PreferredLaunchViewSize =
Windows::Foundation::Size(float(options.width), float(options.height));
currView->PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize;
currView->SetPreferredMinSize(Size(20,20));
Xaml::Window::Current->Activate();
ApplicationViewSwitcher::TryShowAsStandaloneAsync(
window_->id(),
ViewSizePreference::Default,
window_->parentId(),
ViewSizePreference::Default);
}
When the main window comes up, it comes up just fine. When I click on a button which gets to this function, the new window comes up in the same size as the main window. I reopen the app, but now the main window shows up in the size I wanted the new window to show up in. Then clicking the button to bring up the new window brings up the new window in the size I wanted it in. So I am a bit confused. Am I setting the sizes the right way? Is there anything else glaringly wrong here?
As # Raymond Chen said, PreferredLaunchViewSize set the size when the app launches, it will change the size of your main window. And you can use ApplicationView.TryResizeView method to set the size of new window.
For example:
auto parentView = ApplicationView::GetForCurrentView();
auto newView = CoreApplication::CreateNewView();
newView->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([this,parentView]()
{
int newViewId = 0;
Windows::UI::Xaml::Controls::Frame^ rootFrame = ref new Windows::UI::Xaml::Controls::Frame();
rootFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(MainPage::typeid), nullptr);
Window::Current->Content = rootFrame;
// You have to activate the window in order to show it later.
Window::Current->Activate();
newViewId = ApplicationView::GetForCurrentView()->Id;
IAsyncOperation<bool>^ mytask = ApplicationViewSwitcher::TryShowAsStandaloneAsync(newViewId);
auto deviceEnumTask = concurrency::create_task(mytask);
deviceEnumTask.then([this](bool res)
{
// set the size of new window
ApplicationView::GetForCurrentView()->TryResizeView(Size(600, 320));
});
}));

How can I get the same look as the standard with an owner draw menu?

I consider using an owner draw menu in a Windows application that should have the same look as the standard menu. (Reason: the standard menu doesn't work well in some mixed DPI situations.)
Currently I have a problem providing the correct width during WM_MEASUREITEM.
This is a screenshot of the Edit menu of notepad where each item has a shortcut.
We can see that there is a constant gap between the item texts and shortcut texts as if they were columns. It seems as if the widths of the item texts and the widths of the shortcut texts are retrieved separately, as the longest item text "Time/Date" reserves a shortcut width suitable for Ctrl+A while it only needs one for F5.
I could not find any API functionality where I can give the width of the item text and the shortcut text separately, nor did I find any metric specifying the size of the gap.
So my question is: Is it possible to achieve the desired behavior within the usual WM_MEASUREITEM message and if yes, how? If not, is there any other means to get this right or is it just not possible at all?
This is how ReactOS does it:
To measure a menu item:
if ((p = wcschr( lpitem->Xlpstr, '\t' )) != NULL) {
RECT tmprc = rc;
LONG tmpheight;
int n = (int)( p - lpitem->Xlpstr);
/* Item contains a tab (only meaningful in popup menus) */
/* get text size before the tab */
txtheight = DrawTextW( hdc, lpitem->Xlpstr, n, &rc,
DT_SINGLELINE|DT_CALCRECT);
txtwidth = rc.right - rc.left;
p += 1; /* advance past the Tab */
/* get text size after the tab */
tmpheight = DrawTextW( hdc, p, -1, &tmprc,
DT_SINGLELINE|DT_CALCRECT);
lpitem->dxTab += txtwidth;
txtheight = max( txtheight, tmpheight);
txtwidth += MenuCharSize.cx + /* space for the tab */
tmprc.right - tmprc.left; /* space for the short cut */
}
Then to draw it:
Text = lpitem->Xlpstr;
if(Text)
{
for (i = 0; Text[i]; i++)
if (Text[i] == L'\t' || Text[i] == L'\b')
break;
}
if(lpitem->fState & MF_GRAYED)
DrawTextW( hdc, Text, i, &rect, uFormat);
/* paint the shortcut text */
if (!menuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
{
if (L'\t' == Text[i])
{
rect.left = lpitem->dxTab;
uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
else
{
rect.right = lpitem->dxTab;
uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat );
}
So to insert a keyboard accelerator in a menu item, you simply separate it from the item text with the tab character. The measuring and drawing code then looks for this tab character and acts accordingly.
Note, however, that for the keyboard accelerator to be right-aligned in the menu like it is in your screenshot (which is achieved with DrawText with DT_RIGHT) the drawing code expects it to be separated from the item text with the '\b' character, not the tab character, and unless I'm missing something this is not accounted for in the measuring code, so you might want to compensate for that.
Replicating the standard menu with owner draw is a world of pain. You have to deal with Visual Styles on and off, mnemonics/Access keys, accessibility and all the undocumented metrics. It is better just to use the normal menu if you can.
Per-monitor DPI support seems to change in every Windows 10 release. 1607 added EnableNonClientDpiScaling which scales the menu and other non-client areas. 1703 added Per Monitor v2 and MSDN says this about PMv2:
Scaling of non-client area - All windows will automatically have their non-client area drawn in a DPI sensitive fashion. Calls to EnableNonClientDpiScaling are unnecessary.
Scaling of Win32 menus - All NTUSER menus created in Per Monitor v2 contexts will be scaling in a per-monitor fashion.
Notepad is PMv2 and its menu seems to work fine:
Windows 8.1 and < 10 Anniversary Update will require more work and I would suggest that you just don't declare yourself DPI aware on these systems and let Windows scale your window for you (with some blurriness) if the system has multiple monitors.

Showing a windows with XCB / Strange Behaviour

I'm trying to show a window in xcb, inside the main window, but actually without luck.
The idea is that when the user press a button (in that case the X button) a small white window is shown (just for test).
But actually i'm stuck on that step. I watched the example code here:
http://en.wikibooks.org/wiki/X_Window_Programming/XCB
And tried to do the same in my application.
[EDIT 28/10/2013] Now with that code i can show a window, but if i try to add other variable like int i=0, or whatever, the window doesn't appear, and no expose events were raised (all events that were raised are or 0 or 2 (even if i add the variables inside other events). Any idea?
This is the XCB_KEY_PRESS event handler code:
Edit (with the new code)
case XCB_KEY_PRESS:{
xcb_key_press_event_t *kp = (xcb_key_press_event_t *)ev;
if(kp->detail==53){
printf("X pressed\n");
uint32_t vals[2];
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
vals[0]=screen->white_pixel;
vals[1]=XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
win = xcb_generate_id(connection);
xcb_create_window(
connection,
XCB_COPY_FROM_PARENT,
win,
root,
80,80,
150,150,
10,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
vals[0]=screen->white_pixel;
vals[1]=0;
background=xcb_generate_id(connection);
xcb_create_gc(connection, background, win, mask, vals);
xcb_map_window(connection,win);
xcb_flush(connection);
printf("finished\n");
}
printf("KEY_PRESS - Pressed: %d\n", kp->detail);
}
root is the root window obtained from xcb_screen_t variable.
The definition of background and win are the following:
xcb_window_t win;
xcb_gcontext_t background;
And i added even a XCB_EXPOSE event handler:
case XCB_EXPOSE:{
printf("EXPOSE NEW WINDOW CREATED\n");
xcb_poly_fill_rectangle(connection, win, background,1,&rectangle);
xcb_flush(connection);
}
What is wrong with that code? What am i missing? (I'm trying to develop a very basic window manager, just for fun)
(My idea for that program is that when x is pressed an input box is shown, do you have any suggestion on how to do that?)

How to use a CTabCtrl in a MFC dialog based application?

I need to do something which i expected to be was simple - create a tab control which has 2 tabs, implying 2 modes of operation for my app. When user clicks on Tab1, he'll be presented with some buttons and textboxes, and when he clicks Tab2, some other input method. I noticed that there was a CTabCtrl class thats used in MFC to add tabs.
However, once I added the tab ctrl using the UI designer, I couldn't specify how many tabs there'll be using property window. Searching on the net, I found some examples but all of them required you to derive from CtabCtrl , create 2 or more child dialogs etc and to write your own custom class. My question is, since I want to do something so basic, why couldn't I do it using the familiar Add Event handler/Add member variable wizard and then handle everything else inside my app's class ? Surely, the default CTabCtrl class can do something useful without needing to derive from it ?
Forget about CTabCtrl and use CMFCTabCtrl which is much easier to work with (this is assuming you are working on VS2008 SP1).
Failing that, you seem to misunderstand how the tab control works. It only provides the 'tab strip' at the top and sends messages when the user clicks on another one. It doesn't provide you with 'tab canvases' on which you can put controls. Showing and hiding the controls on the tab is something that the programmer needs to take care of. The resource editor provides little support there. Like Stewart says, the most common way of working is to have child dialogs in your tab and hide all of them except the one of the current tab.
You don't need to derive from CTabCtrl, you can also implement the switching behavior in the window that is the parent of the CTabCtrl.
The MFC tab control is a pretty thin wrapper over the win32 tab control, which works in pretty much the way you describe. It is a window, which provides switching between child windows using tabs. As it happens, in straight win32 this is the most useful way for it to work. If you want to do something more sophisticated than switching between individual windows, you do this by using child dialogs. MFC doesn't do a great deal to help you, but deriving from CTabCtrl and using child dialogs is really not very difficult to do, although if you're used to the way WinForms does tab controls it does seem unnecessary.
If you want the tab control at the root of the dialog, with no other controls along side it, you might want to look at CPropertySheet (http://msdn.microsoft.com/en-us/library/d3fkt014(VS.80).aspx) which is probably simpler to use. Unless you want to use any of the wizard functionality you don't even need to derive from it - you just create a couple of child dialog classes, then in the place where you want to create the property sheet, make an object, add the pages to it and invoke it.
The approach I took with an MFC dialog that contained a CTabCtrl was to derive a small class to manage the tab control and used dialog templates to create the actual tab window contents.
This is still being worked on so the source code is not very clean however here are some pieces. For instance CTabCtrlDialog needs constructor and destructor in order to release object which may have been created.
In the resource file I have a dialog template with a tab control followed by three dialog templates for each of the different tab content windows inserted into the tab control. While the dialog displaying the tab control has the WS_POPUP style, the dialog templates for the tab windows that are inserted into the tab control have a WS_CHILD style instead. This change makes the tab windows child windows so that when the dialog is moved, everything stays lined up properly with no further effort on my part.
In my case the tab windows which are inserted into the tab control display a set of check boxes to indicate various operational parameters. Using a dialog template approach makes it very easy to create the necessary tab window content.
I derive a class from CTabCtrl that extends the standard MFC class with an additional method for inserting into the tab control a tab window based on a specified dialog template id. Since this is just a single dialog, I just put this class into the same files, .h and .cpp, as the dialog components themselves.
class CTabCtrlDialog : public CTabCtrl
{
public:
void InsertItemDialogTemplate (UINT nIDTemplate, int nItem, TCITEM* pTabCtrlItem);
public:
struct {
UINT nIDTemplate;
CDialog *pDialog;
} m_pDialogData[10];
};
The method InsertItemDialogTemplate() looks like:
/*
* InsertItemDialogTemplate ()
*
* Insert into a tab control a tab pane based on the specified dialog template. The
* dialog template describes what the tab pane looks like so far as controls, etc.
*
* NOTE: The STYLE description must be WS_CHILD and not WS_POPUP. Also the dialog
* needs to have as its top coordinate some distance in pixels so that the
* various tab descriptions are visible. For instance an example dialog
* template in the resource file may look like:
* IDD_CASHIER_TAB_ONE DIALOGEX 0, 10, 178, 113
* STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
* FONT 8, "MS Shell Dlg", 400, 0, 0x1
* BEGIN
* LTEXT "Dialog Tab one",IDC_STATIC,6,44,90,17
* END
*
**/
void CTabCtrlDialog::InsertItemDialogTemplate (UINT nIDTemplate, int nItem, TCITEM* pTabCtrlItem)
{
InsertItem (nItem, pTabCtrlItem);
m_pDialogData[nItem].nIDTemplate = nIDTemplate;
m_pDialogData[nItem].pDialog = new CDialog ();
m_pDialogData[nItem].pDialog->Create (nIDTemplate, this);
m_pDialogData[nItem].pDialog->ShowWindow (FALSE);
}
For handling tab selection which displays the various tabs I have the following message map and then the two event handlers in the dialog.
BEGIN_MESSAGE_MAP(CDiaCashierEdit, CDialog)
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_CASHIER_EDIT_STATUS, &CDiaCashierEdit::OnTcnSelchangeTabCashierEditStatus)
ON_NOTIFY(TCN_SELCHANGING, IDC_TAB_CASHIER_EDIT_STATUS, &CDiaCashierEdit::OnTcnSelchangingTabCashierEditStatus)
END_MESSAGE_MAP()
void CDiaCashierEdit::OnTcnSelchangeTabCashierEditStatus(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
int i = TabCtrl_GetCurSel(pNMHDR->hwndFrom);
m_TabCtrl.m_pDialogData[i + 1].pDialog->ShowWindow (TRUE);
}
void CDiaCashierEdit::OnTcnSelchangingTabCashierEditStatus(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
int i = TabCtrl_GetCurSel(pNMHDR->hwndFrom);
m_TabCtrl.m_pDialogData[i + 1].pDialog->ShowWindow (FALSE);
}
In the DoDataExchange() method of the dialog I have the following which creates first the tab control and then creates each of the tab windows and inserts them into the tab control.
void CDiaCashierEdit::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_CASHIER_NAME, m_CashierName);
DDX_Control(pDX, IDC_EDIT_CASHIER_SUPNO, m_SupervisorId);
DDX_Control(pDX, IDC_EDIT_CASHIER_TEAMNO, m_TeamNumber);
DDX_Control(pDX, IDC_EDIT_CASHIER_GCSTART, m_GuestCheckStart);
DDX_Control(pDX, IDC_EDIT_CASHIER_GCEND, m_GuestCheckEnd);
DDX_Control(pDX, IDC_TAB_CASHIER_EDIT_STATUS, m_TabCtrl);
if (pDX->m_bSaveAndValidate) {
m_CashierName.GetWindowText (m_paraCashier.auchCashierName, 20);
m_paraCashier.usSupervisorID = m_SupervisorId.GetWindowTextAsInt();
m_paraCashier.uchTeamNo = m_TeamNumber.GetWindowTextAsInt();
m_paraCashier.usGstCheckStartNo = m_GuestCheckStart.GetWindowTextAsInt();
m_paraCashier.usGstCheckEndNo = m_GuestCheckEnd.GetWindowTextAsInt();
for (int i = 0; i < sizeof(m_TabItemOneStatus)/sizeof(m_TabItemOneStatus[0]); i++) {
int iTab = m_TabItemOneStatus[i].sTabItem;
int iDlg = m_TabItemOneStatus[i].iDlgItem;
int iOffset = m_TabItemOneStatus[i].sOffset;
CButton *p = (CButton *) m_TabCtrl.m_pDialogData[iTab].pDialog->GetDlgItem(iDlg);
if (p->GetCheck()) {
m_paraCashier.fbCashierStatus[iOffset] |= m_TabItemOneStatus[i].uchBit;
} else {
m_paraCashier.fbCashierStatus[iOffset] &= ~(m_TabItemOneStatus[i].uchBit);
}
}
} else {
m_CashierName.SetWindowText(m_paraCashier.auchCashierName);
m_SupervisorId.SetWindowTextAsInt (m_paraCashier.usSupervisorID);
m_TeamNumber.SetWindowTextAsInt (m_paraCashier.uchTeamNo);
m_GuestCheckStart.SetWindowTextAsInt (m_paraCashier.usGstCheckStartNo);
m_GuestCheckEnd.SetWindowTextAsInt (m_paraCashier.usGstCheckEndNo);
m_TabCtrl.InsertItemDialogTemplate (IDD_CASHIER_TAB_ONE, 1, &m_TabItemOne);
m_TabCtrl.InsertItemDialogTemplate (IDD_CASHIER_TAB_TWO, 2, &m_TabItemTwo);
m_TabCtrl.InsertItemDialogTemplate (IDD_CASHIER_TAB_THREE, 3, &m_TabItemThree);
for (int i = 0; i < sizeof(m_TabItemOneStatus)/sizeof(m_TabItemOneStatus[0]); i++) {
int iTab = m_TabItemOneStatus[i].sTabItem;
int iDlg = m_TabItemOneStatus[i].iDlgItem;
int iOffset = m_TabItemOneStatus[i].sOffset;
CButton *p = (CButton *) m_TabCtrl.m_pDialogData[iTab].pDialog->GetDlgItem(iDlg);
if (m_paraCashier.fbCashierStatus[iOffset] & m_TabItemOneStatus[i].uchBit) {
p->SetCheck (1);
} else {
p->SetCheck (0);
}
}
m_TabCtrl.m_pDialogData[1].pDialog->ShowWindow (TRUE);
}
}

Resources