Win32 Console Disable System Menu Buttons - c++

I want to disable/grey a system menu button on the console window, particularly the minimize button. I've tried functions mentioned on another thread, but even after using them, the console window still doesn't have the minimize button grayed out. I have also looked into the DeleteMenu() function, but it doesn't seem to have the option to grey out buttons.
Here's the test code:
#include <Windows.h>
using namespace std;
int main()
{
//SetConsoleTitle(L"CPU Information");
HWND consoleWindow = GetConsoleWindow();
HMENU hMenu = GetSystemMenu(consoleWindow, FALSE);
EnableMenuItem(hMenu, SC_MINIMIZE, MF_BYCOMMAND | MF_GRAYED);
DrawMenuBar(consoleWindow);
return 0;
}

GetWindowLong + SetWindowLong FTW!
int main(int argc, _TCHAR* argv[])
{
HWND consoleWindow = GetConsoleWindow();
LONG style = GetWindowLong(consoleWindow , GWL_STYLE);
style = style & ~(WS_MINIMIZEBOX);
SetWindowLong(consoleWindow, GWL_STYLE, style);
return 0;
}
This will grey-out and disable both the minimize box in the top-right corner of the window as well as the "minimize" option from the system menu.

Related

ShowWindow restores the window only if is the last minimized

I'm trying to make a program in C++ that shows a minimized calculator.
It works if I minimize it, but if I minimize the Calculator and then another program like firefox, the program doesn't show the calculator anymore.
int main()
{
hwnd = FindWindow(NULL,TEXT("Calculator"));
ShowWindow(hwnd, SW_SHOW);
return 0;
}
If the calculator is minimized (see IsIconic()), then you should be using SW_RESTORE instead of SW_SHOW, per the ShowWindow() documentation:
SW_RESTORE
9
Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
SW_SHOW
5
Activates the window and displays it in its current size and position.
Try this:
int main()
{
HWND hwnd = FindWindow(NULL, TEXT("Calculator"));
if (hwnd)
{
if (IsIconic(hwnd))
ShowWindow(hwnd, SW_RESTORE);
else
ShowWindow(hwnd, SW_SHOW);
}
return 0;
}

Winapi how to hide/show a third-party program window?

I'm trying to hide/show a third-party program (e.g. Discord):
#include <windows.h>
void show_hide(HWND window)
{
if (IsWindowVisible(window) == TRUE) {
ShowWindow(window, SW_HIDE);
} else {
ShowWindow(window, SW_SHOW);
}
}
BOOL CALLBACK enum_windows_cb(HWND window, const LPARAM lParam)
{
const char* target = "Discord";
char title[255];
if (GetWindowText(window, title, sizeof(title))) {
if (strcmpi(title, target) == 0) {
show_hide(window);
return FALSE;
}
}
return TRUE;
}
int main(int argc, char *argv[])
{
EnumWindows(&enum_windows_cb, 0);
return 0;
}
It's work fine, but if I hide a third-party program by click on close button, my program shows frozen window, until I press the tray icon.
Video demonstration:
https://www.youtube.com/watch?v=P-_Fi-Dew1w
I also wrote message log through microsoft spy++ https://pastebin.com/YwGt88yh
It recorded three actions: click on close button hides program, click on tray icon shows program, and my program tries to show window.
I also tried to add these functions one by one after ShowWindow:
SetForegroundWindow(window);
SendMessage(window, WM_SYSCOMMAND, SC_RESTORE, 0);
UpdateWindow(window);
RedrawWindow(window, 0, nil, RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_UPDATENOW or RDW_FRAME);
SendMessage(window, WM_ACTIVATEAPP, TRUE, GetWindowThreadProcessId(window, 0));
But it did not help. What did I do wrong?
I use windows 10.

How do I add vertical scrollbar to a fullscreen win32 console?

