Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Commanding the Command window

Status
Not open for further replies.

vfp4ever

Programmer
Oct 18, 2013
71
East Java
G'day everyone,


in an attempt to automate my VFP IDE start, so that I may find it neat and tidy at all times no matter the video resolution or Windows theme currently in use, I am trying to take some control over the Command window as it opens up in the process.

After dealing with the Program Manager, whose window is a child of the main VFP frame, I have successfully been able to locate the other two 'rebel' windows (Command and Document View), get ther handles, size and position them accordingly at startup (they are actually made of 5 or 6 different windows all layered in parent-child and even sibling levels).

As video resolution and themes are closely related to font names and size, now I am challenged with setting these properties. While most of them are located in the Windows Registry and can be easily read and written, those of the 'rebels' are tucked away in the foxuser.dbf table as binary data (under Type PREFW and Id WINDOWCMD). I am not sure whether it could be possible to mess with that binary data and have the font changed programmatically, so I took a different approach and insisted with Windows API calls. To cut the story short, I managed to send a WM_SETFONT message to the Command window (I can see it through BINDEVENT), the font has been set to my desire (as the function GetTextFace reports) but I still see the old font displayed in the window even after calling UpdateWindow or sending WM_PAINT messages.

Please feel free to make any suggestion on this matter, thank you.


Dario
 
Dario,
I believe you should have a close look at File Locations Page (VFP menu -> tools -> options ) here you will also find a setting for vfpstart.prg (the file which is called everytime you startup vfp) this file also allows you to set your development enviroment as you whish including the appearance of the command window.
Stay healthy,
Koen
 
First of all everything you found out is correct and I'm sure you know the command window simply is a window named 'command' you can position with [tt]Move Window 'command' to row,col[/tt]. If you just try MODIFY WINDOW 'command' FONT 'xyz' VFP tells you it was not defined with DEFINE WINDOW, so it is a special IDE window anyway, it only partly works like a legacy Fox window. It's also not in the _screen.forms() collection, just like the project manager windows and some more.

The settings regarding fonts and colors are much less connected to Windows Themes settings than you expect or fear, though. In DEFINE WINDOW you do have COLOR SCHEME and VFP defaults to colors along Windows theme colors, but mainly the syntax coloring you set for code windows overrides that, ie when you define - what I strongly recommend - strings in Editor windows should be colored red, that also applies to strings you write in the command window. So there only is a default and initial dependency on Window themes colors. But maybe you'd like to change exactly that.

Several window types have font and other settings stored in Foxpro options in the registry: HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\9.0
But indeed the command windows is determined by the foxuser records with Id="WINDOWCMD". The binary information in there could be set, just make settings manually and then see what changes there to find out the meaning, I don't know a specification of the structs used in the data memo. The simplest idea is to make the settings you want to make and then write code restoring exactly that binary data, if a change is detected, or simply write it in by default. There are two records, one with name="DEFAULT" one with empty name. Both records change in data when you close VFP after you changed settings. (So fixuser.dbf does not immediately change).

The simplest way to get the binary data into source code is converting to type Q: _cliptext = Transform(CreateBinary(data)) will give you the hex string of data., prefix that with 0h and this is the Q binary string type in source code.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Hello Olaf,

tweaking the foxuser file is what I eventually intended to do as a last option, if nothing else worked. Though in the meantime I found out the simplest approach would be simply calling the function _EdGetEnv (and _EdSetEnv) from the foxtools.fll library (they do exactly what I was trying to do with Windows API calls). Unfortunately I am a bit reluctant to execute code that I did not edit myself, so I might have to write some C lines after ages... But first I would like to understand where I am wrong with Windows API calls.

Dario
 
What you are wrong with Windows API calls?

Well, anything aside of title bar and border/frame of VFP informs is not Windows standard. That's also causing automation tools working on controls to fail with a VFP executable/window.

The only canvas oriented things working are effecting the transparency of windows canvas and some more like that, ie causing rectangles to redraw with InvalidateRect. You don't set the font, colors, etc. the Windows way as VFP draws everything itself with GDI+.

