How to stop Explorer starting my application maximized? - windows

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.

Related

DirectX11 Swapchain and window losing fullscreen status

I just stumbled on this little annoying behavior, while adding full screen support on a sample program.
Creating a full screen window works, but as soon as I move any window (from another application) on the output that contains my fullscreen window, it automatically switches back to windowed.
Is there any way to prevent this behavior (so full screen window do not go back to windowed)?
As a reference, this is a small standalone example (so problem can be replicated easily).
Also if that is useful, I'm running on Windows 8.1.
I already tried to change WindowAssociationFlags and SwapChainFlags, both with no success, same as using FlipSequential instead of Discard
SharpDX.DXGI.Factory2 factory = new SharpDX.DXGI.Factory2();
SharpDX.DXGI.Adapter adapter = factory.GetAdapter(0);
var renderForm1 = new RenderForm("Form 1");
factory.MakeWindowAssociation(renderForm1.Handle, SharpDX.DXGI.WindowAssociationFlags.IgnoreAll);
Device device = new Device(adapter, DeviceCreationFlags.BgraSupport);
SharpDX.DXGI.SwapChainDescription sd = new SharpDX.DXGI.SwapChainDescription()
{
BufferCount = 2,
ModeDescription = new SharpDX.DXGI.ModeDescription(0, 0, new SharpDX.DXGI.Rational(50, 1), SharpDX.DXGI.Format.R8G8B8A8_UNorm),
IsWindowed = true,
OutputHandle = renderForm1.Handle,
SampleDescription = new SharpDX.DXGI.SampleDescription(1,0),
SwapEffect = SharpDX.DXGI.SwapEffect.Discard,
Usage = SharpDX.DXGI.Usage.RenderTargetOutput,
Flags = SharpDX.DXGI.SwapChainFlags.None
};
var swapChain1 = new SharpDX.DXGI.SwapChain(factory, device, sd);
renderForm1.Left = 1922; //Just hardcoded here to move window to second screen
renderForm1.Width = 1920;
renderForm1.Height = 1080;
renderForm1.FormBorderStyle = FormBorderStyle.None;
swapChain1.SetFullscreenState(true, null);
swapChain1.ResizeBuffers(2, 1920, 1080, SharpDX.DXGI.Format.R8G8B8A8_UNorm, SharpDX.DXGI.SwapChainFlags.AllowModeSwitch);
var resource = Texture2D.FromSwapChain<Texture2D>(swapChain1, 0);
var renderView = new RenderTargetView(device, resource);
RenderLoop.Run(renderForm1, () =>
{
device.ImmediateContext.ClearRenderTargetView(renderView, new SharpDX.Color4(1, 0, 0, 1));
swapChain1.Present(1, SharpDX.DXGI.PresentFlags.None);
});
Edit:
I also tried a c++ sample (just taken DirectX11 basic tutorial from Microsoft and added full screen switch), this leads to the same behavior, so this is not a SharpDX specific issue.
I looked at the message loop, and once this occurs, first fullscreen mode is changed back to windowed, and I receive a WM_DISPLAYCHANGE message).
This sounds like expected behavior. If you have a full screen 'exclusive' mode swapchain and the associated window loses focus, the system automatically switches the application out of full screen mode back to windowed mode by design.
With a single monitor, it mostly works as long as you have your applications' window sized to fill the display. Users can't use the mouse to change focus of your window, and it requires something like ALT+TAB to switch focus.
With multiple monitors, it's a real problem. If you click on another window on another display, your app loses focus and the full screen mode is again switched out. There are also limitations that prevent you from setting full screen 'exclusive' mode on more than one monitor.
Furthermore, on Windows Vista or later the notion of 'exclusive' mode is an illusion: the GPU is always shared anyhow. The 'focus' application gets priority whether it is a full screen or a windowed swap chain.
For a Windows desktop apps you have three choices for a full screen style experience:
Use the traditional full screen 'exclusive' mode with a window sized to fill the display, along with setting the display mode which may not be what the user has set for Windows generally. Here you have IsWindowed = false.
You set the window size to fill the full display (i.e. maximized). You can use windows styles to ensure that the window has no frame which results in a full screen style experience (WS_POPUP). Here you have IsWindowed = true, and you should be sure to set DXGI_MWA_NO_ALT_ENTER to avoid allowing DXGI to try to take you to use the 1 case.
You can do the same as 2 with IsWindowed = true and the borderless window sized to match the screen, but you change the display mode to something other than the system default. This is commonly referred to as 'fake full screen'. The display mode gets changed back whenever you exit the application.
1 has all has all the problems with multi-tasking and focus we just described. 2 and 3 allow system notifications and other pop-ups to show up over the game and not force a mode switch. 2 and 3 also work a lot better in multi-monitor setups where you can play your game on one display and use other apps on another display. For multi-tasking most people to prefer a classic window style with a frame border.
Windows Store UWP notions of full screen mode is basically like 2 above. You can't change the display mode with a UWP.
Debugging a full-screen setup is quite challenging. With multiple monitors, 2 and 3 can work with your debugger on the other screen. For true full-screen exclusive mode, really the only option is to use remote debugging from another PC.
Another issue with 1 and 3 is that you can set the display mode to something that won't sync with the display leaving the user with a system with no UI and no way to exit. Ideally with the right driver setup, the DXGI enumeration list does not contain unsupported modes, but it is something to be aware of. For this reason, your UI for selecting a display mode should have a timeout and you should make sure there's a reasonable way to abort the application with the keyboard if the display mode fails to sync at some point in the future. Using the existing display mode as we do in 2 above is always the safest option.
The main reason to use full screen exclusive mode (1) above is to try to get 'flip' rather than 'blit' of the backbuffer/frontbuffer. For most modern systems, this is a negligible performance difference. The other reason to go through the pain of using it is for SLI/Crossfire multi-GPU rendering going to a single display. There are a number of other optimizations required to really make that scenario work, and it's pretty niche. You should seek out the vendor optimization guides for the details.
Most modern games default to using fake full screen rather than full screen 'exclusive' mode. They offer the ability to use a true windowed mode as many users want to be able to multi-task while playing (like looking up hints online, use IM or external voice chat, etc.). AAA Windows desktop games that want to support tuned high-performance gaming for SLI/Crossfire will offer a full screen 'exclusive' mode, but this requires some work to get working fully and entails more work than just some DXGI code.
See DXGI Overview and DirectX Graphics Infrastructure (DXGI): Best Practices
After several attempts and trials, here are the different workarounds I used, none are ideal but all are somehow better than getting a mode change.
1/Force cursor in the middle of the full screen window, with a keyboard shortcut to get control again.
This is not ideal since we can't really do anything while our part is running, but at least prevents accidental "disaster click". It does not prevent keyboard interaction either.
2/Use a DX9 renderer with a shared texture.
DX9 Swapchain can have it's parent window set to desktop, so it does not lose focus when moving to something else.
Having a focused window on top show little borders visible while moving it, but that is a bit more acceptable than losing everything.
Not future proof but guess will stay actual for a while.
3/Stay on Windows 7 and Disable DWM Service:
Doesn't work in Windows 8 anymore, but in my use case since most media companies I work for are still on Windows 7, it stays a valid solution for at least 5 to 10 years.
4/Force the DX11 Window on foreground
Basically continuously call SetForegroundWindow to avoid another window to take focus.
5/Prevent mode switch at presentation level.
Since on my application I got access to when presentation occurs, I use the following routine (before to call Present)
-Get Foreground window handle (using GetForegroundWindow), If Foreground handle is our fullscreen window, just call Present as usual.
If Foreground handle is not our fullscreen window, perform the following. Please note that visibility check is not needed, since even an invisible overlapping window will also cause a full screen loss! (seriously, this is just so bad...)
-Verify if our foreground window overlaps with the monitor:
Call GetWindowRect to get the bounds, and perform intersection with the monitor location.
Alternatively, call Present on the swapchain with the DXGI_PRESENT_TEST flag. If a window is overlapping, the Present call will return DXGI_STATUS_OCCLUDED
If a window overlaps, either Hide it or move it in another monitor (anywhere so it does not overlap):
ShowWindow and SetWindowPos are aperfect fit for this task.
Repeat that Test present call in a loop until it doesn't return the occluded status (this is important, since windows might not have processed the messages immediately); Once occluded flag is gone, call Present as usual.
There is a way to prevent DXGI from automatically leaving fullscreen mode when your process loses focus, though I must warn, it is a bit hackish.
Basically DXGI calls GetForegroundWindow() and checks if the returned window is yours.
If not, it switches off the fullscreen mode.
So if you hook/redirect this function to your own replacement, that always returns your window (regardless of whether it has the focus or not) - that will get the job done.
Here is a simple code that does that. It is for 64-bit mode and assumes that you NEVER need to call the real function, so it simply overwrites its start with a jump instruction to your replacement:
HWND WINAPI get_our_window()
{
return our_window;
}
void disable_automatic_leaving_fullscreen_on_lost_focus()
{
// get the address of GetForegroundWindow
char *p = (char *)GetProcAddress(GetModuleHandleA("user32.dll"), "GetForegroundWindow");
// make the function code writable
DWORD old;
VirtualProtect(p, 12, PAGE_EXECUTE_WRITECOPY, &old);
// overwrite the function start:
// mov rax, <address_of_GetOurWindow>
p[0] = 0x48, p[1] = 0xB8, *(void **)(p + 2) = (void *)get_our_window;
// jmp rax
p[10] = 0xFF, p[11] = 0xE0;
}
This code is only for demonstration.
If you need to retain the ability to call the true function, then you have to hook it in a different, more complicated way, but this is a separate subject

