Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 730
  • Last Modified:

Change DOS Font size programatically

I am using Windows NT currently, though we may upgrade to XP in a year or so.
In the properties of a running DOS prompt, there is a Font tab, which allows you to change the size and type of font, and immediately apply this to the current window. The changes are applied during runtime.

Now the DOS application we have made can change its columns from 80 to 132 depending on what information we need to display, however, when we change to width 132, the window takes up considerably more area than we want it to (80->132 is more than half again the original window width). We'd prefer instead to decrease the font size, and keep the window size about the same.

So, the question is, how can we programatically change the font size/font of a DOS application during runtime?
0
Crius
Asked:
Crius
1 Solution
 
jkrCommented:
You can read and alter all the console settings under HKEY_CURRENT_USER\Console\ - note that there might be subkeys specifying settings that belong to certain console mode executables.
0
 
CriusAuthor Commented:
Will this work while the console app is running? I don't want to have to restart the console app to get these changes since this width change is dynamic within the console app itself.

Typically, changing registry settings requires at least a program restart, if not, a windows restart. Would I need anything else to effect the change without restarting the console app?
0
 
DanRollinsCommented:
It seems possible... after all, one can press

 Alt+Shift+Space
 P
 Alt+S
 8
 Enter
 Enter

and set the font size to Lucida 8 pt immediately.

But I can't locate any API access to those interal settings (You already know about HKCU/Console/<console name> in the registery.

As one thing to try:  I monitored the registry while doing that sequence above and I noticed one odd thing... it seems the console handler does a GetConsoleOuputCP() followed by a SetConsoleOutputCp().  It also sets HKCU/Console/CurrentPage to a dword value of 0x01 (even though it is already set at that) These actions may trigger the system to re-examine registery settings.
=-=-=-=-=-=-=-=-
If nothing else works, you could try GetConsoleHWND and post a series of keystrokes as described above.
=-=-=-=-=-=-=-=-
And finally, I hope that you know that what you are doing is completely foolish.  If you want font control, you should use this wonderful thing called the Windows GUI.

-- Dan
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
CriusAuthor Commented:
I too was unable to find any API anywhere. I will try this method today to see if it works.

And yes, I know this *seems* completely foolish, but the program exists, and has existed for about 18 years, and originally on the Vax (CHUI). It is far easier to do this foolish thing than to try to convert the entire CHUI interface to a GUI interface. :)
0
 
CriusAuthor Commented:
Fooling with the registry (within the app), then setting the OutputCP to itself, and setting the CurrentPage to 1 did not alter the font in any way. I've confirmed that the settings are correct, and do take place when the application is restarted.

Any other possible methods?

     unsigned char WorkCharStr[100];
     unsigned long WorkLong = 100;
     HKEY hKey;
     
     RegOpenKeyEx(HKEY_CURRENT_USER,
         TEXT("Console\\D:_dvl_TESTAPP_Debug_TESTAPP.exe"),
         0,
         KEY_QUERY_VALUE,
         &hKey);
     
     RegQueryValueEx(hKey,
         TEXT("FaceName"),
         NULL,
         NULL,
         WorkCharStr,
         &WorkLong);
     if(strcmp((char *)WorkCharStr, "Lucida Console"))
         strcpy((char *)WorkCharStr, "Lucida Console");
     else
         strcpy((char *)WorkCharStr, "Andale Mono");
     
     RegCloseKey(hKey);

     RegOpenKeyEx(HKEY_CURRENT_USER,
         TEXT("Console\\D:_dvl_TESTAPP_Debug_TESTAPP.exe"),
         0,
         KEY_SET_VALUE,
         &hKey);

     RegSetValueEx(hKey,
         TEXT("FaceName"),
         NULL,
         REG_SZ,
         WorkCharStr,
         strlen((char *)WorkCharStr)+1);
     
     RegCloseKey(hKey);

     SetConsoleOutputCP(GetConsoleOutputCP());
     
     RegOpenKeyEx(HKEY_CURRENT_USER,
         TEXT("Console"),
         0,
         KEY_SET_VALUE,
         &hKey);
     strcpy((char *)WorkCharStr, "1");
     RegSetValueEx(hKey,
         TEXT("CurrentPage"),
         NULL,
         REG_DWORD,
         WorkCharStr,
         strlen((char *)WorkCharStr)+1);
     
     RegCloseKey(hKey);
0
 
CriusAuthor Commented:
Oh, before I forget, I don't see how PostMessaging the keys will work either since as soon as you hit Alt+Shift+Space, that triggers a menu, and from a previous question we both tried to answer, you know how difficult life gets when that happens. The menu triggers a modal-like loop and no more code can run to push keys or buttons. Worse, it's on another window, so we'd have to get that window handle too, which opens the property window, which we'd have to get, and interact with... Basically, the focus changes are horrible, and even if we could do all this, if the user had another properties window open somewhere, we might operate on it instead, and Boom! Face explosion.
0
 
CriusAuthor Commented:
The ideal solution would be to simulate the "Apply properties to current window only" button. But simulating either button is fine.
0
 