Some VFP window properties are inherited from the informs standard, VFP is C++ and so the C++ TForm class is a reference, eg the HWND property that's so important for many WinAPI calls, then also WindowState and WindowType. But surely not things like FontName, which is the font used when you print to a form. If you do print, you also realize this is destroying the graphics drawn from the VFP controls, so visual form drawing with controls and print command doesn't mix, and once you cause VFP to redraw with form.Cls() all print output will vanish.

Also just notice how alien the concept of ActiveX controls is to have a separate HWND for a single control. VFP supports COM/OLE/ActiveX, but it's already an alien concept not seamless integrating, which you can also feel in many ways, eg try to put VFP controls on top of ActiveX controls and struggle with their visibility at runtime.

Bye, Olaf.

Olaf Doschke Software Engineering
 
By the way, I remember Christof Wollenhaupt used _EdGetEnv and _EdSetEnv in his IntelliSenseX IDE extension which implemented parts of intellisense and autocomplete behaviour before it was a VFP feature (See ISX.prgt.ZIP in
This goes deeper into the Library Construction Kit and VFP API offers for your FLL creation with C++, so you may use that instead of foxtools, but foxtools.fll is part of VFP, it's something you can rely being present, it's just not a library set by default with SET LIBRARY TO, but it is from MS, not from a third party.

Bye, Olaf.

Olaf Doschke Software Engineering
 
I agree, Olaf. Sometimes it feels as if we could do everything with Windows API calls, and forget that, at some point, they will interfere with VFP internals.

Now I am looking at Foxtools.fll to achieve the same purpose, will let you know if I finally succeed.

Regards,
Dario
 
I'm afraid something is wrong here:

Code:
SET LIBRARY TO (HOME( ) + "FOXTOOLS.FLL")
? SET( "LIBRARY" )  && OK --> "C:\PROGRAM FILES (X86)\MICROSOFT VISUAL FOXPRO 9\FOXTOOLS.FLL"

*--- just to be sure I loaded the correct library
? STRFILTER( "12345", "13579" )  && OK --> "135"

*--- I can see the Command window on my IDE
? WEXIST( "Command" )  && OK --> .T.

*--- I get its "VFP" handle
? _WFindTitl( "Command" )  && OK --> 38933912

*--- I check if it corresponds to the Windows handle I get from Windows API functions
? _WhToHWnd( _WFindTitl( "Command" ))  && OK --> 65920

*--- now that's what I want:
DIMENSION laEnv[25]
? _EdGetEnv( _WFindTitl( "Command" ), @laEnv )  && ?? --> 0 (shouldn't I get 1 for "Command" window?)
? laEnv[22], laEnv[23]  && ?? --> "", 0 (I expected something like "Consolas", 11 )

SET LIBRARY TO  && OK --> ""

All of the above commands have been executed in the Command window several times with no success (VFP 9..7423/W 7 Pro), restarting VFP and/or PC multiple times. Unfortunately I have never used this library before, so I cannot guess how reliable it is in different situations.
 
Well, then it only works for editor windows, not command.

So I guess you must set that data memo to keep or set the definition as you want it.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Dario, excuse for jumping in late. Rather than editing the binary data in the Foxuser file, would there be any mileage in your keeping multiple versions of the file, one with each of the desired settings, and then switching between them (via SET RESOURCE TO) in your startup program?

Of course, that would mean losing all the othre resource file settings that have changed during a session (the configuration of a Browse window, for example). So perhaps another option would be to maintain the multiple versions, but to copy the WINDOWCMD record from the relevant file to the actual file.

This is just off the top of my head. If I'm on the wrong track with this, just ignore it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
It's surely a good idea to simply keep versions of foxuser.dbf or more specific the command window record in place for restoration.

I see just one problem remaining: Once you see the actual foxuser.dbf differs from your standard, changing it is too late to take immediate effect. Because as I tested, when you manually change the font that only reflects after a restart. So whatever is read at the start also only is saved at closing VFP. A change made to the active dbf while the IDE runs may also be overwritten again.

What you would need to do is be able to change the dbf before the IDE evaluates it to establish the state of the command window.

And I fear that stage is before what you can configure for the _startup system variable runs. So an EXE with its own foxuser.dbf (or with resource off) would need to care for the IDE foxuser.dbf before the IDE starts.

I totally get why Dario would like to be able to set command window properties at runtime. You might want to cover the case the command window gets lost while you work and you want to reset it with a new system menu item "reset command window". As far as we are you could only set things up for the next VFP start.



And, Dario, maybe you struggle with a slow VFP start. Disabling the Task pane to start with VFP helps a lot. There is a reason it slows the restart of VFP: a record about gotdotnet.com, a website of which the community tab of the task pane manager loads some info. A website, that does not exist anymore, though. This leads to a timeout, but before that timeout, you can't use VFP.

And there is a cure for that:
If you have done that, you may need to redo that step every time you let the VFP IDE create a new foxuser.dbf and let it be at its default content.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Mike, Olaf...

it appears as if you had been misled a bit, the problem is not the resource file. Maybe that was not clear enough in my first post, what I am trying to do is adapt my vfpstart.prg to my current video resolution and theme, so that when I launch VFP its windows (main VFP window, Command, Document View, Project Manager and Editor) arrange themselves neatly without stretching out of the screen or overlapping, and keeping the very same proportions. A font change is also necessary at this stage, as Consolas 11 might look too large on a 1024x768 display, or SegoeUI might look too bad with the Classic theme (still my favourite!). That is why I tried to tweak the Command window using Windows API calls, just to realize that Foxtools.fll allows me to do it very simply with _EdGetEnv and _EdSetEnv.

I have got good news in the meantime, as I found out why the above code did not work. _WFindTitl( "Command" ) returns the VFP handle of the outer window (I said there are five, two titled "Command" and three untitled). _WOnTop( ), on the other hand, returns the correct inner one. I found this short article on the matter: Link

Regards, and many thanks for your most precious ideas
Dario
 
Good to hear that you are making progress, Dario. I only mentioned the resource file because I thought you were considering editing it as one of your options. Not to worry.

That said, if I had this same problem, I think the approach I would have taken would be to create a set of keyboard macros, each of which would make all the required settings, such as changing the font size. Each macro would have a shortcut key. Then, each time I launched VFP, I would simply hit the key combo appropriate for the resolution, etc.

I appreciate that you probably prefer a completely automatic solution, but my approach only requires one keypress per session.

As far as the position of the command window is concerned, I always have mine docked, so - as far as I know - the problem would not arise.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I see. For me, the code you linked to shows errors, for example [tt]IF lnResult 0[/tt] should rather be [tt]IF lnResult<>0[/tt] or =1.

But in the end, it works, yes.

I would have guessed because the command window differs from any other editor window by executing the current line when you ENTER it, that it would remove the ability to use _EgGetEnv() on it, but there's your solution.

In some way, the command window is an editor window because it maintains a _command.ptg stored in your Roaming profile appdata but that filename isn't showing up in the first array element.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Mike,
your thoughts were not wrong at all, as a matter of fact I am still trying to hack the Data field in foxuser.dbf. That is because _EdSetEnv of foxtools.fll does its job perfectly on editor windows (including Command), but not on others (Document View and Project Manager are those I would like to manipulate). I can overcome the problem of checksums by replacing both Data and a given CkVal (corresponding to a specified font name and size), but then the problem is what Olaf clearly explained.

Olaf,
the IF lnResult 0 was a typo, of course an operator != is missing. Indeed I cannot find the way to tell the Document View window to update itself after its foxuser's record has been modified, as it is too late. Also, when the window is closed it immediately overwrites it, too. I need to trigger a different WM_ message before WM_SHOWWINDOW (that is when I save Windows handles in the first place), I believe.
 
I think the only soluton to influnce the IDE by changing the binary data of its fixuser is before starting the IDE, you can't do that from within.

So to get as near as possible to the VFP start, you'd replace your VFP9.exe shortcut with a shortcut to a foxuser maintenance EXE which after preparing the foxuser records according to current themes and screen resolution starts the IDE. This can be a VFP built exe, it doesn't need to be done in C++ and make use of LCK and API calls, but it must of course know which foxuser.dbf to handle, not it's own. Sounds complicated, but it's no big deal, such a restart exe would work on the standard location of a foxuser.dbf in Addbs(GetEnv("APPDATA"))+"Microsoft\Visual Foxpro 9\foxuser.dbf" or you'd make it configurable.

At runtime you can forget to influcne the foxuser. It already is read in and changes made to the windows are only saved at closing VFP as far as I see.

You can set the command window and editor windows. You can influence _screen itself, of course. But I don't see you getting anywhere with other IDE windows. They are really just maintained by the IDE. As far as there are setting you can interactively change, like the font of properties in the property window, I think Mike has the only viable idea to let this be done via keyboard macros. You may need to send them to the windows via Windows API. But you're surely limited. I don't see influence on the font used for tha tab captions of the properties window, for example.

So these either are inherited from the Windows Themes about general appearance of application windows and fonts and sizes, or - just like you can do in your own applications, are only decided by the VFP9.exe itself. To change them would need hacking into the vfp9.exe and I don't think that's a good idea.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Using an external launcher for the IDE is another good idea, Olaf. I have not beaten my head enough to give up trying from inside the IDE, though. After all, I am only aiming at a couple of more windows. I was trying to change foxuser's Data and CkVal from inside the WM_NCCREATE message (one of the earliest that windows receive), but apparently I have problems with checksums now:

Code:
*--- detecting a first WM_NCCREATE message for the "Document View" window
IF lcBuffer == "Document View" .AND. TSys.FirstRun
	LOCAL lcResource AS String
	LOCAL ARRAY laData[1, 1]

	lcResource = SET( "RESOURCE" )
	SET RESOURCE OFF

	SELECT CkVal, CREATEBINARY( Data ) FROM (SYS( 2005 )) WHERE Id == "EDPROCLIST" INTO ARRAY laData
	IF _TALLY == 1
		*--- even replacing the same text within Data is problematic
		laData[1, 2] = STRTRAN( laData[1, 2], CREATEBINARY( "Fira Mono" ), CREATEBINARY( "Fira Mono" ))
		UPDATE (SYS( 2005 )) SET Data = ( "" + laData[1, 2] ), CkVal = VAL( SYS( 2007, ( "" + laData[1, 2] ))) WHERE Id == "EDPROCLIST"

	ENDIF

	SET RESOURCE &lcResource
ENDIF

According to the literature, CkVal should be the result of SYS( 2007, Data ). Some say SUBSTR( Data, 2 ), too. I tried all SUBSTR( Data, x ) but never matched the same CkVal assigned by VFP.

As for macros... I used them a few years back to tell the Project Manager to automatically select the Code tab and highlight the current source file, but sometimes effects were more annoying than pleasing.
 
I don't know about CKVAL rules, so I could also only try. But the idea was to use records with known data. If VFP only accepts them with the right CKVAL checksum, then save whole records for windows you manually set as you want them. Just remember they only change when you exit VFP.

I also think the foxuser.dbf is simply read into memory by the IDE at the start. Whatever you change in SYS(2005) doesn't affect the current session (I said that already). Simply try it in reverse: Manually change the font of a window and then look into the corresponding SYS(2005) record: It's still the data from the start of the IDE. The IDE only updates foxuser when exiting. And changing foxuser.dbf data does not affect the current session (I said that already), your changes get overwritten (I said that already). Your only chance is changing foxuser before the IDE starts.

Keyboard macros have to happen with the focus on the right window, that means you have to do this focusing. But this and _EdSetVal at least work from within. You can do some things from within, changing foxuser will only affect when you do it in advance of the ISE start.

Bye, Olaf.

Olaf Doschke Software Engineering
 
It's not only about the command window anymore, but I see how you get to any window activating menu item.
Some things are not configurable like font in the data session window. And I don't know if you can set something in foxuser for that, instead.
So the whole idea stays problematic and with mixed results anyway.

Bye, Olaf.




Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top