When I set my win32 console to full screen, the vertical scrollbar disappears. When the text goes to the bottom of the screen, it does not scroll up. Newly written output is not presented to the user because it is below.
This is the style:
if (isFullScreen)
{
// Set the full screen window style.
style = GetWindowLong(handle, GWL_STYLE);
style &= ~(WS_BORDER | WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPEDWINDOW);
SetWindowLong(handle, GWL_STYLE, style);
// Minimalize, then show maximized to avoid the cursor blink bug in conhost.exe.
ShowWindow(handle, SW_MINIMIZE);
ShowWindow(handle, SW_SHOWMAXIMIZED);
// Set the font size
setFontSize(fontSize);
}
I searched the web but it's understandably not common.
How can I add the vertical scrollbar to this while in full screen?
On my computer, I can realize the appearance of full screen console and vertical scrollbar. My system is Win10, using vs2017.
This is my code.
#include "pch.h"
#include <iostream>
#include <Windows.h>
void full_screen()
{
HWND hwnd = GetForegroundWindow();
int cx = GetSystemMetrics(SM_CXSCREEN); /* Screen width pixels */
int cy = GetSystemMetrics(SM_CYSCREEN); /* Screen Height Pixel */
LONG l_WinStyle = GetWindowLong(hwnd, GWL_STYLE); /* Get window information */
/* Set window information to maximize the removal of title bar and border*/
SetWindowLong(hwnd, GWL_STYLE, (l_WinStyle | WS_POPUP | WS_MAXIMIZE) & ~WS_CAPTION & ~WS_THICKFRAME & ~WS_BORDER);
SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
}
int main()
{
full_screen();
while(1)
{
std::cout << "Hello World!\n";
}
return 0;
}
Debug Result:
The official way to set a console to fullscreen is to call SetConsoleDisplayMode().
Under Windows 10 Pro Version 1803 the following code shows a vertical scrollbar without further ado:
#include <iostream>
#include <windows.h>
int main()
{
HANDLE const hConsole = ::GetStdHandle( STD_OUTPUT_HANDLE );
if( hConsole == INVALID_HANDLE_VALUE ||
! ::SetConsoleDisplayMode( hConsole, CONSOLE_FULLSCREEN_MODE, nullptr ) )
{
DWORD const err = ::GetLastError();
std::cerr << "Failed to set console fullscreen mode. System error: " << err << "\n";
return 1;
}
for( int i = 0; i < 200; ++i )
{
std::cout << "Hello World!\n";
}
return 0;
}
Note that SetConsoleDisplayMode() can fail if the process is not attached to a console (e. g. by passing the flag CREATE_NO_WINDOW to CreateProcess()) or if STDOUT is redirected to a file.

Why did I fail to find window use parent specified in Spy++?

Imagine there is a web page with a <input type="file" />. I open this page in Firefox, and click on the file button. Then a dialog will popup.
I want to set the file name edit of the popup dialog programmatically in C++:
First I use Spy++ to check window class, the Firefox window and popup dialog properties in Spy++ look like:
Firefox window:
Handle: 001E013E
Caption: Table with objects - Mozilla Firefox
Class: MozillaWindowClass
Popup dialog:
Handle: 004508BE
Caption: File Upload
Class: #32770 (Dialog)
Spy++ also shows browser window is the parent of popup dialog.
My code looks like:
#include <Windows.h>
#include <stdio.h>
int main()
{
HWND hBrowser = FindWindow(L"MozillaWindowClass", NULL);
printf("Browser hwnd=%X\n", hBrowser);
HWND hDialog = FindWindowEx(hBrowser, NULL, L"#32770 (Dialog)", NULL);
printf("Dialog hwnd=%X\n", hDialog);
system("pause");
}
But the value of hBrowser does not equal the value in Spy++ dialog, and value of hDialog is NULL. I have only one Firefox window opened, with only one tab.
Then I tried to change my code to:
// 0x001E013E is the handle in Spy++
HWND hDialog = FindWindowEx((HWND)0x001E013E, NULL, L"#32770 (Dialog)", NULL);
hDialog still outputs as NULL.
Questions:
Why the handle in Spy++ and the one I get in program is not the same?
Does the "parent window" in Spy++ have the same meaning with the parent parameter in FindWindowEx?
Note: I can't use window title to do the find, due to localization issue (Firefox may be installed in languages other than English).
MozillaWindowClass is the owner of the open dialog, it is not a parent you can use with FindWindowEx. There can also be more than one MozillaWindowClass window so it is better to look for the dialog first:
BOOL CALLBACK FindMozillaOpenFilenameDialogEnumProc(HWND hWnd, LPARAM param)
{
HWND*pData = (HWND*) param;
if (GetClassLongPtr(hWnd, GCW_ATOM) == 32770) // Found a dialog?
{
HWND hOwner = GetWindow(hWnd, GW_OWNER);
if (hOwner)
{
WCHAR buf[100];
GetClassName(hOwner, buf, 100);
if (0 == lstrcmp(buf, TEXT("MozillaWindowClass"))) // The dialog is owned by a Mozilla window?
{
HWND hCombo = GetDlgItem(hWnd, 0x047c); // cmb13
GetClassName(hCombo, buf, 100);
buf[8] = '\0'; // Some Windows versions use ComboBox and some use ComboBoxEx32, we only care if it is some type of combobox
if (0 == lstrcmp(buf, TEXT("ComboBox"))) // The dialog contains a ComboBox with the expected ID?
{
*pData = hWnd;
return false;
}
}
}
}
return true;
}
int main()
{
HWND hDialog = NULL;
EnumWindows(FindMozillaOpenFilenameDialogEnumProc, (LPARAM) &hDialog);
printf("Dialog hwnd=%X\n", hDialog);
if (hDialog)
{
HWND hCombo = GetDlgItem(hDialog, 0x047c);
SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM) TEXT("c:\\foo\\bar.exe")); // Could also use CDM_SETCONTROLTEXT?
}
return 0;
}
This code relies on undocumented and internal names and window relationships, it could break at any time.
Keep in mind that "MozillaWindowClass" is a internal Mozilla name and could change at any time. The documented cmb13 id of the filename control is only documented for GetOpenFileName and GetSaveFileName but not for IFileDialog based dialogs. You really should use UI Automation when you interact with the open dialog in another application!