DanRollinsCommented:
A quick check with Spy++ showed that the Owner window for the "Command Prompt Properties" window is the console window, so knowing the HWND of the console, it should be easy to identify which of these windows to direct the keystrokes (and to be honest, don't you think it would be rather unusual to have several console property sheets open simultaneously?).  

>>and from a previous question we both tried to answer
I don't recall the question

Also PostMessage is asynchronous.  You can pile up a bunch of them and the target window will fetch them in the order in which they were posted.

-- Dan
0
 
Da_WeaselCommented:
There is a very limited set of Console APIs available.

SetConsoleTextAttribute is the only thing I know of, and this only work for data output by the WriteConsole API, and a couple others.

Your best bet is to use the registry settings to modify the look.
0
 
CriusAuthor Commented:
I already checked that API, but all out text output is with printf and similar functions. :( This is why I put 300 points into this rather tough question.

I'll wait a bit for another option, because unless I can cause the console to reload at runtime, it's not going to work.

I also fear posting keystrokes since dialogs do popup (it's a really bad hack at best), and I don't believe it'll work. Has anyone tried doing it?
0
 
DanRollinsCommented:
This looks promising:  The VB documentation for the OLEObject object that I found under the RichTextBox control dox:

   http://msdn.microsoft.com/library/en-us/rtfbox98/html/vbobjOLEObjectObjectOLEObjectsCollection.asp

It appears to have properties such as Height and Width and methods such as DoVerb.

-- Dan
0
 
CriusAuthor Commented:
I'm sorry, you've gotten me a bit confused.. DOS doesn't support OLE objects... Which are, things like pictures, activeX controls, et al.

Could you please help me out with your train of thought?
0
 
DanRollinsCommented:
Well that explains twhat happened to tha other post.  Sorry... wrong window.
-- Dan
0
 
CriusAuthor Commented:
No problem. :)

I guess I should explain why I feel PostMessage won't work...
When you open up a menu, the menu starts a new non-message processing loop as it waits for you to either select a menu item, or close the menu. If you don't believe me, try to move the cursor to the menu down 1 by simulating keypresses. It won't work.

You and I (Dan) tried to answer someone else's question as to how they could change the default menu item, so it would select something other than the top menu item. We couldn't do it. I'm pretty sure that question is still open somewhere, but since search is disabled, I can't find it.

Since we Posted a message, and that message opened the menu, we can assume that the second message we posted would be handled by that same thread. So, it would never get to the second message because the thread would be stuck in this menu processing loop. We'd be stuck basically, until the user either closed the menu, or picked an item, at which point, the next message would likely be processed.
0
 
DanRollinsCommented:


#include <windows.h>

//----------------------- this fn from MSDN ID: Q124103
HWND GetConsoleHwnd(void)
{
     #define MY_BUFSIZE 1024 // Buffer size for console window titles.
     HWND hwndFound;         // This is what is returned to the caller.
     char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated WindowTitle.
     char pszOldWindowTitle[MY_BUFSIZE]; // Contains original WindowTitle.

     // Fetch current window title.
     GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);

     // Format a "unique" NewWindowTitle.
     wsprintf(pszNewWindowTitle,"%d/%d", GetTickCount(),GetCurrentProcessId() );
     SetConsoleTitle(pszNewWindowTitle); // Change current window title.
     Sleep(40); // Ensure window title has been updated.
     hwndFound=FindWindow(NULL, pszNewWindowTitle); // Look for NewWindowTitle.
     SetConsoleTitle(pszOldWindowTitle); // Restore original window title.
     return(hwndFound);
}


void main()
{
     HWND  hwndCon= GetConsoleHwnd();
     HMENU hmnuCon= GetSystemMenu( hwndCon, FALSE /*fRevert*/ );

     char szBuf[100];
     MENUITEMINFO rMII;
     rMII.cbSize= sizeof( rMII );
     rMII.fMask= MIIM_STRING;
     rMII.dwTypeData= szBuf;

     BOOL fRet= GetMenuItemInfo(hmnuCon, 9, TRUE, &rMII ); // item 9 in the menu
 
     if ( strcmp( szBuf, "&Properties") != 0 ) {
          ::MessageBox( hwndCon, "woopsiedaisy","OOPS!", MB_OK );
     } else {
          ::MessageBox( hwndCon, "found Properties item in the Menu" ,"KEWL!", MB_OK );
     }

     rMII.fMask= MIIM_ID;
     fRet= GetMenuItemInfo(hmnuCon, 9, TRUE, &rMII );

     SendMessage( hwndCon, WM_SYSCOMMAND, rMII.wID, 0 );
     Sleep(1000); // give it some time
     ... here you could find the prop dlg windo and post some keystroks
        .... (hint" ALT+S, '8', Enter, wait, Enter)
     
     ::MessageBox( hwndCon, "...waiting...","KEWL!", MB_OK );
}

-- Dan
0
 
CriusAuthor Commented:
After mentioning the only way we could come up with would cause the dialog to pop up, and be manipulated, it was decided it'd be better to just not have the ability. The smallish project was cancelled, and I don't know if this code will work or not, but, I guess my problems are gone one way or the other.

It looks like, by triggering the menu item directly, we avoid the modal loop caused when you bring up a menu, so, chances are this code will work - although since the properties dialog window would be visible, and could be affected by the user while the code is using the dialog, it is a pretty bad hack. Still, it may be there is no one outside of Microsoft who knows how to do it in a better way.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now