One of the greatest advantages that Windows applications have over their DOS counterparts is device independence: You don't need to worry about the specific characteristics of the video system or printer you're using. Instead, Windows provides a layer of abstraction that you can use to interface devices that you've never seen or used.
However, while device independence is a very good thing, there are times when you need to know the specific capabilities of an output device. For example, if you want to center a dialog box, you'll need to position the window yourself, since Windows doesn't provide a built-in centering function.
Since the dimensions of the current screen could be 640 x 480, 800 x 600, 1024 x 768, or some other resolution, you'll need to know something about the screen settings before calculating a position that's truly centered. In addition, if your application changes the default screen-mapping system (the coordinate system that Windows uses to specify screen positions), specifying an absolute screen position might place the dialog box off the screen!
Fortunately, you can use the Windows function GetSystemMetrics()
to retrieve information about the current coordinate system and
the current screen size. In this article, we'll show how
you can create a custom dialog box class for the ObjectWindows
Library (OWL) that uses this information to automatically center
dialog boxes on the screen.
To calculate the center of the current Windows screen, you need to access two global system values, or system metricsthe height (SM_CYSCREEN) and the width (SM_CXSCREEN) of the current screen. Using these two values, the size of the dialog box, and some simple math, you can calculate an origin that will position the dialog box in the center of the screen.
To retrieve the height of the screen, you call
GetSystemMetrics(SM_CYSCREEN)
Likewise, to retrieve the width of the screen, you call
GetSystemMetrics(SM_CXSCREEN)
You'll use these two values to calculate and save the coordinates of the center of the screen.
To calculate the correct X-axis origin for a dialog box, you need to subtract half of the dialog box's width from the horizontal center of the screen. To calculate the correct Y-axis for a dialog box, you subtract half of the dialog box's height from the vertical center of the screen.
Once you've determined the new origin for a dialog box, you can use the member function MoveWindow() to reposition the dialog box in the centered location. If you call this function inside the dialog box's SetupWindow() member function, the movement of the dialog box won't be visible.
Finally, you should wrap this centering behavior inside a new
class that you derive from the TDialog class. This allows
you to derive dialog box classes from the new class instead of
from TDialog and to take advantage of the centering behavior
automatically.
Now let's create a simple OWL application that takes advantage of an automatically centered dialog box class. To begin, launch the Borland C++ 4.0 or 4.5 Integrated Development Environment (IDE).
When the IDE's main window appears, choose New Project... from the Project menu. In the New Project window, enter \CENTER\CENTER.IDE in the Project Path And Name entry field, choose Application from the Target Type list box, choose Windows 3.x (16) from the Platform combo box, and select the OWL check box in the Standard Libraries section. Click OK to create the new project.
When the Project window appears, double-click on the name center [.cpp] to open an editing window for that file. When the editing window appears, enter the code from Listing A.
Listing A: CENTER.CPP
#include <owl/applicat.h> #include <owl/framewin.h> #include <owl/owlpch.h> #include <owl/eventhan.h> #include "ctrdlog.h" class TNewDialog : public TCenteredDialog { public: TNewDialog(TWindow* parent, int resId) : TCenteredDialog(parent, resId) {} }; class TCenterApp : public TApplication { public: TCenterApp() {} ~TCenterApp() {} protected: void InitMainWindow() { TFrameWindow* frame = new TFrameWindow(0, "Center Test"); frame->AssignMenu(1); SetMainWindow(frame); } void ShowDialog() { TNewDialog* dialog = new TNewDialog(GetMainWindow(), 1000); dialog->Execute(); dialog->Destroy(); } DECLARE_RESPONSE_TABLE(TCenterApp); }; DEFINE_RESPONSE_TABLE1(TCenterApp, TApplication) EV_COMMAND(101, ShowDialog), END_RESPONSE_TABLE; int OwlMain(int, char**) { return TCenterApp().Run(); }
When you finish entering the code, choose Save from the File menu. In the Project window, right-click on the center [.cpp] node and choose Add Node from the pop-up menu. In the Add To Project List dialog box, enter CTRDLOG.H in the File Name entry field and click OK. Double-click on the name center [.h] to open an editing window for this file, and then enter the code from Listing B.
Listing B: CTRDLOG.H
#include <owl/dialog.h> class TCenteredDialog : public TDialog { public: TCenteredDialog(TWindow* parent, int resId) : TDialog(parent, resId) {} void SetupWindow() { TDialog::SetupWindow(); TPoint newOrigin(GetSystemMetrics(SM_CXSCREEN) / 2, GetSystemMetrics(SM_CYSCREEN) / 2); TRect tempRect = GetWindowRect(); newOrigin.x -= tempRect.Width() / 2; newOrigin.y -= tempRect.Height() / 2; MoveWindow(TRect(newOrigin, tempRect.Size())); } };
When you finish entering this code, choose Save from the File menu. In the Project window, right-click on the center [.rc] file, and choose Text Edit from the pop-up menu's View submenu. In the editing window for this file, enter the resource description from Listing C.
Listing C: CENTER.RC
1000 DIALOG 2, 12, 104, 43 STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Am I off center?" { DEFPUSHBUTTON "OK", IDOK, 27, 14, 50, 14 } 1 MENU { POPUP "Window" { MENUITEM "Show", 101 } }
When you finish entering this code, choose Save from the File menu. In the Project window, right-click on the center [.def] node and choose Delete Node from the pop-up menu. Click Yes in the confirmation dialog box to delete the node.
Finally, choose Run from the Debug menu to build and test the
application. When the application runs, choose Show from the Window
menu. You'll see the simple dialog box centered on the
screen, as shown in Figure A. Click
OK to close the Am I Off Center dialog box. Double-click on the
Center Test window's System menu icon to close the window
and return to the IDE.
Figure A - You can use the TCenteredDialog class to create dialog boxes that always center themselves on the screen.
As high-performance video systems become more popular, it's
more difficult than ever to predict the resolution of the screen
that's displaying your program. By deriving your dialog
box classes from the TCenteredDialog class we've
created here, your dialog boxes will center themselves no matter
what the resolution of the target system might be.
Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.