Get Desktop PIDL from Coordinates

I'm trying to create functionality of the shell context menus despite them being blocked by a group policy for no real reason. One thing this demands is which icon the user is actually right-clicking, or if they are just clicking the desktop. The same thing also applies to explorer windows, although the desktop is where I'm planning on starting.
So far I can get the context menu to show for a specific file with a literal path. I found a nice list of interfaces on msdn, but none of the desktop-related ones I could find had any way of getting the desktop item like this. The closest match I could find was IActiveDesktop::GetDesktopItem with going through every single item and seeing whether the position matches, and then assuming none were clicked if none match.
This approach brings up two new issues, though. Firstly, I'm not sure how to go through every icon. Secondly, I have no clue how to convert this to a PIDL.
Also, even if I got the icons working, how would I extend this to the shell context menu for just the desktop?
Here's the code I use for a specific file:
#define _WIN32_WINNT _WIN32_WINNT_WINXP //going to be using on XP, tested on 7
#include <windows.h> //main header
#include <shellapi.h> //shell headers
#include <shlobj.h>
#include "G:\programming\v1\winwrap.h" //used for the window to display menu on
LPCONTEXTMENU cm; //holds context menu
msgproc (rproc) //this is called when right mouse button is depressed on window
{
//This function shows the context menu of the program on this window
//hwnd() is the HWND of the window involved with the right click
HMENU hMenu = CreatePopupMenu();
DWORD Flags = CMF_EXPLORE;
cm->QueryContextMenu(hMenu, 0, 1, 0x7FFF, Flags);
POINT pt;
GetCursorPos(&pt);
int Cmd = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd(), 0);
CMINVOKECOMMANDINFO ci;
if (Cmd)
{
ci.lpVerb = MAKEINTRESOURCE(Cmd - 1);
ci.lpParameters = "";
ci.lpDirectory = "";
ci.nShow = SW_SHOWNORMAL;
cm->InvokeCommand(&ci);
}
}
int main()
{
Window win; //create window for menu to go on, can be invisible, fullscreen later
win.addmsg (WM_RBUTTONUP, rproc); //handle message with previous function
WCHAR fname [MAX_PATH] = L"C:\\Users\\Chris\\Desktop\\context.exe"; //full path
WCHAR path [MAX_PATH] = L"C:\\Users\\Chris\\Desktop"; //path part
WCHAR name [MAX_PATH] = L"context.exe"; //filename part
LPSHELLFOLDER desktopFolder; //get desktop shell folder
SHGetDesktopFolder (&desktopFolder);
LPITEMIDLIST pidl; //tried using this for no icon by changing GetUIObjectOf to this pild to no avail
DWORD eaten;
desktopFolder->ParseDisplayName (0, 0, path, &eaten, &pidl, 0);
LPSHELLFOLDER parent;
desktopFolder->BindToObject (pidl, 0, IID_IShellFolder, (void **)&parent);
LPITEMIDLIST localPidl; //file pidl
parent->ParseDisplayName (0, 0, name, &eaten, &localPidl, 0);
parent->GetUIObjectOf (0, 0, (LPCITEMIDLIST *)&localPidl, IID_IContextMenu, 0, (void **)&cm); //gets context menu
messageLoop(); //window message loop
}
Any help is very appreciated.