|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionWhen I cleaned up my harddisk lately, I found some ancient text files I created a long time ago. One of them contained "coding tips" and code fragments concerning problems I had to solve during the development of some of my applications. Whenever I found a solution for a specific problem, I pasted the corresponding code into the text file, and now, dozens of self-made applications later, I know what stuff you will run into over and over again:
I present the answers here and hope they come along handy for you and your application; maybe this article even helps saving some of your valuable time. So here we go… 1. Preventing an application from showing up in the taskbarYears ago, a friend of mine came up with the idea for a small digital clock hovering above all other windows with adjustable transparency. I started coding and quickly ran into two major problems: first, the clock application (based on I tried several approaches to get around these problems, and finally found the solution presented below. The trick for "hiding" your application is quite simple: the main dialog window is attached to an "invisible" parent window. That's all, and it's perfectly preventing my clock application from showing up in the taskbar or being accessible via ALT-TAB ever since. Here is the default code generated by MSVC for any new // // Default MSVC init: window will show up in taskbar and is accessible // via ALT+TAB // CTestDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); So, to make your dialog "taskbar-resistent", just use the init method shown below. If you also want to prevent the user from accessing your window using the ALT-TAB taskswitch mechanism, just make your dialog a // // Custom init: Prevent application from showing up in the taskbar // CWnd *pWnd = NULL; if(!::IsWindow(m_Invisible_pWnd.m_hWnd)) { LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0); // Create an invisible parent window if(m_Invisible_pWnd.CreateEx(0, pstrOwnerClass, _T(""), WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, 0)) { pWnd = &m_Invisible_pWnd; } } CTestDlg dlg(pWnd); // "Attach" dialog to the "invisible" parent window m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); Don't forget to add the appropriate definition for class CTestApp : public CWinApp { public: CTestApp(); protected: CWnd m_Invisible_pWnd; // "Invisible" parent window ... 2. Starting an application minimized without flickeringTo start an application minimized (e.g. appearing directly in the tray area), the common way to do this is callingShowWindow(SW_HIDE) as soon as possible, preferably directly after the call to CDialog::OnInitDialog().
This surely does the trick, but every now and then, you will see your main dialog window flickering for a fraction of a second before it is finally hidden or sent to the tray area. This is because the basic window has already been created when A few years from now, when computers operate faster than light, you'll get rid of this annoying flickering automatically, because your Operating System will then hide your window before you even start the corresponding application. But for now, just add this // // Avoid flickering of main window when starting minimized // void CTestDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos) { if(m_bDlgVisible == false) lpwndpos->flags &= ~SWP_SHOWWINDOW; CDialog::OnWindowPosChanging(lpwndpos); } You can also declare an optional boolean member variable ( Note: Adding this message handler to your code will not make your computer operate faster than light. 3. Avoiding multiple starts of your applicationSo you finally coded it, this ultimate application, only to find your beta testers launching it a hundred times, rendering your database useless because your function calls are not MT safe? Well, how about this little code snippet that allows only one instance of your application running at a time. There is more than one approach to check if your application's already running or not. You could, for example, read in the list of running processes on startup and see if you can find your application more than once. But this is kind of overkill and, even more important, it's not cool. It's more efficient (and cool) to create a system-wide unique object (called a "mutex") and check if it already exists when your program starts. If it does exist, all that's left to do then is to exit the recently started instance…et voilà! As an option, you can also broadcast a custom message and grab the HWND of the responding application to perform other magic tricks. Let's do itThe code shown below tries to grab the If you don't need this kind of hocus pocus, you can quietly exit the recently started instance and be at peace. But we want it nice, so first of all, create your own custom message; you do this in the main instance .h file: const UINT WM_ANYBODY_OUT_THERE We use And by the way…you can of course fill in any other message text that fits your needs! And since you're editing the .h file right now, add the following to it: struct SingleInstance { SingleInstance() { // Create a global (and unique) mutex object HANDLE hMutex = CreateMutex(0, FALSE, _T("My very own mutex")); // Failed to create the mutex object: there's an instance of this Looks impressive, doesn't it! And best of all, the majority of this code is optional… But wait! There's one last step to take: add ///////////////////////////////////////////////////////////////////////////// SingleInstance TheOneAndOnly; BOOL CMyApp::InitInstance() { ... And there it is, your ultimate application, blocking any of your beta tester's attempts to start it more than once! 4. Solving the XP gridlines problemYou've probably seen it all before: using a custom The gridlines scrolling bug only applies to systems that have the Smooth Scrolling feature enabled, but you can't go wrong adding (or modifying) the void CMyListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
Invalidate();
UpdateWindow();
}
That was easy! We're just forcing an additional redraw to get things right. If you think it's a waste of valuable CPU time to redraw the control even with Smooth Scrolling disabled, then this might come in handy: // Put this somewhere in your app's init routine SystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &bIsEnabled, 0); This will set Points of InterestAnd that was my box of tricks…I'm not quite sure if any of the topics have already been discussed on this site. Anyway, now they're all together here, and it would be cool if you find them useful. HistoryThis is the very first version of this article, and probably the last one, too, and there's no version number. In fact, there never was one.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||