Can a window be resized past the screen size/offscreen?

My purpose is to size a window to a width/height greater than the size of my physical screen programmatically under Win32. How can I do this?
On my systems it seems the maximum size of a given window is bound by the size of my screen whether programmatically or whether sizing manually by dragging the sizing cursor.
I have tried programmatically with SetWindowPos() and MoveWindow() and both cap the size of the target window. Oddly I know some people do not have this 'cap' so I wonder whether this is perhaps due to some OS setting (registry). Does anyone know something about this? Or perhaps some way to workaround it?
// Edit: new developments
I am testing on Windows XP and Windows 7. The graphics cards I'm using are a NVIDIA Quadro NVS 290 (256MB) and a Geforce 9800GT (1GB). After further investigation it looks like Windows is intercepting the message and fiddling with the parameters. For example, if you call SetWindowPos to make a target 2000x2000 it will only receive a WM_SIZE for the capped x/y.
Implement a message handler for WM_GETMINMAXINFO to stop Windows from applying the sane default behavior:
case WM_GETMINMAXINFO: {
DefWindowProc(hWnd, message, wParam, lParam);
MINMAXINFO* pmmi = (MINMAXINFO*)lParam;
pmmi->ptMaxTrackSize.x = 2000;
pmmi->ptMaxTrackSize.y = 2000;
return 0;
}
Windows with a thick frame (to allow user resize) are restricted from growing larger than the desktop.
Try SetWindowLong() clearing the THICKFRAME (0x40000) flag.
The following should allow programatic sizing, but the user will lose the ability to resize. If you add the Thickframe back after sizing, the user can resize, but when he does so the window will immediately shrink back to the desktop limited size.
The following is from some csharp code that also removes all borders, caption, etc:
WS style = (WS)GetWindowLong(ptr, GWL_STYLE);
style = style & ~WS.BORDER & ~WS.ThickFrame & ~WS.SYSMENU & ~WS.CAPTION | WS.POPUP;
SetWindowLong(ptr, GWL_STYLE, (int)style);
A good tool to play with window settings is uuSpy.
It's like Microsoft Spy++, but allows you to modify settings like THICKFRAME.
Yes, windows can be larger than the screen (or even the sum of all your monitors). Windows can also be positioned off-screen (which some applications do as a hack to hide while remaining active).
Perhaps the Windows 7 desktop manager is kicking in and trying to "dock" those windows to the edges of your screen for you.
You might try using the slightly lower-level API SetWindowPos, which gives you control over notifications, z-order, and other stuff.
You can get a window to be larger in resolution (and even way way larger) than your screen, using the 'Infinte Screen" software:
http://ynea.futureware.at/cgi-bin/infinite_screen.pl
Here's how to use it:
Download it, run it.
In the Oversize tab, choose the Windows you want to enlarge.
Give it the Width and Height you want. Done!
Just in case you need a large screenshot (that's how I ended up here):
If you want to get a screenshot of the window, you've got a screenshot option in the same Oversize tab. (Because screenshots are normally no bigger than the screen size, even if the window is larger). Another (and better) way to screenshot the window is using Greenshot, as you can save them in .tiff and directly watching the window.

Unknown extended window style values from GetWindowLong and GetWindowInfo

I am calling querying the extended window styles of a window using the GetWindowLog property and it is returning values in many cases that are not documented in msdn.
Particularly 0x00000800L and 0x00000100L or a combination of the two. Does anyone have information about these values, or a more complete list than what is documented on the msdn site?
I ran across this thread while looking for an answer to why this value changes when Microsoft Word "disappears" a window. I maintain an app that tracks the HWND values in order to do application sharing. This works well, but Microsoft Office applications often handle these in unusual ways. In this particular case, I found that if you do the following in Microsoft Word 2013:
Open two new documents in separate windows.
Save the HWND values for both windows.
Close one of the two windows.
Both HWND values will, when interrogated with the IsWindow, IsVisible, etc Windows functions, appear to be normal, still visible, etc. There's no way I can find to tell that one of the windows has been closed -- except this undocumented dwExStyle value. 0x800 will be 'on' in the window that's still visible, and 'off' in the window that isn't visible any more.
(BTW, I know you're not "supposed" to save HWND values this way -- but try tracking windows for sharing without saving this value -- not so easy!)
Since 0x00000100L is listed right on the Extended Window Styles page it is a little unclear to me if you mean the normal or extended style so I'll describe both.
Style:
Dialog & old (user32) controls
0xFFFF for control/dialog specific styles
Common control:
0x00FF is generally used by the shared common control styles (CCS_NORESIZE, CCS_TOP etc)
0xFF00 for control specific styles, for a toolbar you would have TBSTYLE_LIST, TBSTYLE_TRANSPARENT etc
ExStyle:
0x00000100L=WS_EX_WINDOWEDGE
0x00000800L=Don't know, undocumented flag maybe (Edit: ReactOS has/had 0x00000800 as WS_EX_MAKEVISIBLEWHENUNGHOSTED, that does not mean that it has the same meaning on windows since ReactOS is not 100% compatible with windows)
Jeremy, this is just a bug of GetWindowInfo (for any OS after Win98: 2k, XP, Vista, Win7).
see http://rsdn.ru/forum/winapi/3362548.all.aspx ("WINDOWINFO.dwExStyle error")
try small tester therefrom: http://files.rsdn.ru/42164/wi_exstyle.zip
kero

Carbon Accessibility API - Getting windows information across spaces

I have the following (minor) problem that I want to solve programmatically. Whenever I unplug my secondary monitor from my laptop, every windows get moved to be visible in the now smaller resolution. When I plug my external monitor back in, I need to manually replace the windows to their correct position. I have to do that every morning (sigh).
Now I decided to write a simple command-line program that could save the position of every open windows and reposition them when I want to restore their positions.
I have managed to do something that works just fine by using the Accessibility API, which allows me to control windows that aren't part of my process space. I have a problem though: the program can only see the windows that are in my current space (I'm talking about the OSX Spaces feature here).
In other words, when I run my program to save the windows positions, it will only be able to save the positions of the windows in the space I'm currently in.
Some more details about my program:
It loops through all the processes running and get their PIDs.
It creates application elements from these PIDs (AXUIElementCreateApplication)
It gets the windows associated with this application, and then their positions
When getting the windows elements from the application element, the AXUIElementCopyAttributeValues only returns me the windows of the current space.
Now, is there a way to control any windows (across different spaces)? If not, I wouldn't mind programmatically changing spaces to get every windows, but that doesn't seem possible.
Any help would be appreciated!
I'm not aware of a documented way to switch spaces.
You probably want CGSPrivate.h - CGSSetWorkspace et al. Just keep in mind those functions are SPI and can break without warning even in a 10.6.x release.
If you want to avoid using private APIs you can take advantage of the fact Mission Control has keyboard shortcuts for moving to various spaces, and you can programmatically send the key codes to activate them. I wrote a blog post about it (http://ianyh.com/blog/2013/06/05/accessibility/) for a tiling window manager I've been working on called Amethyst, which has some example code you can check out in -[AMWindow moveToSpace:].
The short version is moving to a space looks something like using the default ctrl + arrow key to move to adjacent spaces:
CGEventRef keyboardDownEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, true);
CGEventRef keyboardUpEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, false);
CGEventSetFlags(keyboardDownEvent, kCGEventFlagMaskControl);
CGEventSetFlags(keyboardUpEvent, 0);
CGEventPost(kCGHIDEventTap, keyboardDownEvent);
CGEventPost(kCGHIDEventTap, keyboardUpEvent);
CFRelease(keyboardEvent);
CFRelease(keyboardEventUp);
You could combine this with NSWorkspaceActiveSpaceDidChangeNotification to traverse all spaces and gather window data.
Also, as a potentially interesting note the accessibility APIs can actually give you windows across all spaces at the same time, but it will only give you windows in spaces that you have traversed to since the process utilizing the APIs launched. I have no idea why this is the case, but it does seem to be.

