We have come across some behaviour involving the taskbar icons that Windows 7 displays for different applications. I'm wondering whether anybody could shed some light on this:
Windows 7 is set with font-size = 110%.
Two MFC dialog applications A.exe and B.exe have exactly the same .ico resource embedded in them.
A.exe has a shortcut associated with it; B.exe does not.
Running A.exe shows a nice interpolated icon on the taskbar.
Running B.exe shows a different icon on the taskbar (not interpolated).
We would wish that the same icon appears on the taskbar for A.exe and B.exe - this is easily achieved by making a shortcut to B.exe to give the same behaviour. However, I'm really trying to understand more on what's going on.
In trying to understand what was going on I have handled the WM_GETICON message inside B.exe, returning an icon according to the sizes given by GetSystemMetrics SM_CXICON/SM_CYICON or SM_CXSMALLICON/SM_CYSMALLICON size. However, this didn't seem to affect the icon shown in the taskbar.
I also know that we could create an .ico file to be built into B.exe with lots of different sizes of icons - maybe this would improve things, but that's a tedious solution!
Any ideas?
Just met this issue with following simple scenario(all on win7):
create A.exe with icon B
create B.lnk associated to A.exe with different icon C (by winapi CreateLink)
run with clicking B.lnk. On some win7 machines, taskbar's icon is C. But, on some other machine(also win7), it's B.
If the icon is C, it even can't be changed by following code:
const HANDLE bigicon = ::LoadImage(::GetModuleHandle(0), MAKEINTRESOURCE(IDI_TO_ICON), IMAGE_ICON, 256, 256, 0);
if (bigicon) {
::SendMessage(theMainWnd, WM_SETICON, ICON_BIG, (LPARAM)bigicon);
::SendMessage(GetWindow(theMainWnd, GW_OWNER), WM_SETICON, ICON_BIG, (LPARAM)bigicon);
}
const HANDLE smallicon = ::LoadImage(::GetModuleHandle(0), MAKEINTRESOURCE(IDI_TO_ICON_SMALL), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 0);
if (smallicon) {
::SendMessage(theMainWnd, WM_SETICON, ICON_SMALL, (LPARAM)smallicon);
::SendMessage(GetWindow(theMainWnd, GW_OWNER), WM_SETICON, ICON_SMALL, (LPARAM)smallicon);
}
Related
I have the problem, that I want to include one app into another.
In normal mode this works with no problem. In Delphi (VCL) I remove the window frame and set the container panel of the main app A as parent of the app B.
using WinApi.Windows;
var
A: TPanel;
B: TWinProcInfo;
SetParent(B.HWND, A.Handle);
// remove title bar and window frame
aWindowStyle := GetWindowLong(B.HWND, GWL_STYLE);
SetWindowLong(B.HWND, GWL_STYLE, aWindowStyle and (not WS_CAPTION) and (not WS_THICKFRAME));
// set position/size inside A
SetWindowPos(B.HWND, 0, 0, 0, A.width, A.height, SWP_NOSIZE)
Unfortunately, in tablet mode nevertheless the app B is displayed maximized and now I also cannot get to the main app A, because it is the parent of B (so B overlays A).
But: not every app is maximized in tablet mode!
If I set Application.MainFormOnTaskbar := False; in a Delphi demo app, that app can be freely moved and sized, even in tablet mode. If I understand the docs correctly this sets which form is connected to the taskbar icon.
If the MainFormOnTaskBar is True, a taskbar button represents the application's main form and displays its caption. If False, a taskbar button represents the application's (hidden) main window and bears the application's Title.
MainFormOnTaskBar must be True to use Windows Vista or Windows 7 Aero effects, including live taskbar thumbnails, Dynamic Windows, Windows Flip, and Windows Flip 3D.
My problem now is:
how can I do this for an external app? Because B is not my own (its UltraVNC btw).
Is there any winapi like the styling above to accomplish this?
Explorer seems to always start my application with SW_MAXIMIZE (STARTF_USESHOWWINDOW is set in STARTUPINFO.dwFlags). I know that ShowWindow will use this value the first time you/Windows needs to display a window but it has the unfortunate consequence of maximizing a window that should never be maximized.
My window is created with CreateDialogIndirectParam and has the following styles: WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPCHILDREN|DS_MODALFRAME|DS_CENTER|WS_VISIBLE. Why does ShowWindow not check if WS_MAXIMIZEBOX is set before allowing STARTF_USESHOWWINDOW to force SW_MAXIMIZE? Is this a bug in Windows?
This happens on a HP Stream 7 with Windows 8.1. I'm not sure if Explorer does this because it is touch enabled or because of the small screen.
Is this Explorer behavior documented anywhere and is there a way to turn it off? What is the best way to stop Explorer (or any other parent process) from affecting my initial window mode? (I don't want to block people starting me with SW_*MINIMIZE*)
WinVer.exe in system32 has the same problem:
My first thought was to turn off STARTF_USESHOWWINDOW in the PEB if the parent wanted me to start maximized but that is too nasty and undocumented so I have not tried that yet.
Preventing any kind of size change (which is OK for my application since it is just a "modal" dialog) sort of works:
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lp)->flags |= SWP_NOSIZE;
return true;
The problem is that the window position is still set to 0 x 0 like a maximized window.
A better solution seems to be to detect and correct the problem after WM_INITDIALOG:
case WM_INITDIALOG:
PostMessage(hDlg, WM_APP, 0, 0);
break;
case WM_APP:
if (IsZoomed(hDlg)) ShowWindow(hDlg, SW_SHOWNOACTIVATE);
break;
I am the proud owner of several HP Stream 7 tablets and I would like to add my 2 cents here. Microsoft has made an arbitrary decision that devices with screen sizes smaller than 8 inches will behave differently than the norm. A lot of users are somewhat aware of this, but unaware that this is where your problem originates.
Windows determines a screen's size by reading the EDID information from the screen, which contains sizing information in it, in centimeters.
If no sizing information is present in the EDID, or the sizing information is below Microsoft's arbitrarily chosen 8 inch threshold, you get this apparent misbehavior which is at the very least, aggrivating to those who notice it and don't want it.
The solution is to override the default driver for the monitor in Device Manager with one that informs Windows that the screen is in fact, 8 inches or larger.
To do so, you need to first read the EDID information from the registry with a tool such as Deltacast's E-EDID Editor (free, last time I checked), and modify the size values and save the modified file someplace you can find it.
After you have modified your EDID file and saved it, download Monitor Asset Manager from EnTech (also free) and use it to create an INF file.
Once the INF file has been created, you need to restart Windows with the Advanced settings menu and choose to Disable Driver Signing Enforcement, since the INF file you created won't be digitally signed. Once disabled, open Device Manager in Windows and update the driver for the monitor using the INF file you created. You will need to confirm that you do in fact want to install the unsigned driver file.
Reboot and Windows will now behave normally with the one catch that, the onscreen keyboard will now appear a different size and will have more options available.
Sadly, Microsoft can change this behavior in the future, so there is no guarantee that through the same flawed decision making process they used to implement this in the first place, they won't force it down our throats again, using a much more difficult to counteract method.
Is it possible create MFC form that cold stay on the top of all applications on PC not allowing to do anything else without entering required information.
Win32 doesn't support system-modal dialogs any more, as far as I'm aware. This is a relic from 16 bit Windows versions.
You can try yourself with a MB_SYSTEMMODAL type MessageBox.
Closest thing would be to utilize a screen-sized window to display a dimmed desktop background while your dialog is shown. This simulates the behaviour of the user account control -- except that you still can switch tasks.
You can obtain something similar setting your window on "TopMost". You can do it on property sheet in design mode, or programmatically with this line:
SetWindowPos( pWnd->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE );
Hope this will fit your needs.
I have an MFC application. In my application if I run on Windows XP it's working fine. But if I run in Windows Vista the MFC dialog hides behind the taskbar.
bool bHide=true;
CRect rectWorkArea = CRect(0,0,0,0);
CRect rectTaskBar = CRect(0,0,0,0);
CWnd* pWnd = CWnd::FindWindow("Shell_TrayWnd", "");
pWnd->ShowWindow(SW_SHOW);
if( bHide )
{ // Code to Hide the System Task Bar
SystemParametersInfo(SPI_GETWORKAREA,0,(LPVOID)&rectWorkArea,0);
if( pWnd )
{
pWnd->GetWindowRect(rectTaskBar);
// rectWorkArea.bottom -= rectTaskBar.Height();
rectWorkArea.bottom += rectTaskBar.Height();//-----to hide taskbar
SystemParametersInfo(SPI_SETWORKAREA,0,(LPVOID)&rectWorkArea,0);
// pWnd->ShowWindow(SW_SHOW);
pWnd->ShowWindow(SW_HIDE); //--to hide taskbar
}
}
I used this code but it hides the taskbar. But I want to show the application above the task bar.
You don't own the taskbar, so you are not supposed to hide it. You have the option to auto-minimize it by the way. You have another option of using secondary monitor without taskbar there.
On the primary monitor your app is given work area, you are being able to locate (judging from the code snippet provided above). It is the best to position your window within this area without interfering with the taskbar, whether it is above or beyond.
If you still feel like making it more like a competition "who is on top" with the task bar, you might want to take a look at SetWindowPos API and window Z-Order.
finally i found the solution , what we want to do is we should add the below code in our oninitdialog,
SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
the above line is enough to show the mfc dialog on above the taskbar . but sometimes the focus of the dialog get changed looks hanged(no response in dialog) the application.if it occurs put the below code.
SetWindowPos(&this->wndBottom,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
I've got a dialog box where I need to display the standard Information icon. Here's my RC code:
ICON "",IDC_ICON_INFORMATION,18,70,21,20
I process the WM_INITDIALOG message as follows:
HICON aIcn = LoadIcon(NULL, IDI_INFORMATION);
SendDlgItemMessage(m_hWnd, IDC_ICON_INFORMATION, STM_SETICON, (WPARAM) aIcn, 0);
Everything works great under 96 DPI: the static control displays a 32x32-pixel icon.
However, when I switch to higher DPI's (through right-clicking on the Desktop, choosing Screen resolution, and clicking Make or other items larger or smaller) the icon does not scale! Since everything else scales nicely, the icon looks visually much smaller than the neighboring text. I would expect that on 144 DPI (150%) the icon dimensions will be 48x48 pixels. I did declare my application as DPI-aware through an XML manifest.
The damnedest thing is that when I use my own custom-made icon (also coming from the RC file), everything scales perfectly. Furthermore, the MessageBox function called with the MB_ICONINFORMATION flag does display a scaled version of the icon, as well.
Given these thoughts, I assume of the following:
The static control with the SS_ICON style can display scaled versions of icons.
The icon resource that contains the standard Information icon has a scaled version of the icon (48x48).
What am I doing wrong then?
Use LoadImage() instead of LoadIcon(), and specify the cxDesired and cyDesired params with the values you get from GetSystemMetrics(SM_CYICON) and GetSystemMetrics(SM_CXICON).
Or maybe just declaring your app as DPI aware could be enough? You can try that easily by simple creating a text file making it a manifest file.
See the example in the remarks section for the SetProcessDPIAware API