Yet Another Code Site |
This page contains tricks that left me thinking "why did I not think of that?" or "you can do that?" or "so that is how they do that!"and other tips that may make your coding a little easier. Here you will find slick C/C++ precompiler tricks, IDE shortcuts and configuration tips, and other bits that do not really belong anywhere else. Much of this is untested, so use it at your own risk. This page will undoubtedly be a mess initially, so please bear with me.
Warning: Some of the code provided below is Delphi/Pascal. It should be easy to convert and, as soon as I have a personal need to use the code, I will convert it to BCB/C++. In the meantime, it looks right to me, so I am adding it to this page in hopes that you will find it useful. If you translate it before I do, please send the code to me so that we can share it with others that follow. On the other hand, if a BCB version is not posted, please do not ask me to do it for you give it a try yourself....
Get access to a private or protected class data member or method without changing the source. (01-06-1999) Go to the trick
Giving an application real-time priority. (02-23-2000) Go to the trick.
Constrain a value to a permitted range of values. (02-14-1999) Go to the trick.
Associate a file extension with an application. (04-14-1999) Go to the trick.
Run an application at Windows startup without putting the application in the Programs | Startup menu. (02-14-1999) Go to the trick.
Unpublish a VCL property. (02-14-1999) Go to the trick.
Disable task switching (e.g., prevent applications from using <Alt-Tab> to change tasks). (02-18-1999) Go to the trick.
Debugging access violations. (04-14-1999) Go to the trick.
Easy source code version comparisons, not merely cheap, but free (at least with Windows 98). (04-17-1999) Go to the trick.
Simple wildcard matching for AnsiStrings. (03-06-2001) Go to the trick.
Get access to a private or protected class data member or method without changing the source.
Borland, for some unfathomable reason, decided to make member data private in many of the VCL classes. I cannot count how many times that this has interfered with my plans. Here is a rather clever way to get around it, (although it is analogous to killing a fly with a surface-to-air missile):
#define private public #define protected public #include <theworld.h> #undef private #undef public
Harold Howe's comments: "Don't laugh. I've used this to get out of jams when there was no other way out than to edit a header file. I usually only define the variables for the one header file that is causing the problem, then I undef them."
Glommed from borland.public.cppbuilder.non-technical newsgroup post by Harold Howe (Team B).
Giving an application real-time priority.
Generally, changing the processing priority is *not* a Good Thing for applications to do. But if you absolutely must change the priorities, Serge Kreutzmann provided the following code and notes:
// HIGH_PRIORITY_CLASS is in most cases a better choice, then the REALTIME_PRIORITY_CLASS // **************************************************** // Fuction changes priority of current process: // // following arguments can be used: // IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, // HIGH_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS // **************************************************** void SetAppPriority(DWORD dwPiority) { // Detemine Process Handle using OpenProcess() and pass it to // SetPriorityClass(): if(!::SetPriorityClass(GetCurrentProcess(),dwPiority)) ShowMessage("Cannot change the Process Priority!"); }
Of course, use this only where absolutely necessary.
Constrain a value to a permitted range of values.
I frequently find myself writing code that looks something like this:
if (x < 1) x = 1; if (x > 10) x = 10;
All I want to do is ensure that x lies between 1 and 10 (in this example). Here is a template that makes this a bit simpler:
template<class T> inline T constrain(const T& value, const T& low,const T& high) { return (high < value) ? high : (value < low) ? low : value; }
With this template defined, you can simply write:
x = constrain(x, 1, 10);
Put this in your toolbox to save a few keystrokes.
Associate a file extension with an application.
From a newsgroup post: "How can I get my application to register a file type with Windows? I would like my application to open when someone double-clicks on one of the files, that the application creates in Explorer." Here is one response:
You have to create some keys in the registry, under HKEY_CLASSES_ROOT:
key: <fileextension> (e.g., .dat, containing the dot) default value: <typename> (e.g., myApp.Datafile) key: <typename> default value: <display name> (displayed in Explorer for the file type) key: <typename>\shell\open\command default value: <full executable path> "%1"
Use RegEdit to examine some existing entries, e.g., for the *.txt extension.
Another response:
Assuming you can write to the appropriate areas of the Registry (i.e., you are not running under WinNT with funky security problems) then you can create a key structure similar to this:
HKEY_CLASSES_ROOT\.ext (Default) "MyProg.File"
This sets the association between the file extension ".ext" with the type "MyProg.File":
HKEY_CLASSES_ROOT\MyProg.File (Default) "Type Description" HKEY_CLASSES_ROOT\MyProg.File\Shell\Open\Command (Default) "c:\path\myprog.exe "%1""
Those three values will launch the program "c:\path\myprog.exe" in response to a double-click in Explorer (or right-click and select 'Open'), passing the name of the file that you double-clicked on.
You might also want to set a default icon for your new filetype:
HKEY_CLASSES_ROOT\MyProg.File\DefaultIcon (Default) "F:\WIN95\SYSTEM\shell32.dll,-154"
(I yanked that icon declaration out of the Win95 registry entry for 'vxdfile' - play around with it, or add icons to your program for your files).
Glommed from borland.public.delphi.winapi newsgroup posts by Peter Below (TeamB) and Corey Murtagh.
Run an application at Windows startup without putting the application in the Programs | Startup menu.
A netizen asked: "I don't want to use the StartUp group. How can I have a program run on Win95/98 start (a la the "load" and "run" entries in win.ini)?" Yoto Yotov, a quite reliable source, gave this (edited) advice:
Add a value to the Registry entry: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. Example: Name: MyApp Data: "c:\myapppath\myappname.exe" Visit "The Bits" (http://www.cbuilder.dthomas.co.uk) for some tutorials on how to edit the registry.
Glommed from borland.public.cppbuilder.language newsgroup post by Yoto Yotov.
Another newsgroup question: "Is there a way to 'unpublish' inherited published properties, so that they are not displayed by the object inspector?" Frankly, I thought that this was pretty close to impossible, especially given Borland's "you cannot unpublish properties" commentary in several sources. Here is slightly edited advice that solves the problem imperfectly, but adequately:
Assume that the component you inherit from is TDummy:
TDummy = class (TComponent) published property DummyProperty : String read GetDummyProperty write SetDummyProperty; end;
Then you want your component to inherit from this (stupid) component:
TDummyEx = class (TDummy) ... end;
To hide the property, just do this:
TDummyEx = class(TDummy) ... published property DummyProperty : String read GetDummyProperty; end;
You tell Delphi that this property becomes read-only, and then it won't show it in the object inspector. If you (the component developer) need to modify this property value by code just call the inherited one. If GetDummyProperty was private (bad!), just make a wrapper method to call the inherited one:
TDummyEx = class(TDummy) ... protected function GetMyDummyProperty : String; published property DummyProperty : String read GetMyDummyProperty; end; with: function TDummyEx.GetMyDummyProperty : String; begin result := inherited DummyProperty; end;
Although the example is Delphi code, I am pretty sure that I have used this same technique (admittedly, by accident) with the same results in BCB.
Glommed from borland.public.delphi.vcl.components.writing newsgroup post by Olivier Deckmyn.
Disable task switching (e.g., prevent applications from using <Alt-Tab> to change tasks).
A surprising number of newsgroup posts ask how to prevent users from changing to another task. I must admit that I find this to be an odd request why would anyone want to subvert the normal Win95 user interface? And there is typically no justification for these requests. Frankly, I do not wish to find that most of my application software behaves in this fashion and, worse yet, I find myself questioning why anyone would want to do this. However, it is so simple that anyone that thinks this is desirable and necessary can easily find the solution, so I will share it here.
The solution is to trick Windows into thinking that a screen saver is running. Here is a post answered, once again, by the knowledgeable Mr. Yotov.
Question: How do I prevent task switching (Alt-Tab, Ctrl-Esc, Ctrl-Alt-Del) in my application?
Answer: Preventing a user from switching to another application is possible under Windows 95 [and Win98 ed] and earlier versions of Windows by tricking Windows into thinking the screen saver is running. This method does not work under Windows NT and is not guaranteed to be available in future versions of Windows. Many versions of Windows may also respond to a task switching trap installed by a CBT (Computer Based Training) application hook. To prevent task switching under Windows NT, you will need access to a third party keyboard device device driver.
The following code will trick Windows 3.1/95 [and 98 ed] into believing that the screen saver is running:
unsigned long OldValue; //turns trap on SystemParametersInfo(97, true, &OldValue, 0); //turns trap off SystemParametersInfo(97, false, &OldValue, 0);
Glommed from borland.public.cppbuilder.language newsgroup post by Yoto Yotov.
Debugging is a pain, especially when you get uninformative errors from the operating system. For example, a developer posted this problem: An access violation occurred when he closed his program. The following edited and partial answer demonstrates a generally useful technique.
The access violation dialog should say that an access violation happened at XXXXXX: read of address YYYYYY. Try running your program in the debugger. Pause the program and bring up the view CPU pane. In the upper left pane, right click and select Go To Address. Go to the address that caused the access violation. Look around a little bit and see if you can find where you are in the program.
Insert some breakpoints and try to close the program. When you hit a breakpoint, view the call stack and see if it gives any clues.
Glommed from borland.public.cppbuilder.language newsgroup post by Harold Howe (TeamB).
Easy source code version comparisons, not merely cheap, but free (at least with Windows 98).
I frequently find myself trying to identify the differences between two versions of a source file. Usually, the code worked before making several changes, now it is broken, and I do not recall what I did. If only I had a tool for comparing the old and new versions....
Well, Microsoft had already come to my rescue I just did not know it. I stumbled upon Start Menu | Programs | Accessories | Windows 98 Resource Kit | Tools Management Console, a freebie from the Windows 98 upgrade disk. The Console has a number of useful tools including a source code comparison utility called WinDiff.
WinDiff is pretty neat. It allows you to enter two directories to compare. It then identifies the files that exist in only one or the other directory, the files that exist in both directories, and, for these, which are the same and which are different. From this list you can open a file that exists in both directories with a click. This displays the files with lines that were added, deleted, or changed highlighted in different colors. A creative and effective graphical representation of your current location with respect to differences in the files is presented in a separate pane to the left of the source code.
It took me a while to figure out how to use it (hint spend some time with the help file), but once I did, life got much easier. My only complaint is that selecting the directories to be compared is not done using a Browse Folders dialog. Instead, you must know the full path names of the folders and key them into simple edit boxes. I worked around this annoyance by writing a "launcher" that takes advantage of the documented command line interface to start WinDiff with a pair of directories already selected. (If you would like a copy of the WinDiff Launcher executable, drop me an e-mail. If I get enough requests, I will post it on the site.)
If you are interested in this utility, scan your drive(s) for WinDiff.exe. On my machine, it is located at C:\Win98CD\tools\reskit\file\windiff.exe. If you do not find it, look on your Windows 98 installation disk in \tools\reskit\file. If you have Windows 95 or NT, look around and let me know if you find it (and send me the details about where you found it so that I may add the information to this entry).
Simple wildcard matching for AnsiStrings.
The VCL contains an extremely poorly documented class, TMask, that allows wildcard comparisons of strings. TMask works similarly to filename masks, but adds a bit more flexibility and works with AnsiStrings directly.
Ok, that is a bit oblique, so an example may help. Assume that you have an AnsiString called SomeString and you want to know if it begins with "foo" and ends with "bar" with any number of characters between "foo" and "bar". You can use the following to test for this:
// required #include for the TMask class #include "masks.hpp" AnsiString SomeString; bool Matches; TMask* foobarMask = new TMask("foo*bar"); SomeString = "foobar"; Matches = foobarMask->Matches(SomeString); // Matches is true SomeString = "fooXXXbar"; Matches = foobarMask->Matches(SomeString); // Matches is true SomeString = "fobar"; Matches = foobarMask->Matches(SomeString); // Matches is false delete foobarMask;
As you see, '*' matches zero or more characters. You can also use '?' to match exactly one character; "[a-c]" to match exactly one 'a', 'b', or 'c'; and "[!a-c]" to match any character except 'a', 'b', and 'c'. See the BCB help for TMask for more information and, if you are still unsure how it works, play with it a bit....
Home | Top Of Page | Code | Papers | FAQs | Links | Search | Feedback |
Page updated |
Copyright © 1998-2001 Thin Air Enterprises and Robert Dunn. All rights reserved.