Why is the Windows cmd.exe limited to 80 characters wide?

I love stretching my terminal on unix. What is the history or reason behind windows lame command line?
It isn't. You can right click the title bar, select properties, and in the "Layout" tab alter the screen buffer size (line width and scrollback) and the window size (viewport size). If you started cmd from a shortcut, you can save these settings for future sessions.
If you are mouse-phobic you can also just type this inside the cmd window:
mode <cols>,<lines>
mode 80,25
mode 120,50
etc.
It's not limited.
Run cmd.exe
Click on the icon in the upper left hand of the screen.
Select Properties
Select the Layout tab.
Set the buffer and window widths to whatever you like.
Click OK
Select Save Properties for future...
Click OK.
You might want to check out Console. It's an open source app that lets you run multiple shells in a tabbed environment. You can also set the alpha-transparency of the shells.
RE: Because MS value "backwards compatibility" over a lot of things and in this case I suspect it's a misplaced belief that it will somehow unnerve people if they don't have their standard 80 wide window.
The backwards compatibility works pretty terribly, though. I don't imagine Microsoft was pretty thorough about their implementation of it, and I do believe Microsoft is the poster boy for making sure newer versions won't work on older versions. A lot doesn't work properly under COMMAND.COM, which considerably sabotages the usefulness it possesses, not to mention that you have to enter DOSONLY to make some programs run properly, plus Microsoft has been removing useful commands. Honestly, I can't imagine Microsoft holds "backwards compatibility" in much of a high regard.
Furthermore, I think the real reason why the line length is at a standard of 80 columns is because most command-line programs, etc. operate under the assumption that the user is capped at an 80 column prompt, meaning that increasing the width can cause formatting errors or worse possibly break programs altogether.
As jmucchiello mentioned, MODE will work fine for resizing the window if you feel like it.
Configures system devices.
Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s]
[to=on|off] [xon=on|off] [odsr=on|off]
[octs=on|off] [dtr=on|off|hs]
[rts=on|off|hs|tg] [idsr=on|off]
Device Status: MODE [device] [/STATUS]
Redirect printing: MODE LPTn[:]=COMm[:]
Select code page: MODE CON[:] CP SELECT=yyy
Code page status: MODE CON[:] CP [/STATUS]
Display mode: MODE CON[:] [COLS=c] [LINES=n]
Typematic rate: MODE CON[:] [RATE=r DELAY=d]
If you have DOSONLY enabled on your CONFIG.NT, however, when you open COMMAND.COM, it will inherit a proper DOS-style line resolution from cmd.exe, but you cannot invoke MODE from inside COMMAND.COM. If you wish to resize inside COMMAND.COM, you will have to use 16-bit assembly instructions, like so:
80x50 Line Resolution (No framebuffer, no SVGA, virtually universally supported.)
DEBUG
A100
MOV AX,1112
INT 10
INT 20
G
Q
132x60 Line Resolution (No framebuffer, requires SVGA. Won't work on ATI gfx cards, usually works on nVidia gfx cards, afaict always works on Intel integrated gfx cards.)
DEBUG
A100
MOV AX,4F02
MOV BX,010C
INT 10
INT 20
G
Q
If you enter this on your COMMAND.COM, it will give you the specified resolution. (Warning: If your monitor is ancient enough not to support the mode, you might wind up destroying it. Side-note: If you can run Windows, your monitor should be fine. Disclaimer: Emphasis on should, and you've been warned, so it's not my problem if your monitor fries. ;-) However, if you use this without DOSONLY enabled, COMMAND.COM will resize back to its previous size as soon as the application (in this case, unless you wrote it to a file and executed that, DEBUG) exits.
Alternatively, you could use FreeDOS's MODE.COM, which will run properly under COMMAND.COM set to DOSONLY. You can either pull it from the disk image at the official website (freedos.org) or get it at http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/dos/mode/2005/.
New FreeDOS MODE by Eric Auer 2003-2005. License: GPL. (version 12may2005)
MODE [device] [/STA[TUS]] (show status of one or all devices)
MODE LPTn[:] cols[,[lines][,retry]] (cols or cpi, 6/8 lpi, retry p or n)
MODE LPTn[:] [COLS=...] [LINES=...] [RETRY=...] (retry: p infinite / n none)
MODE LPTn[:]=[COMn[:]|NUL] (redirect printer data to serial port or NUL)
MODE COMn[:] baud,parity,data,stop,retry (empty values allowed)
MODE COMn[:] [BAUD[HARD]=...] [PARITY=...] [DATA=...] [STOP=...] [RETRY=...]
Baud can be abbreviated to unique prefix, parity can be o/e/n/s/m, the
latter 2 mean space/mark, data can be 5..8, stop 1..2. Retry is IGNORED!
PLANNED: Retry b/e/r -> busy/error/ready if busy, p/n infinite/no retry.
MODE CON[:] [CP|CODEPAGE] [/STA[TUS]] (FreeDOS DISPLAY must be loaded)
MODE CON[:] [CP|CODEPAGE] REF[RESH] (needs DISPLAY)
MODE CON[:] [CP|CODEPAGE] SEL[ECT]=number (needs DISPLAY)
MODE CON[:] [CP|CODEPAGE] PREP[ARE]=((codepage) filename) (needs DISPLAY)
Use PREP=((,cp2,cp3,,cp5) ...) to prep codepages in other buffers.
MODE [40|80|BW40|BW80|CO40|CO80|MONO][,rows] (rows can be 25, 28, 43 or 50)
Use 8, 14 or 16 as 'rows' value if you only want to change the font.
MODE [CO40|CO80|...],[R|L][,T] (shift CGA left/right, T is interactive mode)
MODE CON[:] [NUMLOCK|CAPSLOCK|SCROLLLOCK|SWITCHAR]=value
Value can be: + or - for the locks or a character for switchar.
MODE CON[:] [COLS=...] [LINES=...] (possible values depend on your hardware)
MODE CON[:] [RATE=...] [DELAY=...] (default rate 20, default delay 1)
Rate can be 1..32 for 2..30 char/sec, delay can be 1..4 for 1/4..4/4 sec.
For the same reasons as with the ASM code I provided, unless you execute it in COMMAND.COM with DOSONLY added to your CONFIG.NT file, the window will immediately rebound to its previous size once MODE.COM exits.
Lastly, as others have stated, it is also possible to modify these settings simply by right clicking on the command prompt's title bar, and modifying Properties -> Layout. Similarly, you can set the resolution for any shortcuts to CMD.EXE and batch files (Right click the shortcut -> Properties -> Layout). This only works for CMD.EXE, however, not COMMAND.COM.
A simple command to fix the window size that I use all the time:
wmic
It will open the Windows Management Instrumentation Command-line and remove the size limits.
Then just close it with Ctrl+C.
I don't know the history behind it, but this wishlist item from the author of PuTTy is an interesting post that explains the technical hurdles involved with any type of cmd.exe replacement that isn't lame:
http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/win-command-prompt.html
You don't mention that you're looking for a replacement, but if so you might also check out some of the cmd.exe replacements like Console 2 or JP Software's Take Command etc. I've also had some good experiences with PuTTy-Cyg which lets you use PuTTy as a cygwin shell.
While the width is not limited as other answers show, I've always found it strange that one can drag and resize the height with the mouse, but not the width.
I think the default 80 character width is related to compatibility with old programs that assume the terminal won't be more than 80 characters wide. I don't think this has been a realistic reason for a decade or so, though.
As others have pointed out, it's not limited to 80 characters wide, but my guess as to why it defaults to 80 characters would be that it's left over from the DOS days where CRT displays were 80 characters wide.
See also
You could also use a different terminal application, such as Console2, which allows you to resize the window all you want (among other things, such as transparency, and the ability to use any font you'd like). It's a great application, I've switched to it and now I only use cmd.exe when I absolutely have to.
Since it will scroll left to right as well as up and down, the very first thing I do on a system is define my width as 180 and save it. That's generally enough so that stack traces don't have to wrap for the most part, but not so much that you are waisting a ton of space.
While you're at it, set the vertical size (scrollback buffer) to all 9's. You'll be glad you did some day.
Because MS value "backwards compatibility" over a lot of things and in this case I suspect it's a misplaced belief that it will somehow unnerve people if they don't have their standard 80 wide window.
Of course it could be that it was programmed for a fixed 80 chars width when that was pretty much universal, and the additional property settings were a bit of a hack.
It IS limited. Check it out. (I mean window size NOT buffer)
You will find that the maximum width you can set is limited but varies according to your screen resolution. If your resolution is set to 1024 x 768 you will find that you can only get to 128 on the command prompt width. 128/1024=.125
you will find that ratio to be consistent across the board. I have an RDP session running at 2000x768 (across two of my three monitors) and get a max width of 250.
Now, that actaully turns out to be a little bigger than your actaul monitor size but I have three monitors all running individual desktops. (so in essence, 3 1024x768 resolutions) and if I want to do something SO SIMPLE as stretch a command prompt across 2 or more monitors, I CAN'T. (I want to when doing things with very long paths (diruse.exe/etc.)...
-c
This isn't closed. So it should be noted that Windows Terminal is now is changing all of this:
https://github.com/microsoft/terminal
https://www.theverge.com/2020/1/9/21059316/microsoft-windows-terminal-crt-effects-retro-search-tabs-features
https://devblogs.microsoft.com/commandline/windows-command-line-backgrounder/
https://github.com/microsoft/terminal/blob/master/doc/terminal-v1-roadmap.md
https://www.microsoft.com/en-us/p/windows-terminal-preview/9n0dx20hk701?activetab=pivot:overviewtab
Because improving the usability and functionality of anything that Unix/GNU-like development requires will undermine Windows as a commercial platform for Microsoft's partners. Preventing this means other large companies' products for developers, such as improved terminals, and other general third party products, like word processors, video players etc. aren't competing with existing Unix/GNU software. Without this, Windows wouldn't be a profitable platform, and Microsoft would lose its desktop monopoly.
This is why the terminal sucks, there's no POSIX API, no C99 support in MSVC and the list goes on. To clarify, common Unix/GNU technologies and development are intentionally unsupported so that large commercial software houses don't have to compete with them.

Resources