4 * ---------------------------------------------------------------------------
6 * Implementation of a minimal C++ class framework for use with the
7 * Microsoft Windows Application Programming Interface.
11 * This file provides the implementation of AlignWindow(), a helper
12 * function for controlling the placement of child windows relative
13 * to their parent, or to the screen bounds.
15 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
16 * Copyright (C) 2013, MinGW.org Project.
18 * ---------------------------------------------------------------------------
20 * Permission is hereby granted, free of charge, to any person obtaining a
21 * copy of this software and associated documentation files (the "Software"),
22 * to deal in the Software without restriction, including without limitation
23 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 * and/or sell copies of the Software, and to permit persons to whom the
25 * Software is furnished to do so, subject to the following conditions:
27 * The above copyright notice, this permission notice, and the following
28 * disclaimer shall be included in all copies or substantial portions of
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
32 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
34 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
36 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
37 * DEALINGS IN THE SOFTWARE.
39 * ---------------------------------------------------------------------------
42 #define WIN32_LEAN_AND_MEAN
47 void AlignWindow( HWND child, unsigned int alignment )
49 /* Helper to be invoked while handling a WM_CREATE or WM_INITDIALOG
50 * message; it adjusts the position at which the window or dialogue
51 * box is created, such that it is displayed either neatly centred,
52 * or flush with specified boundaries, on the screen, or within its
55 HWND parent = ((alignment & WTK_ALIGN_ONSCREEN) == 0)
57 * Unless alignment relative to the screen is specified, we must
58 * identify the parent window from which the alignment bounds are
65 /* When no parent has yet been identified, we are either explicitly
66 * attempting to align within the desktop bounds, or the window we
67 * are attempting to align has no valid parent; in either case, we
68 * use the desktop window as the effective parent.
70 parent = GetDesktopWindow();
74 /* We now have a valid effective parent, so we may continue...
79 /* First, we obtain the physical co-ordinates of the four corners
80 * for both the dialogue box in its default position, and for the
81 * parent window, all mapped as screen co-ordinates.
83 GetWindowRect( child, &window );
84 GetWindowRect( parent, &screen );
86 /* Adjust the left-right position, setting the left ordinate for the
87 * "screen" co-ordinate group to the physical left ordinate for final
88 * placement of the dialogue on-screen...
90 switch( mode = alignment & WTK_ALIGN_HCENTRE )
93 case WTK_ALIGN_HCENTRE:
94 /* In the case of right or centred alignment, we initially push
95 * the left ordinate of the "window" co-ordinate group as far to
96 * the right as possible, while still keeping the window within
97 * the designated screen bounds...
99 window.left += screen.right - screen.left - window.right;
100 if( mode == WTK_ALIGN_HCENTRE )
101 /* ...then, in the centred case, we move it back to the left,
102 * by half of the distance between the leftmost "screen" bound
103 * and the right-adjusted "window" ordinate.
105 screen.left += (window.left > 0) ? window.left >> 1 : 0;
108 /* In the case of left alignment we have nothing to do -- the
109 * left bound of the "screen" co-ordinate group is already set
110 * to the position where we want to place the left side of the
116 /* In the case where no left-right alignment is specified, we
117 * can simply make the left "screen" ordinate coincide with the
118 * default position of the window.
120 screen.left = window.left;
123 /* Adjust the top-bottom position, setting the top ordinate for the
124 * "screen" co-ordinate group to the physical top ordinate for final
125 * placement of the dialogue on-screen...
127 switch( mode = alignment & WTK_ALIGN_VCENTRE )
129 case WTK_ALIGN_BOTTOM:
130 case WTK_ALIGN_VCENTRE:
131 /* In the case of bottom or centred alignment, we initially push
132 * the top ordinate of the "window" co-ordinate group downwards as
133 * far as is possible, while still keeping the window within the
134 * designated screen bounds...
136 window.top += screen.bottom - screen.top - window.bottom;
137 if( mode == WTK_ALIGN_VCENTRE )
138 /* ...then, in the centred case, we adjust it upwards again,
139 * by half of the distance between the topmost "screen" bound
140 * and the downwards adjusted top "window" ordinate.
142 screen.top += (window.top > 0) ? window.top >> 1 : 0;
145 /* In the case of top alignment we have nothing to do -- the
146 * top bound of the "screen" co-ordinate group is already set
147 * to the position where we want to place the top edge of the
153 /* In the case where no top-bottom alignment is specified, we
154 * can simply make the top "screen" ordinate coincide with the
155 * default position of the window.
157 screen.top = window.top;
160 /* Finally, we reposition the dialogue box to the top left screen
161 * co-ordinate we've just computed, preserving its original size.
163 SetWindowPos( child, HWND_TOP, screen.left, screen.top, 0, 0, SWP_NOSIZE );
167 /* $RCSfile$: end of file */