OSDN Git Service

Add a missing return statement.
[mingw/wtklite.git] / wtkalign.c
1 /*
2  * wtkalign.c
3  *
4  * ---------------------------------------------------------------------------
5  *
6  * Implementation of a minimal C++ class framework for use with the
7  * Microsoft Windows Application Programming Interface.
8  *
9  * $Id$
10  *
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.
14  *
15  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
16  * Copyright (C) 2013, MinGW.org Project.
17  *
18  * ---------------------------------------------------------------------------
19  *
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:
26  *
27  * The above copyright notice, this permission notice, and the following
28  * disclaimer shall be included in all copies or substantial portions of
29  * the Software.
30  *
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.
38  *
39  * ---------------------------------------------------------------------------
40  *
41  */
42 #define  WIN32_LEAN_AND_MEAN
43
44 #include <windows.h>
45 #include "wtkalign.h"
46
47 void AlignWindow( HWND child, unsigned int alignment )
48 {
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
53    * parent window.
54    */
55   HWND parent = ((alignment & WTK_ALIGN_ONSCREEN) == 0)
56     /*
57      * Unless alignment relative to the screen is specified, we must
58      * identify the parent window from which the alignment bounds are
59      * to be deduced.
60      */
61     ? GetParent( child )
62     : NULL;
63
64   if( parent == NULL )
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.
69      */
70     parent = GetDesktopWindow();
71
72   if( parent != NULL )
73   {
74     /* We now have a valid effective parent, so we may continue...
75      */
76     RECT screen, window;
77     unsigned int mode;
78
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.
82      */
83     GetWindowRect( child, &window );
84     GetWindowRect( parent, &screen );
85
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...
89      */
90     switch( mode = alignment & WTK_ALIGN_HCENTRE )
91     {
92       case WTK_ALIGN_RIGHT:
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...
98          */
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.
104            */
105           screen.left += (window.left > 0) ? window.left >> 1 : 0;
106
107       case WTK_ALIGN_LEFT:
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
111          * aligned window.
112          */
113         break;
114
115       default:
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.
119          */
120         screen.left = window.left;
121     }
122
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...
126      */
127     switch( mode = alignment & WTK_ALIGN_VCENTRE )
128     {
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...
135          */
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.
141            */
142           screen.top += (window.top > 0) ? window.top >> 1 : 0;
143
144       case WTK_ALIGN_TOP:
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
148          * aligned window.
149          */
150         break;
151
152       default:
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.
156          */
157         screen.top = window.top;
158     }
159
160     /* Finally, we reposition the dialogue box to the top left screen
161      * co-ordinate we've just computed, preserving its original size.
162      */
163     SetWindowPos( child, HWND_TOP, screen.left, screen.top, 0, 0, SWP_NOSIZE );
164   }
165 }
166
167 /* $RCSfile$: end of file */