Codebase list mozc / e13f117
Remove third party libraries Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@debian.org> Nobuhiro Iwamatsu 6 years ago
41 changed file(s) with 0 addition(s) and 62557 deletion(s). Raw diff Collapse all Expand all
0 [submodule "src/third_party/breakpad"]
1 path = src/third_party/breakpad
2 url = https://chromium.googlesource.com/breakpad/breakpad
3 [submodule "src/third_party/gtest"]
4 path = src/third_party/gtest
5 url = https://github.com/google/googletest.git
6 [submodule "src/third_party/gyp"]
7 path = src/third_party/gyp
8 url = https://chromium.googlesource.com/external/gyp
9 [submodule "src/third_party/japanese_usage_dictionary"]
10 path = src/third_party/japanese_usage_dictionary
11 url = https://github.com/hiroyuki-komatsu/japanese-usage-dictionary.git
12 [submodule "src/third_party/jsoncpp"]
13 path = src/third_party/jsoncpp
14 url = https://github.com/open-source-parsers/jsoncpp.git
15 [submodule "src/third_party/protobuf"]
16 path = src/third_party/protobuf
17 url = https://github.com/google/protobuf.git
18 [submodule "src/third_party/zinnia"]
19 path = src/third_party/zinnia
20 url = https://github.com/taku910/zinnia.git
+0
-0
src/third_party/breakpad less more
(Empty file)
+0
-0
src/third_party/gtest less more
(Empty file)
src/third_party/guava/guava-18.0.jar less more
Binary diff not shown
src/third_party/guava/guava-testlib-18.0.jar less more
Binary diff not shown
+0
-0
src/third_party/gyp less more
(Empty file)
+0
-117
src/third_party/ipa_font/LICENSE less more
0 --------------------------------------------------
1 IPA Font License Agreement v1.0 <Japanese/English>
2 --------------------------------------------------
3
4 IPAフォントライセンスv1.0
5
6 許諾者は、この使用許諾(以下「本契約」といいます。)に定める条件の下で、許諾プログラム(1条に定義するところによります。)を提供します。受領者(1条に定義するところによります。)が、許諾プログラムを使用し、複製し、または頒布する行為、その他、本契約に定める権利の利用を行った場合、受領者は本契約に同意したものと見なします。
7
8
9 第1条 用語の定義
10
11 本契約において、次の各号に掲げる用語は、当該各号に定めるところによります。
12
13 1.「デジタル・フォント・プログラム」とは、フォントを含み、レンダリングしまたは表示するために用いられるコンピュータ・プログラムをいいます。
14 2.「許諾プログラム」とは、許諾者が本契約の下で許諾するデジタル・フォント・プログラムをいいます。
15 3.「派生プログラム」とは、許諾プログラムの一部または全部を、改変し、加除修正等し、入れ替え、その他翻案したデジタル・フォント・プログラムをいい、許諾プログラムの一部もしくは全部から文字情報を取り出し、またはデジタル・ドキュメント・ファイルからエンベッドされたフォントを取り出し、取り出された文字情報をそのまま、または改変をなして新たなデジタル・フォント・プログラムとして製作されたものを含みます。
16 4.「デジタル・コンテンツ」とは、デジタル・データ形式によってエンド・ユーザに提供される制作物のことをいい、動画・静止画等の映像コンテンツおよびテレビ番組等の放送コンテンツ、ならびに文字テキスト、画像、図形等を含んで構成された制作物を含みます。
17 5.「デジタル・ドキュメント・ファイル」とは、PDFファイルその他、各種ソフトウェア・プログラムによって製作されたデジタル・コンテンツであって、その中にフォントを表示するために許諾プログラムの全部または一部が埋め込まれた(エンベッドされた)ものをいいます。フォントが「エンベッドされた」とは、当該フォントが埋め込まれた特定の「デジタル・ドキュメント・ファイル」においてのみ表示されるために使用されている状態を指し、その特定の「デジタル・ドキュメント・ファイル」以外でフォントを表示するために使用できるデジタル・フォント・プログラムに含まれている場合と区別されます。
18 6.「コンピュータ」とは、本契約においては、サーバを含みます。
19 7.「複製その他の利用」とは、複製、譲渡、頒布、貸与、公衆送信、上映、展示、翻案その他の利用をいいます。
20 8.「受領者」とは、許諾プログラムを本契約の下で受領した人をいい、受領者から許諾プログラムを受領した人を含みます。
21
22 第2条 使用許諾の付与
23
24 許諾者は受領者に対し、本契約の条項に従い、すべての国で、許諾プログラムを使用することを許諾します。ただし、許諾プログラムに存在する一切の権利はすべて許諾者が保有しています。本契約は、本契約で明示的に定められている場合を除き、いかなる意味においても、許諾者が保有する許諾プログラムに関する一切の権利および、いかなる商標、商号、もしくはサービス・マークに関する権利をも受領者に移転するものではありません。
25
26 1.受領者は本契約に定める条件に従い、許諾プログラムを任意の数のコンピュータにインストールし、当該コンピュータで使用することができます。
27 2.受領者はコンピュータにインストールされた許諾プログラムをそのまま、または改変を行ったうえで、印刷物およびデジタル・コンテンツにおいて、文字テキスト表現等として使用することができます。
28 3.受領者は前項の定めに従い作成した印刷物およびデジタル・コンテンツにつき、その商用・非商用の別、および放送、通信、各種記録メディアなどの媒体の形式を問わず、複製その他の利用をすることができます。
29 4.受領者がデジタル・ドキュメント・ファイルからエンベッドされたフォントを取り出して派生プログラムを作成した場合には、かかる派生プログラムは本契約に定める条件に従う必要があります。
30 5.許諾プログラムのエンベッドされたフォントがデジタル・ドキュメント・ファイル内のデジタル・コンテンツをレンダリングするためにのみ使用される場合において、受領者が当該デジタル・ドキュメント・ファイルを複製その他の利用をする場合には、受領者はかかる行為に関しては本契約の下ではいかなる義務をも負いません。
31 6.受領者は、3条2項の定めに従い、商用・非商用を問わず、許諾プログラムをそのままの状態で改変することなく複製して第三者への譲渡し、公衆送信し、その他の方法で再配布することができます(以下、「再配布」といいます。)。
32 7.受領者は、上記の許諾プログラムについて定められた条件と同様の条件に従って、派生プログラムを作成し、使用し、複製し、再配布することができます。ただし、受領者が派生プログラムを再配布する場合には、3条1項の定めに従うものとします。
33
34 第3条 制限
35
36 前条により付与された使用許諾は、以下の制限に服します。
37
38 1.派生プログラムが前条4項及び7項に基づき再配布される場合には、以下の全ての条件を満たさなければなりません。
39  (1)派生プログラムを再配布する際には、下記もまた、当該派生プログラムと一緒に再配布され、オンラインで提供され、または、郵送費・媒体及び取扱手数料の合計を超えない実費と引き換えに媒体を郵送する方法により提供されなければなりません。
40   (a)派生プログラムの写し; および
41   (b)派生プログラムを作成する過程でフォント開発プログラムによって作成された追加のファイルであって派生プログラムをさらに加工するにあたって利用できるファイルが存在すれば、当該ファイル
42  (2)派生プログラムの受領者が、派生プログラムを、このライセンスの下で最初にリリースされた許諾プログラム(以下、「オリジナル・プログラム」といいます。)に置き換えることができる方法を再配布するものとします。かかる方法は、オリジナル・ファイルからの差分ファイルの提供、または、派生プログラムをオリジナル・プログラムに置き換える方法を示す指示の提供などが考えられます。
43  (3)派生プログラムを、本契約書に定められた条件の下でライセンスしなければなりません。
44  (4)派生プログラムのプログラム名、フォント名またはファイル名として、許諾プログラムが用いているのと同一の名称、またはこれを含む名称を使用してはなりません。
45  (5)本項の要件を満たすためにオンラインで提供し、または媒体を郵送する方法で提供されるものは、その提供を希望するいかなる者によっても提供が可能です。
46 2.受領者が前条6項に基づき許諾プログラムを再配布する場合には、以下の全ての条件を満たさなければなりません。
47  (1)許諾プログラムの名称を変更してはなりません。
48  (2)許諾プログラムに加工その他の改変を加えてはなりません。
49  (3)本契約の写しを許諾プログラムに添付しなければなりません。
50 3.許諾プログラムは、現状有姿で提供されており、許諾プログラムまたは派生プログラムについて、許諾者は一切の明示または黙示の保証(権利の所在、非侵害、商品性、特定目的への適合性を含むがこれに限られません)を行いません。いかなる場合にも、その原因を問わず、契約上の責任か厳格責任か過失その他の不法行為責任かにかかわらず、また事前に通知されたか否かにかかわらず、許諾者は、許諾プログラムまたは派生プログラムのインストール、使用、複製その他の利用または本契約上の権利の行使によって生じた一切の損害(直接・間接・付随的・特別・拡大・懲罰的または結果的損害)(商品またはサービスの代替品の調達、システム障害から生じた損害、現存するデータまたはプログラムの紛失または破損、逸失利益を含むがこれに限られません)について責任を負いません。
51 4.許諾プログラムまたは派生プログラムのインストール、使用、複製その他の利用に関して、許諾者は技術的な質問や問い合わせ等に対する対応その他、いかなるユーザ・サポートをも行う義務を負いません。
52
53 第4条 契約の終了
54
55 1.本契約の有効期間は、受領者が許諾プログラムを受領した時に開始し、受領者が許諾プログラムを何らかの方法で保持する限り続くものとします。
56 2.前項の定めにかかわらず、受領者が本契約に定める各条項に違反したときは、本契約は、何らの催告を要することなく、自動的に終了し、当該受領者はそれ以後、許諾プログラムおよび派生プログラムを一切使用しまたは複製その他の利用をすることができないものとします。ただし、かかる契約の終了は、当該違反した受領者から許諾プログラムまたは派生プログラムの配布を受けた受領者の権利に影響を及ぼすものではありません。
57
58 第5条 準拠法
59
60 1.IPAは、本契約の変更バージョンまたは新しいバージョンを公表することができます。その場合には、受領者は、許諾プログラムまたは派生プログラムの使用、複製その他の利用または再配布にあたり、本契約または変更後の契約のいずれかを選択することができます。その他、上記に記載されていない条項に関しては日本の著作権法および関連法規に従うものとします。
61 2.本契約は、日本法に基づき解釈されます。
62
63
64 ----------
65
66 IPA Font License Agreement v1.0
67
68 The Licensor provides the Licensed Program (as defined in Article 1 below) under the terms of this license agreement (“Agreement”). Any use, reproduction or distribution of the Licensed Program, or any exercise of rights under this Agreement by a Recipient (as defined in Article 1 below) constitutes the Recipient's acceptance of this Agreement.
69
70 Article 1 (Definitions)
71 1.“Digital Font Program” shall mean a computer program containing, or used to render or display fonts.
72 2.“Licensed Program” shall mean a Digital Font Program licensed by the Licensor under this Agreement.
73 3.“Derived Program” shall mean a Digital Font Program created as a result of a modification, addition, deletion, replacement or any other adaptation to or of a part or all of the Licensed Program, and includes a case where a Digital Font Program newly created by retrieving font information from a part or all of the Licensed Program or Embedded Fonts from a Digital Document File with or without modification of the retrieved font information.
74 4.“Digital Content” shall mean products provided to end users in the form of digital data, including video content, motion and/or still pictures, TV programs or other broadcasting content and products consisting of character text, pictures, photographic images, graphic symbols and/or the like.
75 5.“Digital Document File” shall mean a PDF file or other Digital Content created by various software programs in which a part or all of the Licensed Program becomes embedded or contained in the file for the display of the font (“Embedded Fonts”). Embedded Fonts are used only in the display of characters in the particular Digital Document File within which they are embedded, and shall be distinguished from those in any Digital Font Program, which may be used for display of characters outside that particular Digital Document File.
76 6.“Computer” shall include a server in this Agreement.
77 7.“Reproduction and Other Exploitation” shall mean reproduction, transfer, distribution, lease, public transmission, presentation, exhibition, adaptation and any other exploitation.
78 8.“Recipient” shall mean anyone who receives the Licensed Program under this Agreement, including one that receives the Licensed Program from a Recipient.
79
80 Article 2 (Grant of License)
81 The Licensor grants to the Recipient a license to use the Licensed Program in any and all countries in accordance with each of the provisions set forth in this Agreement. However, any and all rights underlying in the Licensed Program shall be held by the Licensor. In no sense is this Agreement intended to transfer any right relating to the Licensed Program held by the Licensor except as specifically set forth herein or any right relating to any trademark, trade name, or service mark to the Recipient.
82
83 1.The Recipient may install the Licensed Program on any number of Computers and use the same in accordance with the provisions set forth in this Agreement.
84 2.The Recipient may use the Licensed Program, with or without modification in printed materials or in Digital Content as an expression of character texts or the like.
85 3.The Recipient may conduct Reproduction and Other Exploitation of the printed materials and Digital Content created in accordance with the preceding Paragraph, for commercial or non-commercial purposes and in any form of media including but not limited to broadcasting, communication and various recording media.
86 4.If any Recipient extracts Embedded Fonts from a Digital Document File to create a Derived Program, such Derived Program shall be subject to the terms of this agreement.
87 5.If any Recipient performs Reproduction or Other Exploitation of a Digital Document File in which Embedded Fonts of the Licensed Program are used only for rendering the Digital Content within such Digital Document File then such Recipient shall have no further obligations under this Agreement in relation to such actions.
88 6.The Recipient may reproduce the Licensed Program as is without modification and transfer such copies, publicly transmit or otherwise redistribute the Licensed Program to a third party for commercial or non-commercial purposes (“Redistribute”), in accordance with the provisions set forth in Article 3 Paragraph 2.
89 7.The Recipient may create, use, reproduce and/or Redistribute a Derived Program under the terms stated above for the Licensed Program: provided, that the Recipient shall follow the provisions set forth in Article 3 Paragraph 1 when Redistributing the Derived Program.
90
91 Article 3 (Restriction)
92 The license granted in the preceding Article shall be subject to the following restrictions:
93
94 1.If a Derived Program is Redistributed pursuant to Paragraph 4 and 7 of the preceding Article, the following conditions must be met :
95  (1)The following must be also Redistributed together with the Derived Program, or be made available online or by means of mailing mechanisms in exchange for a cost which does not exceed the total costs of postage, storage medium and handling fees:
96   (a)a copy of the Derived Program; and
97   (b)any additional file created by the font developing program in the course of creating the Derived Program that can be used for further modification of the Derived Program, if any.
98  (2)It is required to also Redistribute means to enable recipients of the Derived Program to replace the Derived Program with the Licensed Program first released under this License (the “Original Program”). Such means may be to provide a difference file from the Original Program, or instructions setting out a method to replace the Derived Program with the Original Program.
99  (3)The Recipient must license the Derived Program under the terms and conditions of this Agreement.
100  (4)No one may use or include the name of the Licensed Program as a program name, font name or file name of the Derived Program.
101  (5)Any material to be made available online or by means of mailing a medium to satisfy the requirements of this paragraph may be provided, verbatim, by any party wishing to do so.
102 2.If the Recipient Redistributes the Licensed Program pursuant to Paragraph 6 of the preceding Article, the Recipient shall meet all of the following conditions:
103  (1)The Recipient may not change the name of the Licensed Program.
104  (2)The Recipient may not alter or otherwise modify the Licensed Program.
105  (3)The Recipient must attach a copy of this Agreement to the Licensed Program.
106 3.THIS LICENSED PROGRAM IS PROVIDED BY THE LICENSOR “AS IS” AND ANY EXPRESSED OR IMPLIED WARRANTY AS TO THE LICENSED PROGRAM OR ANY DERIVED PROGRAM, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXTENDED, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO; PROCUREMENT OF SUBSTITUTED GOODS OR SERVICE; DAMAGES ARISING FROM SYSTEM FAILURE; LOSS OR CORRUPTION OF EXISTING DATA OR PROGRAM; LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE INSTALLATION, USE, THE REPRODUCTION OR OTHER EXPLOITATION OF THE LICENSED PROGRAM OR ANY DERIVED PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
107 4.The Licensor is under no obligation to respond to any technical questions or inquiries, or provide any other user support in connection with the installation, use or the Reproduction and Other Exploitation of the Licensed Program or Derived Programs thereof.
108
109 Article 4 (Termination of Agreement)
110 1.The term of this Agreement shall begin from the time of receipt of the Licensed Program by the Recipient and shall continue as long as the Recipient retains any such Licensed Program in any way.
111 2.Notwithstanding the provision set forth in the preceding Paragraph, in the event of the breach of any of the provisions set forth in this Agreement by the Recipient, this Agreement shall automatically terminate without any notice. In the case of such termination, the Recipient may not use or conduct Reproduction and Other Exploitation of the Licensed Program or a Derived Program: provided that such termination shall not affect any rights of any other Recipient receiving the Licensed Program or the Derived Program from such Recipient who breached this Agreement.
112
113 Article 5 (Governing Law)
114 1.IPA may publish revised and/or new versions of this License. In such an event, the Recipient may select either this Agreement or any subsequent version of the Agreement in using, conducting the Reproduction and Other Exploitation of, or Redistributing the Licensed Program or a Derived Program. Other matters not specified above shall be subject to the Copyright Law of Japan and other related laws and regulations of Japan.
115 2.This Agreement shall be construed under the laws of Japan.
116
+0
-20
src/third_party/ipa_font/README.mozc less more
0 URL: http://ipafont.ipa.go.jp/ipaexfont/IPAexfont00201.php
1 Version: 002.01
2 License: IPA Open Font License v1.0
3 License File: LICENSE
4
5 Description:
6 This directory contains opensource Japanese fonts provided by
7 Information-technology Promotion Agency (IPA), Japan. These fonts are useful
8 for testing compatibility issues on advanced font rendering features such as
9 Ideographic Variation Sequence (IVS).
10
11 * ipaexg.ttf: IPAexGothic
12 * ipaexm.ttf: Mincho style
13
14 Although IPA Open Font License v1.0 is one of Open Source Initiative (OSI)
15 approved licenses, there are some special licensing conditions like
16 SIL Open Font License (OFL-1.1). See LICENSE for details.
17
18 Local Modifications:
19 No modifications.
+0
-36
src/third_party/ipa_font/Readme_IPAexfont00201.txt less more
0 IPAexフォント
1 ― はじめにお読みください ―
2
3 IPAexフォントは、JIS X 0213:2004に準拠したTrueTypeアウトラインベースのOpenTypeフォントです。
4
5 IPAexフォントの使用または利用に当たっては、添付の「IPAフォントライセンスv1.0」に定める条件に従ってください。
6 IPAexフォントを使用し、複製し、または頒布する行為、その他、「IPAフォントライセンスv1.0」に定める権利の利用を行った場合、受領者は「IPAフォントライセンスv1.0」に同意したものと見なします。
7
8
9 IPAexフォント2書体パック(IPAexゴシック、IPAex明朝) IPAexfont00201.zip
10 |--はじめにお読みください Readme_IPAexfont00201.txt
11 |--IPAフォントライセンスv1.0 IPA_Font_License_Agreement_v1.0.txt
12 |--IPAexゴシック(Ver.002.01) ipaexg.ttf
13 |--IPAex明朝(Ver.002.01) ipaexm.ttf
14
15
16 「IPAフォント」は、IPAの登録商標です。
17
18 =========================
19 IPAex Font
20 -- Readme --
21
22 IPAex Fonts are JIS X 0213:2004 compliant OpenType fonts based on TrueType outlines.
23
24 In using IPAex fonts, please comply with the terms and conditions set out in "IPA Font License Agreement v1.0" included in this package.
25 Any use, reproduction or distribution of the IPA Font or any exercise of rights under "IPA Font License Agreement v1.0" by a Recipient constitutes the Recipient's acceptance of the License Agreement.
26
27
28 IPAex Fonts 2 fonts package (IPAex Gothic、IPAex Mincho) IPAexfont00201.zip
29 |--Readme Readme_IPAexfont00201.txt
30 |--IPA Font License Agreement v1.0 IPA_Font_License_Agreement_v1.0.txt
31 |--IPAexGothic(Ver.002.01) ipaexg.ttf
32 |--IPAexMincho(Ver.002.01) ipaexm.ttf
33
34
35 "IPA Font" is a registered trademark of IPA in Japan.
src/third_party/ipa_font/ipaexg.ttf less more
Binary diff not shown
src/third_party/ipa_font/ipaexm.ttf less more
Binary diff not shown
+0
-0
src/third_party/japanese_usage_dictionary less more
(Empty file)
+0
-0
src/third_party/jsoncpp less more
(Empty file)
+0
-0
src/third_party/protobuf less more
(Empty file)
+0
-2268
src/third_party/wtl/Include/atlapp.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLAPP_H__
9 #define __ATLAPP_H__
10
11 #pragma once
12
13 #ifndef __cplusplus
14 #error WTL requires C++ compilation (use a .cpp suffix)
15 #endif
16
17 #ifndef __ATLBASE_H__
18 #error atlapp.h requires atlbase.h to be included first
19 #endif
20
21 #ifndef _WIN32_WCE
22 #if (WINVER < 0x0400)
23 #error WTL requires Windows version 4.0 or higher
24 #endif
25
26 #if (_WIN32_IE < 0x0300)
27 #error WTL requires IE version 3.0 or higher
28 #endif
29 #endif
30
31 #ifdef _ATL_NO_COMMODULE
32 #error WTL requires that _ATL_NO_COMMODULE is not defined
33 #endif
34
35 #if (_ATL_VER >= 0x0900) && defined(_ATL_MIN_CRT)
36 #error _ATL_MIN_CRT is not supported with ATL 9.0 and higher
37 #endif
38
39 #if defined(_WIN32_WCE) && defined(_ATL_MIN_CRT)
40 #pragma message("Warning: WTL for Windows CE doesn't use _ATL_MIN_CRT")
41 #endif
42
43 #include <limits.h>
44 #if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
45 #include <process.h> // for _beginthreadex
46 #endif
47
48 #if (_ATL_VER < 0x0800) && !defined(_DEBUG)
49 #include <stdio.h>
50 #endif
51
52 #include <commctrl.h>
53 #ifndef _WIN32_WCE
54 #pragma comment(lib, "comctl32.lib")
55 #endif
56
57 #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE) && (_WIN32_WINNT >= 0x0501)
58 #include <VersionHelpers.h>
59 #endif
60
61 #ifndef _WIN32_WCE
62 #include "atlres.h"
63 #else // CE specific
64 #include "atlresce.h"
65 #endif // _WIN32_WCE
66
67 // We need to disable this warning because of template class arguments
68 #pragma warning(disable: 4127)
69
70 #if (_ATL_VER >= 0x0900) && !defined(_SECURE_ATL)
71 #define _SECURE_ATL 1
72 #endif
73
74
75 ///////////////////////////////////////////////////////////////////////////////
76 // WTL version number
77
78 #define _WTL_VER 0x0910
79
80
81 ///////////////////////////////////////////////////////////////////////////////
82 // Classes in this file:
83 //
84 // CMessageFilter
85 // CIdleHandler
86 // CMessageLoop
87 //
88 // CAppModule
89 // CServerAppModule
90 //
91 // CRegKeyEx
92 //
93 // Global functions:
94 // AtlGetDefaultGuiFont()
95 // AtlCreateControlFont()
96 // AtlCreateBoldFont()
97 // AtlInitCommonControls()
98
99
100 ///////////////////////////////////////////////////////////////////////////////
101 // Global support for Windows CE
102
103 #ifdef _WIN32_WCE
104
105 #ifndef SW_SHOWDEFAULT
106 #define SW_SHOWDEFAULT SW_SHOWNORMAL
107 #endif // !SW_SHOWDEFAULT
108
109 // These get's OR-ed in a constant and will have no effect.
110 // Defining them reduces the number of #ifdefs required for CE.
111 #define LR_DEFAULTSIZE 0
112 #define LR_LOADFROMFILE 0
113
114 #ifndef SM_CXCURSOR
115 #define SM_CXCURSOR 13
116 #endif
117 #ifndef SM_CYCURSOR
118 #define SM_CYCURSOR 14
119 #endif
120
121 inline BOOL IsMenu(HMENU hMenu)
122 {
123 MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
124 ::SetLastError(0);
125 BOOL bRet = ::GetMenuItemInfo(hMenu, 0, TRUE, &mii);
126 if(!bRet)
127 bRet = (::GetLastError() != ERROR_INVALID_MENU_HANDLE) ? TRUE : FALSE;
128 return bRet;
129 }
130
131 #if (_WIN32_WCE >= 410)
132 extern "C" void WINAPI ListView_SetItemSpacing(HWND hwndLV, int iHeight);
133 #endif // (_WIN32_WCE >= 410)
134
135 inline int MulDiv(IN int nNumber, IN int nNumerator, IN int nDenominator)
136 {
137 __int64 multiple = nNumber * nNumerator;
138 return static_cast<int>(multiple / nDenominator);
139 }
140
141 #if (_ATL_VER >= 0x0800)
142
143 #ifndef _WTL_KEEP_WS_OVERLAPPEDWINDOW
144 #ifdef WS_OVERLAPPEDWINDOW
145 #undef WS_OVERLAPPEDWINDOW
146 #define WS_OVERLAPPEDWINDOW 0
147 #endif // WS_OVERLAPPEDWINDOW
148 #endif // !_WTL_KEEP_WS_OVERLAPPEDWINDOW
149
150 #ifndef RDW_FRAME
151 #define RDW_FRAME 0
152 #endif // !RDW_FRAME
153
154 #ifndef WM_WINDOWPOSCHANGING
155 #define WM_WINDOWPOSCHANGING 0
156 #endif // !WM_WINDOWPOSCHANGING
157
158 #define FreeResource(x)
159 #define UnlockResource(x)
160
161 namespace ATL
162 {
163 inline HRESULT CComModule::RegisterClassObjects(DWORD /*dwClsContext*/, DWORD /*dwFlags*/) throw()
164 { return E_NOTIMPL; }
165 inline HRESULT CComModule::RevokeClassObjects() throw()
166 { return E_NOTIMPL; }
167 }; // namespace ATL
168
169 #ifndef lstrlenW
170 #define lstrlenW (int)ATL::lstrlenW
171 #endif // lstrlenW
172
173 inline int WINAPI lstrlenA(LPCSTR lpszString)
174 { return ATL::lstrlenA(lpszString); }
175
176 #ifdef lstrcpyn
177 #undef lstrcpyn
178 #define lstrcpyn ATL::lstrcpynW
179 #endif // lstrcpyn
180
181 #ifndef SetWindowLongPtrW
182 inline LONG_PTR tmp_SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
183 {
184 return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
185 }
186 #define SetWindowLongPtrW tmp_SetWindowLongPtrW
187 #endif
188
189 #ifndef GetWindowLongPtrW
190 inline LONG_PTR tmp_GetWindowLongPtrW( HWND hWnd, int nIndex )
191 {
192 return( ::GetWindowLongW( hWnd, nIndex ) );
193 }
194 #define GetWindowLongPtrW tmp_GetWindowLongPtrW
195 #endif
196
197 #ifndef LongToPtr
198 #define LongToPtr(x) ((void*)x)
199 #endif
200
201 #ifndef PtrToInt
202 #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
203 #endif
204
205 #else // !(_ATL_VER >= 0x0800)
206
207 #ifdef lstrlenW
208 #undef lstrlenW
209 #define lstrlenW (int)::wcslen
210 #endif // lstrlenW
211
212 #define lstrlenA (int)strlen
213
214 #ifndef lstrcpyn
215 inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
216 {
217 if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
218 return NULL;
219 int nLen = __min(lstrlen(lpstrSrc), nLength - 1);
220 LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR));
221 lpstrDest[nLen] = 0;
222 return lpstrRet;
223 }
224 #endif // !lstrcpyn
225
226 #ifndef lstrcpynW
227 inline LPWSTR lstrcpynW(LPWSTR lpstrDest, LPCWSTR lpstrSrc, int nLength)
228 {
229 return lstrcpyn(lpstrDest, lpstrSrc, nLength); // WinCE is Unicode only
230 }
231 #endif // !lstrcpynW
232
233 #ifndef lstrcpynA
234 inline LPSTR lstrcpynA(LPSTR lpstrDest, LPCSTR lpstrSrc, int nLength)
235 {
236 if(lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0)
237 return NULL;
238 int nLen = __min(lstrlenA(lpstrSrc), nLength - 1);
239 LPSTR lpstrRet = (LPSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(char));
240 lpstrDest[nLen] = 0;
241 return lpstrRet;
242 }
243 #endif // !lstrcpyn
244
245 #ifdef TrackPopupMenu
246 #undef TrackPopupMenu
247 #endif // TrackPopupMenu
248
249 #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
250 static CWndClassInfo& GetWndClassInfo() \
251 { \
252 static CWndClassInfo wc = \
253 { \
254 { style, StartWindowProc, \
255 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
256 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
257 }; \
258 return wc; \
259 }
260
261 #ifndef _MAX_FNAME
262 #define _MAX_FNAME _MAX_PATH
263 #endif // _MAX_FNAME
264
265 #if (_WIN32_WCE < 400)
266 #define MAKEINTATOM(i) (LPTSTR)((ULONG_PTR)((WORD)(i)))
267 #endif // (_WIN32_WCE < 400)
268
269 #if (_WIN32_WCE < 410)
270 #define WHEEL_PAGESCROLL (UINT_MAX)
271 #define WHEEL_DELTA 120
272 #endif // (_WIN32_WCE < 410)
273
274 #ifdef DrawIcon
275 #undef DrawIcon
276 #endif
277
278 #ifndef VARCMP_LT
279 #define VARCMP_LT 0
280 #endif
281 #ifndef VARCMP_EQ
282 #define VARCMP_EQ 1
283 #endif
284 #ifndef VARCMP_GT
285 #define VARCMP_GT 2
286 #endif
287 #ifndef VARCMP_NULL
288 #define VARCMP_NULL 3
289 #endif
290
291 #ifndef RDW_ALLCHILDREN
292 #define RDW_ALLCHILDREN 0
293 #endif
294
295 #endif // !(_ATL_VER >= 0x0800)
296
297 #endif // _WIN32_WCE
298
299
300 ///////////////////////////////////////////////////////////////////////////////
301 // Global support for using original VC++ 6.0 headers with WTL
302
303 #if (_MSC_VER < 1300) && !defined(_WIN32_WCE)
304 #ifndef REG_QWORD
305 #define REG_QWORD 11
306 #endif
307
308 #ifndef BS_PUSHBOX
309 #define BS_PUSHBOX 0x0000000AL
310 #endif
311
312 struct __declspec(uuid("000214e6-0000-0000-c000-000000000046")) IShellFolder;
313 struct __declspec(uuid("000214f9-0000-0000-c000-000000000046")) IShellLinkW;
314 struct __declspec(uuid("000214ee-0000-0000-c000-000000000046")) IShellLinkA;
315 #endif // (_MSC_VER < 1300) && !defined(_WIN32_WCE)
316
317 #ifndef _ATL_NO_OLD_HEADERS_WIN64
318 #if !defined(_WIN64) && (_ATL_VER < 0x0700)
319
320 #ifndef PSM_INSERTPAGE
321 #define PSM_INSERTPAGE (WM_USER + 119)
322 #endif // !PSM_INSERTPAGE
323
324 #ifndef GetClassLongPtr
325 #define GetClassLongPtrA GetClassLongA
326 #define GetClassLongPtrW GetClassLongW
327 #ifdef UNICODE
328 #define GetClassLongPtr GetClassLongPtrW
329 #else
330 #define GetClassLongPtr GetClassLongPtrA
331 #endif // !UNICODE
332 #endif // !GetClassLongPtr
333
334 #ifndef GCLP_HICONSM
335 #define GCLP_HICONSM (-34)
336 #endif // !GCLP_HICONSM
337
338 #ifndef GetWindowLongPtr
339 #define GetWindowLongPtrA GetWindowLongA
340 #define GetWindowLongPtrW GetWindowLongW
341 #ifdef UNICODE
342 #define GetWindowLongPtr GetWindowLongPtrW
343 #else
344 #define GetWindowLongPtr GetWindowLongPtrA
345 #endif // !UNICODE
346 #endif // !GetWindowLongPtr
347
348 #ifndef SetWindowLongPtr
349 #define SetWindowLongPtrA SetWindowLongA
350 #define SetWindowLongPtrW SetWindowLongW
351 #ifdef UNICODE
352 #define SetWindowLongPtr SetWindowLongPtrW
353 #else
354 #define SetWindowLongPtr SetWindowLongPtrA
355 #endif // !UNICODE
356 #endif // !SetWindowLongPtr
357
358 #ifndef GWLP_WNDPROC
359 #define GWLP_WNDPROC (-4)
360 #endif
361 #ifndef GWLP_HINSTANCE
362 #define GWLP_HINSTANCE (-6)
363 #endif
364 #ifndef GWLP_HWNDPARENT
365 #define GWLP_HWNDPARENT (-8)
366 #endif
367 #ifndef GWLP_USERDATA
368 #define GWLP_USERDATA (-21)
369 #endif
370 #ifndef GWLP_ID
371 #define GWLP_ID (-12)
372 #endif
373
374 #ifndef DWLP_MSGRESULT
375 #define DWLP_MSGRESULT 0
376 #endif
377
378 typedef long LONG_PTR;
379 typedef unsigned long ULONG_PTR;
380 typedef ULONG_PTR DWORD_PTR;
381
382 #ifndef HandleToUlong
383 #define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
384 #endif
385 #ifndef HandleToLong
386 #define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
387 #endif
388 #ifndef LongToHandle
389 #define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
390 #endif
391 #ifndef PtrToUlong
392 #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
393 #endif
394 #ifndef PtrToLong
395 #define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
396 #endif
397 #ifndef PtrToUint
398 #define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
399 #endif
400 #ifndef PtrToInt
401 #define PtrToInt( p ) ((INT)(INT_PTR) (p) )
402 #endif
403 #ifndef PtrToUshort
404 #define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
405 #endif
406 #ifndef PtrToShort
407 #define PtrToShort( p ) ((short)(LONG_PTR)(p) )
408 #endif
409 #ifndef IntToPtr
410 #define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i))
411 #endif
412 #ifndef UIntToPtr
413 #define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui))
414 #endif
415 #ifndef LongToPtr
416 #define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l))
417 #endif
418 #ifndef ULongToPtr
419 #define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul))
420 #endif
421
422 #endif // !defined(_WIN64) && (_ATL_VER < 0x0700)
423 #endif // !_ATL_NO_OLD_HEADERS_WIN64
424
425
426 ///////////////////////////////////////////////////////////////////////////////
427 // Global support for using original VC++ 7.x headers with WTL
428
429 #if (_MSC_VER >= 1300) && (_MSC_VER < 1400)
430
431 #ifndef BS_PUSHBOX
432 #define BS_PUSHBOX 0x0000000AL
433 #endif
434
435 #pragma warning(disable: 4244) // conversion from 'type1' to 'type2', possible loss of data
436
437 #endif // (_MSC_VER >= 1300) && (_MSC_VER < 1400)
438
439
440 ///////////////////////////////////////////////////////////////////////////////
441 // Global support for old SDK headers
442
443 #ifndef BTNS_BUTTON
444 #define BTNS_BUTTON TBSTYLE_BUTTON
445 #endif
446
447 #ifndef BTNS_SEP
448 #define BTNS_SEP TBSTYLE_SEP
449 #endif
450
451 #ifndef BTNS_CHECK
452 #define BTNS_CHECK TBSTYLE_CHECK
453 #endif
454
455 #ifndef BTNS_GROUP
456 #define BTNS_GROUP TBSTYLE_GROUP
457 #endif
458
459 #ifndef BTNS_CHECKGROUP
460 #define BTNS_CHECKGROUP TBSTYLE_CHECKGROUP
461 #endif
462
463 #if (_WIN32_IE >= 0x0300)
464 #ifndef BTNS_DROPDOWN
465 #define BTNS_DROPDOWN TBSTYLE_DROPDOWN
466 #endif
467 #endif
468
469 #if (_WIN32_IE >= 0x0400)
470 #ifndef BTNS_AUTOSIZE
471 #define BTNS_AUTOSIZE TBSTYLE_AUTOSIZE
472 #endif
473
474 #ifndef BTNS_NOPREFIX
475 #define BTNS_NOPREFIX TBSTYLE_NOPREFIX
476 #endif
477 #endif
478
479
480 ///////////////////////////////////////////////////////////////////////////////
481 // Global support for SecureHelper functions
482
483 #ifndef _TRUNCATE
484 #define _TRUNCATE ((size_t)-1)
485 #endif
486
487 #ifndef _ERRCODE_DEFINED
488 #define _ERRCODE_DEFINED
489 typedef int errno_t;
490 #endif
491
492 #ifndef _SECURECRT_ERRCODE_VALUES_DEFINED
493 #define _SECURECRT_ERRCODE_VALUES_DEFINED
494 #define EINVAL 22
495 #define STRUNCATE 80
496 #endif
497
498 #ifndef _countof
499 #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
500 #endif
501
502
503 ///////////////////////////////////////////////////////////////////////////////
504 // Miscellaneous global support
505
506 // define useful macros from winuser.h
507 #ifndef IS_INTRESOURCE
508 #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
509 #endif // IS_INTRESOURCE
510
511 // protect template members from windowsx.h macros
512 #ifdef _INC_WINDOWSX
513 #undef SubclassWindow
514 #endif // _INC_WINDOWSX
515
516 // define useful macros from windowsx.h
517 #ifndef GET_X_LPARAM
518 #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
519 #endif
520 #ifndef GET_Y_LPARAM
521 #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
522 #endif
523
524 // Dummy structs for compiling with /CLR
525 #if (_MSC_VER >= 1300) && defined(_MANAGED)
526 __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
527 __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
528 __if_not_exists(_PSP::_PSP) { struct _PSP { }; }
529 #endif
530
531 // Define ATLVERIFY macro for ATL3
532 #if (_ATL_VER < 0x0700)
533 #ifndef ATLVERIFY
534 #ifdef _DEBUG
535 #define ATLVERIFY(expr) ATLASSERT(expr)
536 #else
537 #define ATLVERIFY(expr) (expr)
538 #endif // DEBUG
539 #endif // ATLVERIFY
540 #endif // (_ATL_VER < 0x0700)
541
542 // Forward declaration for ATL3 and ATL11 fix
543 #if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
544 namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); };
545 #endif
546
547 #ifndef WM_MOUSEHWHEEL
548 #define WM_MOUSEHWHEEL 0x020E
549 #endif
550
551
552 namespace WTL
553 {
554
555 #if (_ATL_VER >= 0x0700)
556 DECLARE_TRACE_CATEGORY(atlTraceUI);
557 #ifdef _DEBUG
558 __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
559 #endif // _DEBUG
560 #else // !(_ATL_VER >= 0x0700)
561 enum wtlTraceFlags
562 {
563 atlTraceUI = 0x10000000
564 };
565 #endif // !(_ATL_VER >= 0x0700)
566
567 // Windows version helper
568 inline bool AtlIsOldWindows()
569 {
570 #ifdef _versionhelpers_H_INCLUDED_
571 return !::IsWindowsVersionOrGreater(4, 90, 0);
572 #else // !_versionhelpers_H_INCLUDED_
573 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
574 BOOL bRet = ::GetVersionEx(&ovi);
575 return (!bRet || !((ovi.dwMajorVersion >= 5) || (ovi.dwMajorVersion == 4 && ovi.dwMinorVersion >= 90)));
576 #endif // _versionhelpers_H_INCLUDED_
577 }
578
579 // Default GUI font helper - "MS Shell Dlg" stock font
580 inline HFONT AtlGetDefaultGuiFont()
581 {
582 #ifndef _WIN32_WCE
583 return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
584 #else // CE specific
585 return (HFONT)::GetStockObject(SYSTEM_FONT);
586 #endif // _WIN32_WCE
587 }
588
589 // Control font helper - default font for controls not in a dialog
590 // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
591 inline HFONT AtlCreateControlFont()
592 {
593 #ifndef _WIN32_WCE
594 LOGFONT lf = { 0 };
595 ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
596 HFONT hFont = ::CreateFontIndirect(&lf);
597 ATLASSERT(hFont != NULL);
598 return hFont;
599 #else // CE specific
600 return (HFONT)::GetStockObject(SYSTEM_FONT);
601 #endif // _WIN32_WCE
602 }
603
604 // Bold font helper
605 // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
606 inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
607 {
608 LOGFONT lf = { 0 };
609 #ifndef _WIN32_WCE
610 if(hFont == NULL)
611 ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
612 else
613 ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
614 #else // CE specific
615 if(hFont == NULL)
616 hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
617 ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
618 #endif // _WIN32_WCE
619 lf.lfWeight = FW_BOLD;
620 HFONT hFontBold = ::CreateFontIndirect(&lf);
621 ATLASSERT(hFontBold != NULL);
622 return hFontBold;
623 }
624
625 // Common Controls initialization helper
626 inline BOOL AtlInitCommonControls(DWORD dwFlags)
627 {
628 INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
629 BOOL bRet = ::InitCommonControlsEx(&iccx);
630 ATLASSERT(bRet);
631 return bRet;
632 }
633
634
635 ///////////////////////////////////////////////////////////////////////////////
636 // RunTimeHelper - helper functions for Windows version and structure sizes
637
638 // Not for Windows CE
639 #if defined(_WIN32_WCE) && !defined(_WTL_NO_RUNTIME_STRUCT_SIZE)
640 #define _WTL_NO_RUNTIME_STRUCT_SIZE
641 #endif
642
643 #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
644
645 #ifndef _SIZEOF_STRUCT
646 #define _SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
647 #endif
648
649 #if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
650 #define REBARBANDINFO_V6_SIZE _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
651 #endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
652
653 #if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
654 #define LVGROUP_V5_SIZE _SIZEOF_STRUCT(LVGROUP, uAlign)
655 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
656
657 #if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
658 #define LVTILEINFO_V5_SIZE _SIZEOF_STRUCT(LVTILEINFO, puColumns)
659 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
660
661 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
662 #define MCHITTESTINFO_V1_SIZE _SIZEOF_STRUCT(MCHITTESTINFO, st)
663 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
664
665 #if !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
666 #define NONCLIENTMETRICS_V1_SIZE _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
667 #endif // !defined(_WIN32_WCE) && (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
668
669 #if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0501) && !defined(TTTOOLINFO_V2_SIZE)
670 #define TTTOOLINFO_V2_SIZE _SIZEOF_STRUCT(TTTOOLINFO, lParam)
671 #endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0501) && !defined(TTTOOLINFO_V2_SIZE)
672
673 #endif // !_WTL_NO_RUNTIME_STRUCT_SIZE
674
675 namespace RunTimeHelper
676 {
677 #ifndef _WIN32_WCE
678 inline bool IsCommCtrl6()
679 {
680 DWORD dwMajor = 0, dwMinor = 0;
681 HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
682 return (SUCCEEDED(hRet) && (dwMajor >= 6));
683 }
684
685 inline bool IsVista()
686 {
687 #ifdef _versionhelpers_H_INCLUDED_
688 return ::IsWindowsVistaOrGreater();
689 #else // !_versionhelpers_H_INCLUDED_
690 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
691 BOOL bRet = ::GetVersionEx(&ovi);
692 return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
693 #endif // _versionhelpers_H_INCLUDED_
694 }
695
696 inline bool IsThemeAvailable()
697 {
698 bool bRet = false;
699
700 if(IsCommCtrl6())
701 {
702 HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
703 if(hThemeDLL != NULL)
704 {
705 typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)();
706 PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThemeActive)::GetProcAddress(hThemeDLL, "IsThemeActive");
707 ATLASSERT(pfnIsThemeActive != NULL);
708 bRet = (pfnIsThemeActive != NULL) && (pfnIsThemeActive() != FALSE);
709 if(bRet)
710 {
711 typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)();
712 PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppThemed)::GetProcAddress(hThemeDLL, "IsAppThemed");
713 ATLASSERT(pfnIsAppThemed != NULL);
714 bRet = (pfnIsAppThemed != NULL) && (pfnIsAppThemed() != FALSE);
715 }
716
717 ::FreeLibrary(hThemeDLL);
718 }
719 }
720
721 return bRet;
722 }
723
724 inline bool IsWin7()
725 {
726 #ifdef _versionhelpers_H_INCLUDED_
727 return ::IsWindows7OrGreater();
728 #else // !_versionhelpers_H_INCLUDED_
729 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
730 BOOL bRet = ::GetVersionEx(&ovi);
731 return ((bRet != FALSE) && (ovi.dwMajorVersion == 6) && (ovi.dwMinorVersion >= 1));
732 #endif // _versionhelpers_H_INCLUDED_
733 }
734
735 inline bool IsRibbonUIAvailable()
736 {
737 static INT iRibbonUI = -1;
738
739 #if defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
740 if (iRibbonUI == -1)
741 {
742 HMODULE hRibbonDLL = ::LoadLibrary(_T("propsys.dll"));
743 if (hRibbonDLL != NULL)
744 {
745 const GUID CLSID_UIRibbonFramework = { 0x926749fa, 0x2615, 0x4987, { 0x88, 0x45, 0xc3, 0x3e, 0x65, 0xf2, 0xb9, 0x57 } };
746 // block - create instance
747 {
748 ATL::CComPtr<IUnknown> pIUIFramework;
749 iRibbonUI = SUCCEEDED(pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework)) ? 1 : 0;
750 }
751 ::FreeLibrary(hRibbonDLL);
752 }
753 else
754 {
755 iRibbonUI = 0;
756 }
757 }
758 #endif // defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
759
760 return (iRibbonUI == 1);
761 }
762
763 #endif // !_WIN32_WCE
764
765 inline UINT SizeOf_REBARBANDINFO()
766 {
767 UINT uSize = sizeof(REBARBANDINFO);
768 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
769 if(!(IsVista() && IsCommCtrl6()))
770 uSize = REBARBANDINFO_V6_SIZE;
771 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
772 return uSize;
773 }
774
775 #if (_WIN32_WINNT >= 0x501)
776 inline UINT SizeOf_LVGROUP()
777 {
778 UINT uSize = sizeof(LVGROUP);
779 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
780 if(!IsVista())
781 uSize = LVGROUP_V5_SIZE;
782 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
783 return uSize;
784 }
785
786 inline UINT SizeOf_LVTILEINFO()
787 {
788 UINT uSize = sizeof(LVTILEINFO);
789 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
790 if(!IsVista())
791 uSize = LVTILEINFO_V5_SIZE;
792 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
793 return uSize;
794 }
795 #endif // (_WIN32_WINNT >= 0x501)
796
797 inline UINT SizeOf_MCHITTESTINFO()
798 {
799 UINT uSize = sizeof(MCHITTESTINFO);
800 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
801 if(!(IsVista() && IsCommCtrl6()))
802 uSize = MCHITTESTINFO_V1_SIZE;
803 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
804 return uSize;
805 }
806
807 #ifndef _WIN32_WCE
808 inline UINT SizeOf_NONCLIENTMETRICS()
809 {
810 UINT uSize = sizeof(NONCLIENTMETRICS);
811 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
812 if(!IsVista())
813 uSize = NONCLIENTMETRICS_V1_SIZE;
814 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
815 return uSize;
816 }
817
818 inline UINT SizeOf_TOOLINFO()
819 {
820 UINT uSize = sizeof(TOOLINFO);
821 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0501)
822 if(!IsVista())
823 uSize = TTTOOLINFO_V2_SIZE;
824 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0501)
825 return uSize;
826 }
827 #endif // !_WIN32_WCE
828 };
829
830
831 ///////////////////////////////////////////////////////////////////////////////
832 // ModuleHelper - helper functions for ATL3 and ATL7 module classes
833
834 namespace ModuleHelper
835 {
836 inline HINSTANCE GetModuleInstance()
837 {
838 #if (_ATL_VER >= 0x0700)
839 return ATL::_AtlBaseModule.GetModuleInstance();
840 #else // !(_ATL_VER >= 0x0700)
841 return ATL::_pModule->GetModuleInstance();
842 #endif // !(_ATL_VER >= 0x0700)
843 }
844
845 inline HINSTANCE GetResourceInstance()
846 {
847 #if (_ATL_VER >= 0x0700)
848 return ATL::_AtlBaseModule.GetResourceInstance();
849 #else // !(_ATL_VER >= 0x0700)
850 return ATL::_pModule->GetResourceInstance();
851 #endif // !(_ATL_VER >= 0x0700)
852 }
853
854 inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
855 {
856 #if (_ATL_VER >= 0x0700)
857 ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
858 #else // !(_ATL_VER >= 0x0700)
859 ATL::_pModule->AddCreateWndData(pData, pObject);
860 #endif // !(_ATL_VER >= 0x0700)
861 }
862
863 inline void* ExtractCreateWndData()
864 {
865 #if (_ATL_VER >= 0x0700)
866 return ATL::_AtlWinModule.ExtractCreateWndData();
867 #else // !(_ATL_VER >= 0x0700)
868 return ATL::_pModule->ExtractCreateWndData();
869 #endif // !(_ATL_VER >= 0x0700)
870 }
871 };
872
873
874 ///////////////////////////////////////////////////////////////////////////////
875 // SecureHelper - helper functions for VS2005 secure CRT
876
877 namespace SecureHelper
878 {
879 inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
880 {
881 #if _SECURE_ATL
882 ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
883 #else
884 if(cchDest > (size_t)lstrlenA(lpstrSrc))
885 ATLVERIFY(lstrcpyA(lpstrDest, lpstrSrc) != NULL);
886 else
887 ATLASSERT(FALSE);
888 #endif
889 }
890
891 inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
892 {
893 #if _SECURE_ATL
894 ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
895 #else
896 if(cchDest > (size_t)lstrlenW(lpstrSrc))
897 ATLVERIFY(lstrcpyW(lpstrDest, lpstrSrc) != NULL);
898 else
899 ATLASSERT(FALSE);
900 #endif
901 }
902
903 inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
904 {
905 #ifdef _UNICODE
906 strcpyW_x(lpstrDest, cchDest, lpstrSrc);
907 #else
908 strcpyA_x(lpstrDest, cchDest, lpstrSrc);
909 #endif
910 }
911
912 inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
913 {
914 #if _SECURE_ATL
915 return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
916 #else
917 errno_t nRet = 0;
918 if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
919 {
920 nRet = EINVAL;
921 }
922 else if(cchCount == _TRUNCATE)
923 {
924 cchCount = __min(cchDest - 1, size_t(lstrlenA(lpstrSrc)));
925 nRet = STRUNCATE;
926 }
927 else if(cchDest <= cchCount)
928 {
929 lpstrDest[0] = 0;
930 nRet = EINVAL;
931 }
932 if(nRet == 0 || nRet == STRUNCATE)
933 nRet = (lstrcpynA(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
934 ATLASSERT(nRet == 0 || nRet == STRUNCATE);
935 return nRet;
936 #endif
937 }
938
939 inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
940 {
941 #if _SECURE_ATL
942 return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
943 #else
944 errno_t nRet = 0;
945 if(lpstrDest == NULL || cchDest == 0 || lpstrSrc == NULL)
946 {
947 nRet = EINVAL;
948 }
949 else if(cchCount == _TRUNCATE)
950 {
951 cchCount = __min(cchDest - 1, size_t(lstrlenW(lpstrSrc)));
952 nRet = STRUNCATE;
953 }
954 else if(cchDest <= cchCount)
955 {
956 lpstrDest[0] = 0;
957 nRet = EINVAL;
958 }
959 if(nRet == 0 || nRet == STRUNCATE)
960 nRet = (lstrcpynW(lpstrDest, lpstrSrc, (int)cchCount + 1) != NULL) ? nRet : EINVAL;
961 ATLASSERT(nRet == 0 || nRet == STRUNCATE);
962 return nRet;
963 #endif
964 }
965
966 inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
967 {
968 #ifdef _UNICODE
969 return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
970 #else
971 return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
972 #endif
973 }
974
975 inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
976 {
977 #if _SECURE_ATL
978 ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
979 #else
980 if(cchDest > (size_t)lstrlenA(lpstrSrc))
981 ATLVERIFY(lstrcatA(lpstrDest, lpstrSrc) != NULL);
982 else
983 ATLASSERT(FALSE);
984 #endif
985 }
986
987 inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
988 {
989 #if _SECURE_ATL
990 ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
991 #else
992 if(cchDest > (size_t)lstrlenW(lpstrSrc))
993 ATLVERIFY(lstrcatW(lpstrDest, lpstrSrc) != NULL);
994 else
995 ATLASSERT(FALSE);
996 #endif
997 }
998
999 inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
1000 {
1001 #ifdef _UNICODE
1002 strcatW_x(lpstrDest, cchDest, lpstrSrc);
1003 #else
1004 strcatA_x(lpstrDest, cchDest, lpstrSrc);
1005 #endif
1006 }
1007
1008 inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
1009 {
1010 #if _SECURE_ATL
1011 ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
1012 #else
1013 if(cbDest >= cbSrc)
1014 memcpy(pDest, pSrc, cbSrc);
1015 else
1016 ATLASSERT(FALSE);
1017 #endif
1018 }
1019
1020 inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
1021 {
1022 #if _SECURE_ATL
1023 ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
1024 #else
1025 if(cbDest >= cbSrc)
1026 memmove(pDest, pSrc, cbSrc);
1027 else
1028 ATLASSERT(FALSE);
1029 #endif
1030 }
1031
1032 inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
1033 {
1034 #if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
1035 return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
1036 #else
1037 cchBuff; // Avoid unused argument warning
1038 #pragma warning(push)
1039 #pragma warning(disable: 4996)
1040 return _vstprintf(lpstrBuff, lpstrFormat, args);
1041 #pragma warning(pop)
1042 #endif
1043 }
1044
1045 inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
1046 {
1047 #if _SECURE_ATL && !defined(_ATL_MIN_CRT) && !defined(_WIN32_WCE)
1048 return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
1049 #else
1050 cchBuff; // Avoid unused argument warning
1051 return ::wvsprintf(lpstrBuff, lpstrFormat, args);
1052 #endif
1053 }
1054
1055 inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
1056 {
1057 va_list args;
1058 va_start(args, lpstrFormat);
1059 int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
1060 va_end(args);
1061 return nRes;
1062 }
1063
1064 inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
1065 {
1066 va_list args;
1067 va_start(args, lpstrFormat);
1068 int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
1069 va_end(args);
1070 return nRes;
1071 }
1072 }; // namespace SecureHelper
1073
1074
1075 ///////////////////////////////////////////////////////////////////////////////
1076 // MinCrtHelper - helper functions for using _ATL_MIN_CRT
1077
1078 namespace MinCrtHelper
1079 {
1080 inline int _isspace(TCHAR ch)
1081 {
1082 #ifndef _ATL_MIN_CRT
1083 return _istspace(ch);
1084 #else // _ATL_MIN_CRT
1085 WORD type = 0;
1086 ::GetStringTypeEx(::GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
1087 return (type & C1_SPACE) == C1_SPACE;
1088 #endif // _ATL_MIN_CRT
1089 }
1090
1091 inline int _isdigit(TCHAR ch)
1092 {
1093 #ifndef _ATL_MIN_CRT
1094 return _istdigit(ch);
1095 #else // _ATL_MIN_CRT
1096 WORD type = 0;
1097 ::GetStringTypeEx(::GetThreadLocale(), CT_CTYPE1, &ch, 1, &type);
1098 return (type & C1_DIGIT) == C1_DIGIT;
1099 #endif // _ATL_MIN_CRT
1100 }
1101
1102 inline int _atoi(LPCTSTR str)
1103 {
1104 #ifndef _ATL_MIN_CRT
1105 return _ttoi(str);
1106 #else // _ATL_MIN_CRT
1107 while(_isspace(*str) != 0)
1108 ++str;
1109
1110 TCHAR ch = *str++;
1111 TCHAR sign = ch; // save sign indication
1112 if(ch == _T('-') || ch == _T('+'))
1113 ch = *str++; // skip sign
1114
1115 int total = 0;
1116 while(_isdigit(ch) != 0)
1117 {
1118 total = 10 * total + (ch - '0'); // accumulate digit
1119 ch = *str++; // get next char
1120 }
1121
1122 return (sign == '-') ? -total : total; // return result, negated if necessary
1123 #endif // _ATL_MIN_CRT
1124 }
1125
1126 inline LPCTSTR _strrchr(LPCTSTR str, TCHAR ch)
1127 {
1128 #ifndef _ATL_MIN_CRT
1129 return _tcsrchr(str, ch);
1130 #else // _ATL_MIN_CRT
1131 LPCTSTR lpsz = NULL;
1132 while(*str != 0)
1133 {
1134 if(*str == ch)
1135 lpsz = str;
1136 str = ::CharNext(str);
1137 }
1138 return lpsz;
1139 #endif // _ATL_MIN_CRT
1140 }
1141
1142 inline LPTSTR _strrchr(LPTSTR str, TCHAR ch)
1143 {
1144 #ifndef _ATL_MIN_CRT
1145 return _tcsrchr(str, ch);
1146 #else // _ATL_MIN_CRT
1147 LPTSTR lpsz = NULL;
1148 while(*str != 0)
1149 {
1150 if(*str == ch)
1151 lpsz = str;
1152 str = ::CharNext(str);
1153 }
1154 return lpsz;
1155 #endif // _ATL_MIN_CRT
1156 }
1157 }; // namespace MinCrtHelper
1158
1159
1160 ///////////////////////////////////////////////////////////////////////////////
1161 // GenericWndClass - generic window class usable for subclassing
1162
1163 // Use in dialog templates to specify a placeholder to be subclassed
1164 // Specify as a custom control with class name WTL_GenericWindow
1165 // Call Rregister() before creating dialog (for example, in WinMain)
1166 namespace GenericWndClass
1167 {
1168 inline LPCTSTR GetName()
1169 {
1170 return _T("WTL_GenericWindow");
1171 }
1172
1173 inline ATOM Register()
1174 {
1175 #ifndef _WIN32_WCE
1176 WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
1177 #else
1178 WNDCLASS wc = { 0 };
1179 #endif
1180 wc.lpfnWndProc = ::DefWindowProc;
1181 wc.hInstance = ModuleHelper::GetModuleInstance();
1182 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
1183 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1184 wc.lpszClassName = GetName();
1185 #ifndef _WIN32_WCE
1186 ATOM atom = ::RegisterClassEx(&wc);
1187 #else
1188 ATOM atom = ::RegisterClass(&wc);
1189 #endif
1190 ATLASSERT(atom != 0);
1191 return atom;
1192 }
1193
1194 inline BOOL Unregister() // only needed for DLLs or tmp use
1195 {
1196 return ::UnregisterClass(GetName(), ModuleHelper::GetModuleInstance());
1197 }
1198 }; // namespace GenericWndClass
1199
1200
1201 ///////////////////////////////////////////////////////////////////////////////
1202 // CMessageFilter - Interface for message filter support
1203
1204 class CMessageFilter
1205 {
1206 public:
1207 virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
1208 };
1209
1210
1211 ///////////////////////////////////////////////////////////////////////////////
1212 // CIdleHandler - Interface for idle processing
1213
1214 class CIdleHandler
1215 {
1216 public:
1217 virtual BOOL OnIdle() = 0;
1218 };
1219
1220 #ifndef _ATL_NO_OLD_NAMES
1221 // for compatilibility with old names only
1222 typedef CIdleHandler CUpdateUIObject;
1223 #define DoUpdate OnIdle
1224 #endif // !_ATL_NO_OLD_NAMES
1225
1226
1227 ///////////////////////////////////////////////////////////////////////////////
1228 // CMessageLoop - message loop implementation
1229
1230 class CMessageLoop
1231 {
1232 public:
1233 ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
1234 ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
1235 MSG m_msg;
1236
1237 // Message filter operations
1238 BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
1239 {
1240 return m_aMsgFilter.Add(pMessageFilter);
1241 }
1242
1243 BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
1244 {
1245 return m_aMsgFilter.Remove(pMessageFilter);
1246 }
1247
1248 // Idle handler operations
1249 BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
1250 {
1251 return m_aIdleHandler.Add(pIdleHandler);
1252 }
1253
1254 BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
1255 {
1256 return m_aIdleHandler.Remove(pIdleHandler);
1257 }
1258
1259 #ifndef _ATL_NO_OLD_NAMES
1260 // for compatilibility with old names only
1261 BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
1262 {
1263 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
1264 return AddIdleHandler(pIdleHandler);
1265 }
1266
1267 BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
1268 {
1269 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
1270 return RemoveIdleHandler(pIdleHandler);
1271 }
1272 #endif // !_ATL_NO_OLD_NAMES
1273
1274 // message loop
1275 int Run()
1276 {
1277 BOOL bDoIdle = TRUE;
1278 int nIdleCount = 0;
1279 BOOL bRet;
1280
1281 for(;;)
1282 {
1283 while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
1284 {
1285 if(!OnIdle(nIdleCount++))
1286 bDoIdle = FALSE;
1287 }
1288
1289 bRet = ::GetMessage(&m_msg, NULL, 0, 0);
1290
1291 if(bRet == -1)
1292 {
1293 ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
1294 continue; // error, don't process
1295 }
1296 else if(!bRet)
1297 {
1298 ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
1299 break; // WM_QUIT, exit message loop
1300 }
1301
1302 if(!PreTranslateMessage(&m_msg))
1303 {
1304 ::TranslateMessage(&m_msg);
1305 ::DispatchMessage(&m_msg);
1306 }
1307
1308 if(IsIdleMessage(&m_msg))
1309 {
1310 bDoIdle = TRUE;
1311 nIdleCount = 0;
1312 }
1313 }
1314
1315 return (int)m_msg.wParam;
1316 }
1317
1318 static BOOL IsIdleMessage(MSG* pMsg)
1319 {
1320 // These messages should NOT cause idle processing
1321 switch(pMsg->message)
1322 {
1323 case WM_MOUSEMOVE:
1324 #ifndef _WIN32_WCE
1325 case WM_NCMOUSEMOVE:
1326 #endif // !_WIN32_WCE
1327 case WM_PAINT:
1328 case 0x0118: // WM_SYSTIMER (caret blink)
1329 return FALSE;
1330 }
1331
1332 return TRUE;
1333 }
1334
1335 // Overrideables
1336 // Override to change message filtering
1337 virtual BOOL PreTranslateMessage(MSG* pMsg)
1338 {
1339 // loop backwards
1340 for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
1341 {
1342 CMessageFilter* pMessageFilter = m_aMsgFilter[i];
1343 if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
1344 return TRUE;
1345 }
1346 return FALSE; // not translated
1347 }
1348
1349 // override to change idle processing
1350 virtual BOOL OnIdle(int /*nIdleCount*/)
1351 {
1352 for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
1353 {
1354 CIdleHandler* pIdleHandler = m_aIdleHandler[i];
1355 if(pIdleHandler != NULL)
1356 pIdleHandler->OnIdle();
1357 }
1358 return FALSE; // don't continue
1359 }
1360 };
1361
1362
1363 ///////////////////////////////////////////////////////////////////////////////
1364 // CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
1365 // internal classes to manage critical sections for both ATL3 and ATL7
1366
1367 class CStaticDataInitCriticalSectionLock
1368 {
1369 public:
1370 #if (_ATL_VER >= 0x0700)
1371 ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
1372
1373 CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
1374 { }
1375 #endif // (_ATL_VER >= 0x0700)
1376
1377 HRESULT Lock()
1378 {
1379 #if (_ATL_VER >= 0x0700)
1380 return m_cslock.Lock();
1381 #else // !(_ATL_VER >= 0x0700)
1382 ::EnterCriticalSection(&ATL::_pModule->m_csStaticDataInit);
1383 return S_OK;
1384 #endif // !(_ATL_VER >= 0x0700)
1385 }
1386
1387 void Unlock()
1388 {
1389 #if (_ATL_VER >= 0x0700)
1390 m_cslock.Unlock();
1391 #else // !(_ATL_VER >= 0x0700)
1392 ::LeaveCriticalSection(&ATL::_pModule->m_csStaticDataInit);
1393 #endif // !(_ATL_VER >= 0x0700)
1394 }
1395 };
1396
1397
1398 class CWindowCreateCriticalSectionLock
1399 {
1400 public:
1401 #if (_ATL_VER >= 0x0700)
1402 ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
1403
1404 CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
1405 { }
1406 #endif // (_ATL_VER >= 0x0700)
1407
1408 HRESULT Lock()
1409 {
1410 #if (_ATL_VER >= 0x0700)
1411 return m_cslock.Lock();
1412 #else // !(_ATL_VER >= 0x0700)
1413 ::EnterCriticalSection(&ATL::_pModule->m_csWindowCreate);
1414 return S_OK;
1415 #endif // !(_ATL_VER >= 0x0700)
1416 }
1417
1418 void Unlock()
1419 {
1420 #if (_ATL_VER >= 0x0700)
1421 m_cslock.Unlock();
1422 #else // !(_ATL_VER >= 0x0700)
1423 ::LeaveCriticalSection(&ATL::_pModule->m_csWindowCreate);
1424 #endif // !(_ATL_VER >= 0x0700)
1425 }
1426 };
1427
1428
1429 ///////////////////////////////////////////////////////////////////////////////
1430 // CTempBuffer - helper class for stack allocations for ATL3
1431
1432 #ifndef _WTL_STACK_ALLOC_THRESHOLD
1433 #define _WTL_STACK_ALLOC_THRESHOLD 512
1434 #endif
1435
1436 #if (_ATL_VER >= 0x0700)
1437
1438 using ATL::CTempBuffer;
1439
1440 #else // !(_ATL_VER >= 0x0700)
1441
1442 #ifndef SIZE_MAX
1443 #ifdef _WIN64
1444 #define SIZE_MAX _UI64_MAX
1445 #else
1446 #define SIZE_MAX UINT_MAX
1447 #endif
1448 #endif
1449
1450 #pragma warning(push)
1451 #pragma warning(disable: 4284) // warning for operator ->
1452
1453 template<typename T, int t_nFixedBytes = 128>
1454 class CTempBuffer
1455 {
1456 public:
1457 CTempBuffer() : m_p(NULL)
1458 {
1459 }
1460
1461 CTempBuffer(size_t nElements) : m_p(NULL)
1462 {
1463 Allocate(nElements);
1464 }
1465
1466 ~CTempBuffer()
1467 {
1468 if(m_p != reinterpret_cast<T*>(m_abFixedBuffer))
1469 free(m_p);
1470 }
1471
1472 operator T*() const
1473 {
1474 return m_p;
1475 }
1476
1477 T* operator ->() const
1478 {
1479 ATLASSERT(m_p != NULL);
1480 return m_p;
1481 }
1482
1483 T* Allocate(size_t nElements)
1484 {
1485 ATLASSERT(nElements <= (SIZE_MAX / sizeof(T)));
1486 return AllocateBytes(nElements * sizeof(T));
1487 }
1488
1489 T* AllocateBytes(size_t nBytes)
1490 {
1491 ATLASSERT(m_p == NULL);
1492 if(nBytes > t_nFixedBytes)
1493 m_p = static_cast<T*>(malloc(nBytes));
1494 else
1495 m_p = reinterpret_cast<T*>(m_abFixedBuffer);
1496
1497 return m_p;
1498 }
1499
1500 private:
1501 T* m_p;
1502 BYTE m_abFixedBuffer[t_nFixedBytes];
1503 };
1504
1505 #pragma warning(pop)
1506
1507 #endif // !(_ATL_VER >= 0x0700)
1508
1509
1510 ///////////////////////////////////////////////////////////////////////////////
1511 // CAppModule - module class for an application
1512
1513 class CAppModule : public ATL::CComModule
1514 {
1515 public:
1516 DWORD m_dwMainThreadID;
1517 ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
1518 ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;
1519
1520 // Overrides of CComModule::Init and Term
1521 HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
1522 {
1523 HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
1524 if(FAILED(hRet))
1525 return hRet;
1526
1527 m_dwMainThreadID = ::GetCurrentThreadId();
1528 typedef ATL::CSimpleMap<DWORD, CMessageLoop*> _mapClass;
1529 m_pMsgLoopMap = NULL;
1530 ATLTRY(m_pMsgLoopMap = new _mapClass);
1531 if(m_pMsgLoopMap == NULL)
1532 return E_OUTOFMEMORY;
1533 m_pSettingChangeNotify = NULL;
1534
1535 return hRet;
1536 }
1537
1538 void Term()
1539 {
1540 TermSettingChangeNotify();
1541 delete m_pMsgLoopMap;
1542 CComModule::Term();
1543 }
1544
1545 // Message loop map methods
1546 BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
1547 {
1548 CStaticDataInitCriticalSectionLock lock;
1549 if(FAILED(lock.Lock()))
1550 {
1551 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
1552 ATLASSERT(FALSE);
1553 return FALSE;
1554 }
1555
1556 ATLASSERT(pMsgLoop != NULL);
1557 ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet
1558
1559 BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
1560
1561 lock.Unlock();
1562
1563 return bRet;
1564 }
1565
1566 BOOL RemoveMessageLoop()
1567 {
1568 CStaticDataInitCriticalSectionLock lock;
1569 if(FAILED(lock.Lock()))
1570 {
1571 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
1572 ATLASSERT(FALSE);
1573 return FALSE;
1574 }
1575
1576 BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());
1577
1578 lock.Unlock();
1579
1580 return bRet;
1581 }
1582
1583 CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
1584 {
1585 CStaticDataInitCriticalSectionLock lock;
1586 if(FAILED(lock.Lock()))
1587 {
1588 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
1589 ATLASSERT(FALSE);
1590 return NULL;
1591 }
1592
1593 CMessageLoop* pLoop = m_pMsgLoopMap->Lookup(dwThreadID);
1594
1595 lock.Unlock();
1596
1597 return pLoop;
1598 }
1599
1600 // Setting change notify methods
1601 // Note: Call this from the main thread for MSDI apps
1602 BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
1603 {
1604 CStaticDataInitCriticalSectionLock lock;
1605 if(FAILED(lock.Lock()))
1606 {
1607 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
1608 ATLASSERT(FALSE);
1609 return FALSE;
1610 }
1611
1612 if(m_pSettingChangeNotify == NULL)
1613 {
1614 typedef ATL::CSimpleArray<HWND> _notifyClass;
1615 ATLTRY(m_pSettingChangeNotify = new _notifyClass);
1616 ATLASSERT(m_pSettingChangeNotify != NULL);
1617 }
1618
1619 BOOL bRet = (m_pSettingChangeNotify != NULL);
1620 if(bRet && m_pSettingChangeNotify->GetSize() == 0)
1621 {
1622 // init everything
1623 _ATL_EMPTY_DLGTEMPLATE templ;
1624 HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
1625 ATLASSERT(::IsWindow(hNtfWnd));
1626 if(::IsWindow(hNtfWnd))
1627 {
1628 // need conditional code because types don't match in winuser.h
1629 #ifdef _WIN64
1630 ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
1631 #else
1632 ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
1633 #endif
1634 bRet = m_pSettingChangeNotify->Add(hNtfWnd);
1635 }
1636 else
1637 {
1638 bRet = FALSE;
1639 }
1640 }
1641
1642 lock.Unlock();
1643
1644 return bRet;
1645 }
1646
1647 void TermSettingChangeNotify()
1648 {
1649 CStaticDataInitCriticalSectionLock lock;
1650 if(FAILED(lock.Lock()))
1651 {
1652 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
1653 ATLASSERT(FALSE);
1654 return;
1655 }
1656
1657 if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
1658 ::DestroyWindow((*m_pSettingChangeNotify)[0]);
1659 delete m_pSettingChangeNotify;
1660 m_pSettingChangeNotify = NULL;
1661
1662 lock.Unlock();
1663 }
1664
1665 BOOL AddSettingChangeNotify(HWND hWnd)
1666 {
1667 CStaticDataInitCriticalSectionLock lock;
1668 if(FAILED(lock.Lock()))
1669 {
1670 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
1671 ATLASSERT(FALSE);
1672 return FALSE;
1673 }
1674
1675 ATLASSERT(::IsWindow(hWnd));
1676 BOOL bRet = FALSE;
1677 if(InitSettingChangeNotify() != FALSE)
1678 bRet = m_pSettingChangeNotify->Add(hWnd);
1679
1680 lock.Unlock();
1681
1682 return bRet;
1683 }
1684
1685 BOOL RemoveSettingChangeNotify(HWND hWnd)
1686 {
1687 CStaticDataInitCriticalSectionLock lock;
1688 if(FAILED(lock.Lock()))
1689 {
1690 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
1691 ATLASSERT(FALSE);
1692 return FALSE;
1693 }
1694
1695 BOOL bRet = FALSE;
1696 if(m_pSettingChangeNotify != NULL)
1697 bRet = m_pSettingChangeNotify->Remove(hWnd);
1698
1699 lock.Unlock();
1700
1701 return bRet;
1702 }
1703
1704 // Implementation - setting change notify dialog template and dialog procedure
1705 struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
1706 {
1707 _ATL_EMPTY_DLGTEMPLATE()
1708 {
1709 memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
1710 style = WS_POPUP;
1711 }
1712 WORD wMenu, wClass, wTitle;
1713 };
1714
1715 #ifdef _WIN64
1716 static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1717 #else
1718 static BOOL CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1719 #endif
1720 {
1721 if(uMsg == WM_SETTINGCHANGE)
1722 {
1723 // need conditional code because types don't match in winuser.h
1724 #ifdef _WIN64
1725 CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
1726 #else
1727 CAppModule* pModule = (CAppModule*)LongToPtr(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
1728 #endif
1729 ATLASSERT(pModule != NULL);
1730 ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
1731 const UINT uTimeout = 1500; // ms
1732 for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
1733 {
1734 #if !defined(_WIN32_WCE)
1735 ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
1736 #elif(_WIN32_WCE >= 400) // CE specific
1737 ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_NORMAL, uTimeout, NULL);
1738 #else // _WIN32_WCE < 400 specific
1739 uTimeout;
1740 ::SendMessage((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam);
1741 #endif
1742 }
1743 return TRUE;
1744 }
1745 return FALSE;
1746 }
1747 };
1748
1749
1750 ///////////////////////////////////////////////////////////////////////////////
1751 // CServerAppModule - module class for a COM server application
1752
1753 class CServerAppModule : public CAppModule
1754 {
1755 public:
1756 HANDLE m_hEventShutdown;
1757 bool m_bActivity;
1758 DWORD m_dwTimeOut;
1759 DWORD m_dwPause;
1760
1761 // Override of CAppModule::Init
1762 HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
1763 {
1764 m_dwTimeOut = 5000;
1765 m_dwPause = 1000;
1766 return CAppModule::Init(pObjMap, hInstance, pLibID);
1767 }
1768
1769 void Term()
1770 {
1771 if(m_hEventShutdown != NULL && ::CloseHandle(m_hEventShutdown))
1772 m_hEventShutdown = NULL;
1773 CAppModule::Term();
1774 }
1775
1776 // COM Server methods
1777 #if (_MSC_VER >= 1300)
1778 LONG Unlock() throw()
1779 #else
1780 LONG Unlock()
1781 #endif
1782 {
1783 LONG lRet = CComModule::Unlock();
1784 if(lRet == 0)
1785 {
1786 m_bActivity = true;
1787 ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
1788 }
1789 return lRet;
1790 }
1791
1792 void MonitorShutdown()
1793 {
1794 for(;;)
1795 {
1796 ::WaitForSingleObject(m_hEventShutdown, INFINITE);
1797 DWORD dwWait = 0;
1798 do
1799 {
1800 m_bActivity = false;
1801 dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
1802 }
1803 while(dwWait == WAIT_OBJECT_0);
1804 // timed out
1805 if(!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail
1806 {
1807 #if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) && defined(_ATL_FREE_THREADED) && !defined(_WIN32_WCE)
1808 ::CoSuspendClassObjects();
1809 if(!m_bActivity && m_nLockCnt == 0)
1810 #endif
1811 break;
1812 }
1813 }
1814 // This handle should be valid now. If it isn't,
1815 // check if _Module.Term was called first (it shouldn't)
1816 if(::CloseHandle(m_hEventShutdown))
1817 m_hEventShutdown = NULL;
1818 ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
1819 }
1820
1821 bool StartMonitor()
1822 {
1823 m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
1824 if(m_hEventShutdown == NULL)
1825 return false;
1826 DWORD dwThreadID = 0;
1827 #if !defined(_ATL_MIN_CRT) && defined(_MT) && !defined(_WIN32_WCE)
1828 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
1829 #else
1830 HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
1831 #endif
1832 bool bRet = (hThread != NULL);
1833 if(bRet)
1834 ::CloseHandle(hThread);
1835 return bRet;
1836 }
1837
1838 static DWORD WINAPI MonitorProc(void* pv)
1839 {
1840 CServerAppModule* p = (CServerAppModule*)pv;
1841 p->MonitorShutdown();
1842 return 0;
1843 }
1844
1845 #if (_ATL_VER < 0x0700)
1846 // search for an occurence of string p2 in string p1
1847 static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
1848 {
1849 while(p1 != NULL && *p1 != NULL)
1850 {
1851 LPCTSTR p = p2;
1852 while(p != NULL && *p != NULL)
1853 {
1854 if(*p1 == *p)
1855 return ::CharNext(p1);
1856 p = ::CharNext(p);
1857 }
1858 p1 = ::CharNext(p1);
1859 }
1860 return NULL;
1861 }
1862 #endif // (_ATL_VER < 0x0700)
1863 };
1864
1865
1866 ///////////////////////////////////////////////////////////////////////////////
1867 // CRegKeyEx - adds type-specific methods to ATL3 CRegKey
1868
1869 #if (_ATL_VER < 0x0700)
1870
1871 class CRegKeyEx : public ATL::CRegKey
1872 {
1873 public:
1874 // Constructors and operators
1875 CRegKeyEx(HKEY hKey = NULL)
1876 {
1877 m_hKey = hKey;
1878 }
1879
1880 CRegKeyEx(CRegKeyEx& key)
1881 {
1882 Attach(key.Detach());
1883 }
1884
1885 CRegKeyEx& operator =(CRegKeyEx& key)
1886 {
1887 Close();
1888 Attach(key.Detach());
1889 return *this;
1890 }
1891
1892 // Methods
1893 LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes)
1894 {
1895 ATLASSERT(m_hKey != NULL);
1896 return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast<const BYTE*>(pValue), nBytes);
1897 }
1898
1899 LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue)
1900 {
1901 ATLASSERT(m_hKey != NULL);
1902
1903 OLECHAR szGUID[64] = { 0 };
1904 ::StringFromGUID2(guidValue, szGUID, 64);
1905
1906 USES_CONVERSION;
1907 LPCTSTR lpstr = OLE2CT(szGUID);
1908 #ifndef _UNICODE
1909 if(lpstr == NULL)
1910 return E_OUTOFMEMORY;
1911 #endif
1912 return SetStringValue(pszValueName, lpstr);
1913 }
1914
1915 LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes)
1916 {
1917 ATLASSERT(m_hKey != NULL);
1918 return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_BINARY, reinterpret_cast<const BYTE*>(pValue), nBytes);
1919 }
1920
1921 LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue)
1922 {
1923 ATLASSERT(m_hKey != NULL);
1924 return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast<const BYTE*>(&dwValue), sizeof(DWORD));
1925 }
1926
1927 #ifndef _WIN32_WCE
1928 LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue)
1929 {
1930 ATLASSERT(m_hKey != NULL);
1931 return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_QWORD, reinterpret_cast<const BYTE*>(&qwValue), sizeof(ULONGLONG));
1932 }
1933 #endif
1934
1935 LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ)
1936 {
1937 ATLASSERT(m_hKey != NULL);
1938 if(pszValue == NULL)
1939 {
1940 ATLASSERT(FALSE);
1941 return ERROR_INVALID_DATA;
1942 }
1943 ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ));
1944
1945 return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast<const BYTE*>(pszValue), (lstrlen(pszValue) + 1) * sizeof(TCHAR));
1946 }
1947
1948 LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue)
1949 {
1950 ATLASSERT(m_hKey != NULL);
1951 if(pszValue == NULL)
1952 {
1953 ATLASSERT(FALSE);
1954 return ERROR_INVALID_DATA;
1955 }
1956
1957 ULONG nBytes = 0;
1958 ULONG nLength = 0;
1959 LPCTSTR pszTemp = pszValue;
1960 do
1961 {
1962 nLength = lstrlen(pszTemp) + 1;
1963 pszTemp += nLength;
1964 nBytes += nLength * sizeof(TCHAR);
1965 } while (nLength != 1);
1966
1967 return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast<const BYTE*>(pszValue), nBytes);
1968 }
1969
1970 LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes)
1971 {
1972 ATLASSERT(m_hKey != NULL);
1973 return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast<LPBYTE>(pData), pnBytes);
1974 }
1975
1976 LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue)
1977 {
1978 ATLASSERT(m_hKey != NULL);
1979
1980 guidValue = GUID_NULL;
1981
1982 TCHAR szGUID[64] = { 0 };
1983 ULONG nCount = 64;
1984 LONG lRes = QueryStringValue(pszValueName, szGUID, &nCount);
1985
1986 if (lRes != ERROR_SUCCESS)
1987 return lRes;
1988
1989 if(szGUID[0] != _T('{'))
1990 return ERROR_INVALID_DATA;
1991
1992 USES_CONVERSION;
1993 LPOLESTR lpstr = T2OLE(szGUID);
1994 #ifndef _UNICODE
1995 if(lpstr == NULL)
1996 return E_OUTOFMEMORY;
1997 #endif
1998
1999 HRESULT hr = ::CLSIDFromString(lpstr, &guidValue);
2000 if (FAILED(hr))
2001 return ERROR_INVALID_DATA;
2002
2003 return ERROR_SUCCESS;
2004 }
2005
2006 LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes)
2007 {
2008 ATLASSERT(pnBytes != NULL);
2009 ATLASSERT(m_hKey != NULL);
2010
2011 DWORD dwType = 0;
2012 LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pValue), pnBytes);
2013 if (lRes != ERROR_SUCCESS)
2014 return lRes;
2015 if (dwType != REG_BINARY)
2016 return ERROR_INVALID_DATA;
2017
2018 return ERROR_SUCCESS;
2019 }
2020
2021 LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue)
2022 {
2023 ATLASSERT(m_hKey != NULL);
2024
2025 ULONG nBytes = sizeof(DWORD);
2026 DWORD dwType = 0;
2027 LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(&dwValue), &nBytes);
2028 if (lRes != ERROR_SUCCESS)
2029 return lRes;
2030 if (dwType != REG_DWORD)
2031 return ERROR_INVALID_DATA;
2032
2033 return ERROR_SUCCESS;
2034 }
2035
2036 #ifndef _WIN32_WCE
2037 LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue)
2038 {
2039 ATLASSERT(m_hKey != NULL);
2040
2041 ULONG nBytes = sizeof(ULONGLONG);
2042 DWORD dwType = 0;
2043 LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(&qwValue), &nBytes);
2044 if (lRes != ERROR_SUCCESS)
2045 return lRes;
2046 if (dwType != REG_QWORD)
2047 return ERROR_INVALID_DATA;
2048
2049 return ERROR_SUCCESS;
2050 }
2051 #endif
2052
2053 LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
2054 {
2055 ATLASSERT(m_hKey != NULL);
2056 ATLASSERT(pnChars != NULL);
2057
2058 ULONG nBytes = (*pnChars) * sizeof(TCHAR);
2059 DWORD dwType = 0;
2060 *pnChars = 0;
2061 LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pszValue), &nBytes);
2062
2063 if (lRes != ERROR_SUCCESS)
2064 {
2065 return lRes;
2066 }
2067
2068 if(dwType != REG_SZ && dwType != REG_EXPAND_SZ)
2069 {
2070 return ERROR_INVALID_DATA;
2071 }
2072
2073 if (pszValue != NULL)
2074 {
2075 if(nBytes != 0)
2076 {
2077 if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0))
2078 return ERROR_INVALID_DATA;
2079 }
2080 else
2081 {
2082 pszValue[0] = _T('\0');
2083 }
2084 }
2085
2086 *pnChars = nBytes / sizeof(TCHAR);
2087
2088 return ERROR_SUCCESS;
2089 }
2090
2091 LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars)
2092 {
2093 ATLASSERT(m_hKey != NULL);
2094 ATLASSERT(pnChars != NULL);
2095
2096 if (pszValue != NULL && *pnChars < 2)
2097 return ERROR_INSUFFICIENT_BUFFER;
2098
2099 ULONG nBytes = (*pnChars) * sizeof(TCHAR);
2100 DWORD dwType = 0;
2101 *pnChars = 0;
2102 LONG lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast<LPBYTE>(pszValue), &nBytes);
2103 if (lRes != ERROR_SUCCESS)
2104 return lRes;
2105 if (dwType != REG_MULTI_SZ)
2106 return ERROR_INVALID_DATA;
2107 if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || nBytes / sizeof(TCHAR) < 1 || pszValue[nBytes / sizeof(TCHAR) - 1] != 0 || ((nBytes / sizeof(TCHAR)) > 1 && pszValue[nBytes / sizeof(TCHAR) - 2] != 0)))
2108 return ERROR_INVALID_DATA;
2109
2110 *pnChars = nBytes / sizeof(TCHAR);
2111
2112 return ERROR_SUCCESS;
2113 }
2114 };
2115
2116 #else // !(_ATL_VER < 0x0700)
2117
2118 typedef ATL::CRegKey CRegKeyEx;
2119
2120 #endif // !(_ATL_VER < 0x0700)
2121
2122
2123 ///////////////////////////////////////////////////////////////////////////////
2124 // CString forward reference (enables CString use in atluser.h and atlgdi.h)
2125
2126 #if defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
2127 #define _WTL_USE_CSTRING
2128 #endif // defined(_WTL_FORWARD_DECLARE_CSTRING) && !defined(_WTL_USE_CSTRING)
2129
2130 #ifdef _WTL_USE_CSTRING
2131 class CString; // forward declaration (include atlmisc.h for the whole class)
2132 #endif // _WTL_USE_CSTRING
2133
2134 // CString namespace
2135 #ifndef _CSTRING_NS
2136 #ifdef __ATLSTR_H__
2137 #define _CSTRING_NS ATL
2138 #else
2139 #define _CSTRING_NS WTL
2140 #endif
2141 #endif // _CSTRING_NS
2142
2143 // Type classes namespace
2144 #ifndef _WTYPES_NS
2145 #ifdef __ATLTYPES_H__
2146 #define _WTYPES_NS
2147 #else
2148 #define _WTYPES_NS WTL
2149 #endif
2150 #endif // _WTYPES_NS
2151
2152 }; // namespace WTL
2153
2154
2155 ///////////////////////////////////////////////////////////////////////////////
2156 // General DLL version helpers
2157 // (ATL3: excluded from atlbase.h if _ATL_DLL is defined; ATL11: removed)
2158
2159 #if (((_ATL_VER < 0x0700) && defined(_ATL_DLL)) || (_ATL_VER >= 0x0B00)) && !defined(_WIN32_WCE)
2160
2161 namespace ATL
2162 {
2163
2164 inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
2165 {
2166 ATLASSERT(pDllVersionInfo != NULL);
2167 if(pDllVersionInfo == NULL)
2168 return E_INVALIDARG;
2169
2170 // We must get this function explicitly because some DLLs don't implement it.
2171 DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
2172 if(pfnDllGetVersion == NULL)
2173 return E_NOTIMPL;
2174
2175 return (*pfnDllGetVersion)(pDllVersionInfo);
2176 }
2177
2178 inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
2179 {
2180 HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
2181 if(hInstDLL == NULL)
2182 return E_FAIL;
2183 HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
2184 ::FreeLibrary(hInstDLL);
2185 return hRet;
2186 }
2187
2188 // Common Control Versions:
2189 // Win95/WinNT 4.0 maj=4 min=00
2190 // IE 3.x maj=4 min=70
2191 // IE 4.0 maj=4 min=71
2192 inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
2193 {
2194 ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
2195 if(pdwMajor == NULL || pdwMinor == NULL)
2196 return E_INVALIDARG;
2197
2198 DLLVERSIONINFO dvi;
2199 ::ZeroMemory(&dvi, sizeof(dvi));
2200 dvi.cbSize = sizeof(dvi);
2201 HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);
2202
2203 if(SUCCEEDED(hRet))
2204 {
2205 *pdwMajor = dvi.dwMajorVersion;
2206 *pdwMinor = dvi.dwMinorVersion;
2207 }
2208 else if(hRet == E_NOTIMPL)
2209 {
2210 // If DllGetVersion is not there, then the DLL is a version
2211 // previous to the one shipped with IE 3.x
2212 *pdwMajor = 4;
2213 *pdwMinor = 0;
2214 hRet = S_OK;
2215 }
2216
2217 return hRet;
2218 }
2219
2220 // Shell Versions:
2221 // Win95/WinNT 4.0 maj=4 min=00
2222 // IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00
2223 // IE 4.0 with Web Integrated Desktop maj=4 min=71
2224 // IE 4.01 with Web Integrated Desktop maj=4 min=72
2225 inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
2226 {
2227 ATLASSERT(pdwMajor != NULL && pdwMinor != NULL);
2228 if(pdwMajor == NULL || pdwMinor == NULL)
2229 return E_INVALIDARG;
2230
2231 DLLVERSIONINFO dvi;
2232 ::ZeroMemory(&dvi, sizeof(dvi));
2233 dvi.cbSize = sizeof(dvi);
2234 HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);
2235
2236 if(SUCCEEDED(hRet))
2237 {
2238 *pdwMajor = dvi.dwMajorVersion;
2239 *pdwMinor = dvi.dwMinorVersion;
2240 }
2241 else if(hRet == E_NOTIMPL)
2242 {
2243 // If DllGetVersion is not there, then the DLL is a version
2244 // previous to the one shipped with IE 4.x
2245 *pdwMajor = 4;
2246 *pdwMinor = 0;
2247 hRet = S_OK;
2248 }
2249
2250 return hRet;
2251 }
2252
2253 }; // namespace ATL
2254
2255 #endif // (_ATL_VER < 0x0700) && defined(_ATL_DLL) && !defined(_WIN32_WCE)
2256
2257
2258 // These are always included
2259 #include "atlwinx.h"
2260 #include "atluser.h"
2261 #include "atlgdi.h"
2262
2263 #ifndef _WTL_NO_AUTOMATIC_NAMESPACE
2264 using namespace WTL;
2265 #endif // !_WTL_NO_AUTOMATIC_NAMESPACE
2266
2267 #endif // __ATLAPP_H__
+0
-2395
src/third_party/wtl/Include/atlcrack.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLCRACK_H__
9 #define __ATLCRACK_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlcrack.h requires atlapp.h to be included first
15 #endif
16
17
18 ///////////////////////////////////////////////////////////////////////////////
19 // Message map macro for cracked handlers
20
21 // Note about message maps with cracked handlers:
22 // For ATL 3.0, a message map using cracked handlers MUST use BEGIN_MSG_MAP_EX.
23 // For ATL 7.0 or higher, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes,
24 // but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl.
25
26 #define BEGIN_MSG_MAP_EX(theClass) \
27 public: \
28 BOOL m_bMsgHandled; \
29 /* "handled" management for cracked handlers */ \
30 BOOL IsMsgHandled() const \
31 { \
32 return m_bMsgHandled; \
33 } \
34 void SetMsgHandled(BOOL bHandled) \
35 { \
36 m_bMsgHandled = bHandled; \
37 } \
38 BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
39 { \
40 BOOL bOldMsgHandled = m_bMsgHandled; \
41 BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \
42 m_bMsgHandled = bOldMsgHandled; \
43 return bRet; \
44 } \
45 BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \
46 { \
47 BOOL bHandled = TRUE; \
48 (hWnd); \
49 (uMsg); \
50 (wParam); \
51 (lParam); \
52 (lResult); \
53 (bHandled); \
54 switch(dwMsgMapID) \
55 { \
56 case 0:
57
58
59 ///////////////////////////////////////////////////////////////////////////////
60 // Standard Windows message macros
61
62 // int OnCreate(LPCREATESTRUCT lpCreateStruct)
63 #define MSG_WM_CREATE(func) \
64 if (uMsg == WM_CREATE) \
65 { \
66 SetMsgHandled(TRUE); \
67 lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
68 if(IsMsgHandled()) \
69 return TRUE; \
70 }
71
72 // BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
73 #define MSG_WM_INITDIALOG(func) \
74 if (uMsg == WM_INITDIALOG) \
75 { \
76 SetMsgHandled(TRUE); \
77 lResult = (LRESULT)func((HWND)wParam, lParam); \
78 if(IsMsgHandled()) \
79 return TRUE; \
80 }
81
82 // BOOL OnCopyData(CWindow wnd, PCOPYDATASTRUCT pCopyDataStruct)
83 #define MSG_WM_COPYDATA(func) \
84 if (uMsg == WM_COPYDATA) \
85 { \
86 SetMsgHandled(TRUE); \
87 lResult = (LRESULT)func((HWND)wParam, (PCOPYDATASTRUCT)lParam); \
88 if(IsMsgHandled()) \
89 return TRUE; \
90 }
91
92 // void OnDestroy()
93 #define MSG_WM_DESTROY(func) \
94 if (uMsg == WM_DESTROY) \
95 { \
96 SetMsgHandled(TRUE); \
97 func(); \
98 lResult = 0; \
99 if(IsMsgHandled()) \
100 return TRUE; \
101 }
102
103 // void OnMove(CPoint ptPos)
104 #define MSG_WM_MOVE(func) \
105 if (uMsg == WM_MOVE) \
106 { \
107 SetMsgHandled(TRUE); \
108 func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
109 lResult = 0; \
110 if(IsMsgHandled()) \
111 return TRUE; \
112 }
113
114 // void OnSize(UINT nType, CSize size)
115 #define MSG_WM_SIZE(func) \
116 if (uMsg == WM_SIZE) \
117 { \
118 SetMsgHandled(TRUE); \
119 func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
120 lResult = 0; \
121 if(IsMsgHandled()) \
122 return TRUE; \
123 }
124
125 // void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther)
126 #define MSG_WM_ACTIVATE(func) \
127 if (uMsg == WM_ACTIVATE) \
128 { \
129 SetMsgHandled(TRUE); \
130 func((UINT)LOWORD(wParam), (BOOL)HIWORD(wParam), (HWND)lParam); \
131 lResult = 0; \
132 if(IsMsgHandled()) \
133 return TRUE; \
134 }
135
136 // void OnSetFocus(CWindow wndOld)
137 #define MSG_WM_SETFOCUS(func) \
138 if (uMsg == WM_SETFOCUS) \
139 { \
140 SetMsgHandled(TRUE); \
141 func((HWND)wParam); \
142 lResult = 0; \
143 if(IsMsgHandled()) \
144 return TRUE; \
145 }
146
147 // void OnKillFocus(CWindow wndFocus)
148 #define MSG_WM_KILLFOCUS(func) \
149 if (uMsg == WM_KILLFOCUS) \
150 { \
151 SetMsgHandled(TRUE); \
152 func((HWND)wParam); \
153 lResult = 0; \
154 if(IsMsgHandled()) \
155 return TRUE; \
156 }
157
158 // void OnEnable(BOOL bEnable)
159 #define MSG_WM_ENABLE(func) \
160 if (uMsg == WM_ENABLE) \
161 { \
162 SetMsgHandled(TRUE); \
163 func((BOOL)wParam); \
164 lResult = 0; \
165 if(IsMsgHandled()) \
166 return TRUE; \
167 }
168
169 // void OnPaint(CDCHandle dc)
170 #define MSG_WM_PAINT(func) \
171 if (uMsg == WM_PAINT) \
172 { \
173 SetMsgHandled(TRUE); \
174 func((HDC)wParam); \
175 lResult = 0; \
176 if(IsMsgHandled()) \
177 return TRUE; \
178 }
179
180 // void OnClose()
181 #define MSG_WM_CLOSE(func) \
182 if (uMsg == WM_CLOSE) \
183 { \
184 SetMsgHandled(TRUE); \
185 func(); \
186 lResult = 0; \
187 if(IsMsgHandled()) \
188 return TRUE; \
189 }
190
191 // BOOL OnQueryEndSession(UINT nSource, UINT uLogOff)
192 #define MSG_WM_QUERYENDSESSION(func) \
193 if (uMsg == WM_QUERYENDSESSION) \
194 { \
195 SetMsgHandled(TRUE); \
196 lResult = (LRESULT)func((UINT)wParam, (UINT)lParam); \
197 if(IsMsgHandled()) \
198 return TRUE; \
199 }
200
201 // BOOL OnQueryOpen()
202 #define MSG_WM_QUERYOPEN(func) \
203 if (uMsg == WM_QUERYOPEN) \
204 { \
205 SetMsgHandled(TRUE); \
206 lResult = (LRESULT)func(); \
207 if(IsMsgHandled()) \
208 return TRUE; \
209 }
210
211 // BOOL OnEraseBkgnd(CDCHandle dc)
212 #define MSG_WM_ERASEBKGND(func) \
213 if (uMsg == WM_ERASEBKGND) \
214 { \
215 SetMsgHandled(TRUE); \
216 lResult = (LRESULT)func((HDC)wParam); \
217 if(IsMsgHandled()) \
218 return TRUE; \
219 }
220
221 // void OnSysColorChange()
222 #define MSG_WM_SYSCOLORCHANGE(func) \
223 if (uMsg == WM_SYSCOLORCHANGE) \
224 { \
225 SetMsgHandled(TRUE); \
226 func(); \
227 lResult = 0; \
228 if(IsMsgHandled()) \
229 return TRUE; \
230 }
231
232 // void OnEndSession(BOOL bEnding, UINT uLogOff)
233 #define MSG_WM_ENDSESSION(func) \
234 if (uMsg == WM_ENDSESSION) \
235 { \
236 SetMsgHandled(TRUE); \
237 func((BOOL)wParam, (UINT)lParam); \
238 lResult = 0; \
239 if(IsMsgHandled()) \
240 return TRUE; \
241 }
242
243 // void OnShowWindow(BOOL bShow, UINT nStatus)
244 #define MSG_WM_SHOWWINDOW(func) \
245 if (uMsg == WM_SHOWWINDOW) \
246 { \
247 SetMsgHandled(TRUE); \
248 func((BOOL)wParam, (int)lParam); \
249 lResult = 0; \
250 if(IsMsgHandled()) \
251 return TRUE; \
252 }
253
254 // HBRUSH OnCtlColorEdit(CDCHandle dc, CEdit edit)
255 #define MSG_WM_CTLCOLOREDIT(func) \
256 if (uMsg == WM_CTLCOLOREDIT) \
257 { \
258 SetMsgHandled(TRUE); \
259 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
260 if(IsMsgHandled()) \
261 return TRUE; \
262 }
263
264 // HBRUSH OnCtlColorListBox(CDCHandle dc, CListBox listBox)
265 #define MSG_WM_CTLCOLORLISTBOX(func) \
266 if (uMsg == WM_CTLCOLORLISTBOX) \
267 { \
268 SetMsgHandled(TRUE); \
269 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
270 if(IsMsgHandled()) \
271 return TRUE; \
272 }
273
274 // HBRUSH OnCtlColorBtn(CDCHandle dc, CButton button)
275 #define MSG_WM_CTLCOLORBTN(func) \
276 if (uMsg == WM_CTLCOLORBTN) \
277 { \
278 SetMsgHandled(TRUE); \
279 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
280 if(IsMsgHandled()) \
281 return TRUE; \
282 }
283
284 // HBRUSH OnCtlColorDlg(CDCHandle dc, CWindow wnd)
285 #define MSG_WM_CTLCOLORDLG(func) \
286 if (uMsg == WM_CTLCOLORDLG) \
287 { \
288 SetMsgHandled(TRUE); \
289 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
290 if(IsMsgHandled()) \
291 return TRUE; \
292 }
293
294 // HBRUSH OnCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
295 #define MSG_WM_CTLCOLORSCROLLBAR(func) \
296 if (uMsg == WM_CTLCOLORSCROLLBAR) \
297 { \
298 SetMsgHandled(TRUE); \
299 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
300 if(IsMsgHandled()) \
301 return TRUE; \
302 }
303
304 // HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic)
305 #define MSG_WM_CTLCOLORSTATIC(func) \
306 if (uMsg == WM_CTLCOLORSTATIC) \
307 { \
308 SetMsgHandled(TRUE); \
309 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
310 if(IsMsgHandled()) \
311 return TRUE; \
312 }
313
314 // void OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
315 #define MSG_WM_SETTINGCHANGE(func) \
316 if (uMsg == WM_SETTINGCHANGE) \
317 { \
318 SetMsgHandled(TRUE); \
319 func((UINT)wParam, (LPCTSTR)lParam); \
320 lResult = 0; \
321 if(IsMsgHandled()) \
322 return TRUE; \
323 }
324
325 // void OnDevModeChange(LPCTSTR lpDeviceName)
326 #define MSG_WM_DEVMODECHANGE(func) \
327 if (uMsg == WM_DEVMODECHANGE) \
328 { \
329 SetMsgHandled(TRUE); \
330 func((LPCTSTR)lParam); \
331 lResult = 0; \
332 if(IsMsgHandled()) \
333 return TRUE; \
334 }
335
336 // void OnActivateApp(BOOL bActive, DWORD dwThreadID)
337 #define MSG_WM_ACTIVATEAPP(func) \
338 if (uMsg == WM_ACTIVATEAPP) \
339 { \
340 SetMsgHandled(TRUE); \
341 func((BOOL)wParam, (DWORD)lParam); \
342 lResult = 0; \
343 if(IsMsgHandled()) \
344 return TRUE; \
345 }
346
347 // void OnFontChange()
348 #define MSG_WM_FONTCHANGE(func) \
349 if (uMsg == WM_FONTCHANGE) \
350 { \
351 SetMsgHandled(TRUE); \
352 func(); \
353 lResult = 0; \
354 if(IsMsgHandled()) \
355 return TRUE; \
356 }
357
358 // void OnTimeChange()
359 #define MSG_WM_TIMECHANGE(func) \
360 if (uMsg == WM_TIMECHANGE) \
361 { \
362 SetMsgHandled(TRUE); \
363 func(); \
364 lResult = 0; \
365 if(IsMsgHandled()) \
366 return TRUE; \
367 }
368
369 // void OnCancelMode()
370 #define MSG_WM_CANCELMODE(func) \
371 if (uMsg == WM_CANCELMODE) \
372 { \
373 SetMsgHandled(TRUE); \
374 func(); \
375 lResult = 0; \
376 if(IsMsgHandled()) \
377 return TRUE; \
378 }
379
380 // BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)
381 #define MSG_WM_SETCURSOR(func) \
382 if (uMsg == WM_SETCURSOR) \
383 { \
384 SetMsgHandled(TRUE); \
385 lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
386 if(IsMsgHandled()) \
387 return TRUE; \
388 }
389
390 // int OnMouseActivate(CWindow wndTopLevel, UINT nHitTest, UINT message)
391 #define MSG_WM_MOUSEACTIVATE(func) \
392 if (uMsg == WM_MOUSEACTIVATE) \
393 { \
394 SetMsgHandled(TRUE); \
395 lResult = (LRESULT)func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
396 if(IsMsgHandled()) \
397 return TRUE; \
398 }
399
400 // void OnChildActivate()
401 #define MSG_WM_CHILDACTIVATE(func) \
402 if (uMsg == WM_CHILDACTIVATE) \
403 { \
404 SetMsgHandled(TRUE); \
405 func(); \
406 lResult = 0; \
407 if(IsMsgHandled()) \
408 return TRUE; \
409 }
410
411 // void OnGetMinMaxInfo(LPMINMAXINFO lpMMI)
412 #define MSG_WM_GETMINMAXINFO(func) \
413 if (uMsg == WM_GETMINMAXINFO) \
414 { \
415 SetMsgHandled(TRUE); \
416 func((LPMINMAXINFO)lParam); \
417 lResult = 0; \
418 if(IsMsgHandled()) \
419 return TRUE; \
420 }
421
422 // void OnIconEraseBkgnd(CDCHandle dc)
423 #define MSG_WM_ICONERASEBKGND(func) \
424 if (uMsg == WM_ICONERASEBKGND) \
425 { \
426 SetMsgHandled(TRUE); \
427 func((HDC)wParam); \
428 lResult = 0; \
429 if(IsMsgHandled()) \
430 return TRUE; \
431 }
432
433 // void OnSpoolerStatus(UINT nStatus, UINT nJobs)
434 #define MSG_WM_SPOOLERSTATUS(func) \
435 if (uMsg == WM_SPOOLERSTATUS) \
436 { \
437 SetMsgHandled(TRUE); \
438 func((UINT)wParam, (UINT)LOWORD(lParam)); \
439 lResult = 0; \
440 if(IsMsgHandled()) \
441 return TRUE; \
442 }
443
444 // void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
445 #define MSG_WM_DRAWITEM(func) \
446 if (uMsg == WM_DRAWITEM) \
447 { \
448 SetMsgHandled(TRUE); \
449 func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
450 lResult = TRUE; \
451 if(IsMsgHandled()) \
452 return TRUE; \
453 }
454
455 // void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
456 #define MSG_WM_MEASUREITEM(func) \
457 if (uMsg == WM_MEASUREITEM) \
458 { \
459 SetMsgHandled(TRUE); \
460 func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
461 lResult = TRUE; \
462 if(IsMsgHandled()) \
463 return TRUE; \
464 }
465
466 // void OnDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
467 #define MSG_WM_DELETEITEM(func) \
468 if (uMsg == WM_DELETEITEM) \
469 { \
470 SetMsgHandled(TRUE); \
471 func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
472 lResult = TRUE; \
473 if(IsMsgHandled()) \
474 return TRUE; \
475 }
476
477 //int OnCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
478 #define MSG_WM_CHARTOITEM(func) \
479 if (uMsg == WM_CHARTOITEM) \
480 { \
481 SetMsgHandled(TRUE); \
482 lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
483 if(IsMsgHandled()) \
484 return TRUE; \
485 }
486
487 // int OnVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
488 #define MSG_WM_VKEYTOITEM(func) \
489 if (uMsg == WM_VKEYTOITEM) \
490 { \
491 SetMsgHandled(TRUE); \
492 lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
493 if(IsMsgHandled()) \
494 return TRUE; \
495 }
496
497 // HCURSOR OnQueryDragIcon()
498 #define MSG_WM_QUERYDRAGICON(func) \
499 if (uMsg == WM_QUERYDRAGICON) \
500 { \
501 SetMsgHandled(TRUE); \
502 lResult = (LRESULT)func(); \
503 if(IsMsgHandled()) \
504 return TRUE; \
505 }
506
507 // int OnCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
508 #define MSG_WM_COMPAREITEM(func) \
509 if (uMsg == WM_COMPAREITEM) \
510 { \
511 SetMsgHandled(TRUE); \
512 lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
513 if(IsMsgHandled()) \
514 return TRUE; \
515 }
516
517 // void OnCompacting(UINT nCpuTime)
518 #define MSG_WM_COMPACTING(func) \
519 if (uMsg == WM_COMPACTING) \
520 { \
521 SetMsgHandled(TRUE); \
522 func((UINT)wParam); \
523 lResult = 0; \
524 if(IsMsgHandled()) \
525 return TRUE; \
526 }
527
528 // BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct)
529 #define MSG_WM_NCCREATE(func) \
530 if (uMsg == WM_NCCREATE) \
531 { \
532 SetMsgHandled(TRUE); \
533 lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
534 if(IsMsgHandled()) \
535 return TRUE; \
536 }
537
538 // void OnNcDestroy()
539 #define MSG_WM_NCDESTROY(func) \
540 if (uMsg == WM_NCDESTROY) \
541 { \
542 SetMsgHandled(TRUE); \
543 func(); \
544 lResult = 0; \
545 if(IsMsgHandled()) \
546 return TRUE; \
547 }
548
549 // LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
550 #define MSG_WM_NCCALCSIZE(func) \
551 if (uMsg == WM_NCCALCSIZE) \
552 { \
553 SetMsgHandled(TRUE); \
554 lResult = func((BOOL)wParam, lParam); \
555 if(IsMsgHandled()) \
556 return TRUE; \
557 }
558
559 // UINT OnNcHitTest(CPoint point)
560 #define MSG_WM_NCHITTEST(func) \
561 if (uMsg == WM_NCHITTEST) \
562 { \
563 SetMsgHandled(TRUE); \
564 lResult = (LRESULT)func(_WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
565 if(IsMsgHandled()) \
566 return TRUE; \
567 }
568
569 // void OnNcPaint(CRgnHandle rgn)
570 #define MSG_WM_NCPAINT(func) \
571 if (uMsg == WM_NCPAINT) \
572 { \
573 SetMsgHandled(TRUE); \
574 func((HRGN)wParam); \
575 lResult = 0; \
576 if(IsMsgHandled()) \
577 return TRUE; \
578 }
579
580 // BOOL OnNcActivate(BOOL bActive)
581 #define MSG_WM_NCACTIVATE(func) \
582 if (uMsg == WM_NCACTIVATE) \
583 { \
584 SetMsgHandled(TRUE); \
585 lResult = (LRESULT)func((BOOL)wParam); \
586 if(IsMsgHandled()) \
587 return TRUE; \
588 }
589
590 // UINT OnGetDlgCode(LPMSG lpMsg)
591 #define MSG_WM_GETDLGCODE(func) \
592 if (uMsg == WM_GETDLGCODE) \
593 { \
594 SetMsgHandled(TRUE); \
595 lResult = (LRESULT)func((LPMSG)lParam); \
596 if(IsMsgHandled()) \
597 return TRUE; \
598 }
599
600 // void OnNcMouseMove(UINT nHitTest, CPoint point)
601 #define MSG_WM_NCMOUSEMOVE(func) \
602 if (uMsg == WM_NCMOUSEMOVE) \
603 { \
604 SetMsgHandled(TRUE); \
605 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
606 lResult = 0; \
607 if(IsMsgHandled()) \
608 return TRUE; \
609 }
610
611 // void OnNcLButtonDown(UINT nHitTest, CPoint point)
612 #define MSG_WM_NCLBUTTONDOWN(func) \
613 if (uMsg == WM_NCLBUTTONDOWN) \
614 { \
615 SetMsgHandled(TRUE); \
616 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
617 lResult = 0; \
618 if(IsMsgHandled()) \
619 return TRUE; \
620 }
621
622 // void OnNcLButtonUp(UINT nHitTest, CPoint point)
623 #define MSG_WM_NCLBUTTONUP(func) \
624 if (uMsg == WM_NCLBUTTONUP) \
625 { \
626 SetMsgHandled(TRUE); \
627 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
628 lResult = 0; \
629 if(IsMsgHandled()) \
630 return TRUE; \
631 }
632
633 // void OnNcLButtonDblClk(UINT nHitTest, CPoint point)
634 #define MSG_WM_NCLBUTTONDBLCLK(func) \
635 if (uMsg == WM_NCLBUTTONDBLCLK) \
636 { \
637 SetMsgHandled(TRUE); \
638 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
639 lResult = 0; \
640 if(IsMsgHandled()) \
641 return TRUE; \
642 }
643
644 // void OnNcRButtonDown(UINT nHitTest, CPoint point)
645 #define MSG_WM_NCRBUTTONDOWN(func) \
646 if (uMsg == WM_NCRBUTTONDOWN) \
647 { \
648 SetMsgHandled(TRUE); \
649 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
650 lResult = 0; \
651 if(IsMsgHandled()) \
652 return TRUE; \
653 }
654
655 // void OnNcRButtonUp(UINT nHitTest, CPoint point)
656 #define MSG_WM_NCRBUTTONUP(func) \
657 if (uMsg == WM_NCRBUTTONUP) \
658 { \
659 SetMsgHandled(TRUE); \
660 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
661 lResult = 0; \
662 if(IsMsgHandled()) \
663 return TRUE; \
664 }
665
666 // void OnNcRButtonDblClk(UINT nHitTest, CPoint point)
667 #define MSG_WM_NCRBUTTONDBLCLK(func) \
668 if (uMsg == WM_NCRBUTTONDBLCLK) \
669 { \
670 SetMsgHandled(TRUE); \
671 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
672 lResult = 0; \
673 if(IsMsgHandled()) \
674 return TRUE; \
675 }
676
677 // void OnNcMButtonDown(UINT nHitTest, CPoint point)
678 #define MSG_WM_NCMBUTTONDOWN(func) \
679 if (uMsg == WM_NCMBUTTONDOWN) \
680 { \
681 SetMsgHandled(TRUE); \
682 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
683 lResult = 0; \
684 if(IsMsgHandled()) \
685 return TRUE; \
686 }
687
688 // void OnNcMButtonUp(UINT nHitTest, CPoint point)
689 #define MSG_WM_NCMBUTTONUP(func) \
690 if (uMsg == WM_NCMBUTTONUP) \
691 { \
692 SetMsgHandled(TRUE); \
693 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
694 lResult = 0; \
695 if(IsMsgHandled()) \
696 return TRUE; \
697 }
698
699 // void OnNcMButtonDblClk(UINT nHitTest, CPoint point)
700 #define MSG_WM_NCMBUTTONDBLCLK(func) \
701 if (uMsg == WM_NCMBUTTONDBLCLK) \
702 { \
703 SetMsgHandled(TRUE); \
704 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
705 lResult = 0; \
706 if(IsMsgHandled()) \
707 return TRUE; \
708 }
709
710 // void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
711 #define MSG_WM_KEYDOWN(func) \
712 if (uMsg == WM_KEYDOWN) \
713 { \
714 SetMsgHandled(TRUE); \
715 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
716 lResult = 0; \
717 if(IsMsgHandled()) \
718 return TRUE; \
719 }
720
721 // void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
722 #define MSG_WM_KEYUP(func) \
723 if (uMsg == WM_KEYUP) \
724 { \
725 SetMsgHandled(TRUE); \
726 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
727 lResult = 0; \
728 if(IsMsgHandled()) \
729 return TRUE; \
730 }
731
732 // void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
733 #define MSG_WM_CHAR(func) \
734 if (uMsg == WM_CHAR) \
735 { \
736 SetMsgHandled(TRUE); \
737 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
738 lResult = 0; \
739 if(IsMsgHandled()) \
740 return TRUE; \
741 }
742
743 // void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
744 #define MSG_WM_DEADCHAR(func) \
745 if (uMsg == WM_DEADCHAR) \
746 { \
747 SetMsgHandled(TRUE); \
748 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
749 lResult = 0; \
750 if(IsMsgHandled()) \
751 return TRUE; \
752 }
753
754 // void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
755 #define MSG_WM_SYSKEYDOWN(func) \
756 if (uMsg == WM_SYSKEYDOWN) \
757 { \
758 SetMsgHandled(TRUE); \
759 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
760 lResult = 0; \
761 if(IsMsgHandled()) \
762 return TRUE; \
763 }
764
765 // void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
766 #define MSG_WM_SYSKEYUP(func) \
767 if (uMsg == WM_SYSKEYUP) \
768 { \
769 SetMsgHandled(TRUE); \
770 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
771 lResult = 0; \
772 if(IsMsgHandled()) \
773 return TRUE; \
774 }
775
776 // void OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
777 #define MSG_WM_SYSCHAR(func) \
778 if (uMsg == WM_SYSCHAR) \
779 { \
780 SetMsgHandled(TRUE); \
781 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
782 lResult = 0; \
783 if(IsMsgHandled()) \
784 return TRUE; \
785 }
786
787 // void OnSysDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
788 #define MSG_WM_SYSDEADCHAR(func) \
789 if (uMsg == WM_SYSDEADCHAR) \
790 { \
791 SetMsgHandled(TRUE); \
792 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
793 lResult = 0; \
794 if(IsMsgHandled()) \
795 return TRUE; \
796 }
797
798 // void OnSysCommand(UINT nID, CPoint point)
799 #define MSG_WM_SYSCOMMAND(func) \
800 if (uMsg == WM_SYSCOMMAND) \
801 { \
802 SetMsgHandled(TRUE); \
803 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
804 lResult = 0; \
805 if(IsMsgHandled()) \
806 return TRUE; \
807 }
808
809 // void OnTCard(UINT idAction, DWORD dwActionData)
810 #define MSG_WM_TCARD(func) \
811 if (uMsg == WM_TCARD) \
812 { \
813 SetMsgHandled(TRUE); \
814 func((UINT)wParam, (DWORD)lParam); \
815 lResult = 0; \
816 if(IsMsgHandled()) \
817 return TRUE; \
818 }
819
820 // void OnTimer(UINT_PTR nIDEvent)
821 #define MSG_WM_TIMER(func) \
822 if (uMsg == WM_TIMER) \
823 { \
824 SetMsgHandled(TRUE); \
825 func((UINT_PTR)wParam); \
826 lResult = 0; \
827 if(IsMsgHandled()) \
828 return TRUE; \
829 }
830
831 // void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
832 #define MSG_WM_HSCROLL(func) \
833 if (uMsg == WM_HSCROLL) \
834 { \
835 SetMsgHandled(TRUE); \
836 func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
837 lResult = 0; \
838 if(IsMsgHandled()) \
839 return TRUE; \
840 }
841
842 // void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
843 #define MSG_WM_VSCROLL(func) \
844 if (uMsg == WM_VSCROLL) \
845 { \
846 SetMsgHandled(TRUE); \
847 func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
848 lResult = 0; \
849 if(IsMsgHandled()) \
850 return TRUE; \
851 }
852
853 // void OnInitMenu(CMenuHandle menu)
854 #define MSG_WM_INITMENU(func) \
855 if (uMsg == WM_INITMENU) \
856 { \
857 SetMsgHandled(TRUE); \
858 func((HMENU)wParam); \
859 lResult = 0; \
860 if(IsMsgHandled()) \
861 return TRUE; \
862 }
863
864 // void OnInitMenuPopup(CMenuHandle menuPopup, UINT nIndex, BOOL bSysMenu)
865 #define MSG_WM_INITMENUPOPUP(func) \
866 if (uMsg == WM_INITMENUPOPUP) \
867 { \
868 SetMsgHandled(TRUE); \
869 func((HMENU)wParam, (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)); \
870 lResult = 0; \
871 if(IsMsgHandled()) \
872 return TRUE; \
873 }
874
875 // void OnMenuSelect(UINT nItemID, UINT nFlags, CMenuHandle menu)
876 #define MSG_WM_MENUSELECT(func) \
877 if (uMsg == WM_MENUSELECT) \
878 { \
879 SetMsgHandled(TRUE); \
880 func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
881 lResult = 0; \
882 if(IsMsgHandled()) \
883 return TRUE; \
884 }
885
886 // LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenuHandle menu)
887 #define MSG_WM_MENUCHAR(func) \
888 if (uMsg == WM_MENUCHAR) \
889 { \
890 SetMsgHandled(TRUE); \
891 lResult = func((TCHAR)LOWORD(wParam), (UINT)HIWORD(wParam), (HMENU)lParam); \
892 if(IsMsgHandled()) \
893 return TRUE; \
894 }
895
896 // LRESULT OnNotify(int idCtrl, LPNMHDR pnmh)
897 #define MSG_WM_NOTIFY(func) \
898 if (uMsg == WM_NOTIFY) \
899 { \
900 SetMsgHandled(TRUE); \
901 lResult = func((int)wParam, (LPNMHDR)lParam); \
902 if(IsMsgHandled()) \
903 return TRUE; \
904 }
905
906 // void OnEnterIdle(UINT nWhy, CWindow wndWho)
907 #define MSG_WM_ENTERIDLE(func) \
908 if (uMsg == WM_ENTERIDLE) \
909 { \
910 SetMsgHandled(TRUE); \
911 func((UINT)wParam, (HWND)lParam); \
912 lResult = 0; \
913 if(IsMsgHandled()) \
914 return TRUE; \
915 }
916
917 // void OnMouseMove(UINT nFlags, CPoint point)
918 #define MSG_WM_MOUSEMOVE(func) \
919 if (uMsg == WM_MOUSEMOVE) \
920 { \
921 SetMsgHandled(TRUE); \
922 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
923 lResult = 0; \
924 if(IsMsgHandled()) \
925 return TRUE; \
926 }
927
928 // BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
929 #define MSG_WM_MOUSEWHEEL(func) \
930 if (uMsg == WM_MOUSEWHEEL) \
931 { \
932 SetMsgHandled(TRUE); \
933 lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
934 if(IsMsgHandled()) \
935 return TRUE; \
936 }
937
938 // void OnLButtonDown(UINT nFlags, CPoint point)
939 #define MSG_WM_LBUTTONDOWN(func) \
940 if (uMsg == WM_LBUTTONDOWN) \
941 { \
942 SetMsgHandled(TRUE); \
943 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
944 lResult = 0; \
945 if(IsMsgHandled()) \
946 return TRUE; \
947 }
948
949 // void OnLButtonUp(UINT nFlags, CPoint point)
950 #define MSG_WM_LBUTTONUP(func) \
951 if (uMsg == WM_LBUTTONUP) \
952 { \
953 SetMsgHandled(TRUE); \
954 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
955 lResult = 0; \
956 if(IsMsgHandled()) \
957 return TRUE; \
958 }
959
960 // void OnLButtonDblClk(UINT nFlags, CPoint point)
961 #define MSG_WM_LBUTTONDBLCLK(func) \
962 if (uMsg == WM_LBUTTONDBLCLK) \
963 { \
964 SetMsgHandled(TRUE); \
965 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
966 lResult = 0; \
967 if(IsMsgHandled()) \
968 return TRUE; \
969 }
970
971 // void OnRButtonDown(UINT nFlags, CPoint point)
972 #define MSG_WM_RBUTTONDOWN(func) \
973 if (uMsg == WM_RBUTTONDOWN) \
974 { \
975 SetMsgHandled(TRUE); \
976 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
977 lResult = 0; \
978 if(IsMsgHandled()) \
979 return TRUE; \
980 }
981
982 // void OnRButtonUp(UINT nFlags, CPoint point)
983 #define MSG_WM_RBUTTONUP(func) \
984 if (uMsg == WM_RBUTTONUP) \
985 { \
986 SetMsgHandled(TRUE); \
987 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
988 lResult = 0; \
989 if(IsMsgHandled()) \
990 return TRUE; \
991 }
992
993 // void OnRButtonDblClk(UINT nFlags, CPoint point)
994 #define MSG_WM_RBUTTONDBLCLK(func) \
995 if (uMsg == WM_RBUTTONDBLCLK) \
996 { \
997 SetMsgHandled(TRUE); \
998 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
999 lResult = 0; \
1000 if(IsMsgHandled()) \
1001 return TRUE; \
1002 }
1003
1004 // void OnMButtonDown(UINT nFlags, CPoint point)
1005 #define MSG_WM_MBUTTONDOWN(func) \
1006 if (uMsg == WM_MBUTTONDOWN) \
1007 { \
1008 SetMsgHandled(TRUE); \
1009 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1010 lResult = 0; \
1011 if(IsMsgHandled()) \
1012 return TRUE; \
1013 }
1014
1015 // void OnMButtonUp(UINT nFlags, CPoint point)
1016 #define MSG_WM_MBUTTONUP(func) \
1017 if (uMsg == WM_MBUTTONUP) \
1018 { \
1019 SetMsgHandled(TRUE); \
1020 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1021 lResult = 0; \
1022 if(IsMsgHandled()) \
1023 return TRUE; \
1024 }
1025
1026 // void OnMButtonDblClk(UINT nFlags, CPoint point)
1027 #define MSG_WM_MBUTTONDBLCLK(func) \
1028 if (uMsg == WM_MBUTTONDBLCLK) \
1029 { \
1030 SetMsgHandled(TRUE); \
1031 func((UINT)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1032 lResult = 0; \
1033 if(IsMsgHandled()) \
1034 return TRUE; \
1035 }
1036
1037 // void OnParentNotify(UINT message, UINT nChildID, LPARAM lParam)
1038 #define MSG_WM_PARENTNOTIFY(func) \
1039 if (uMsg == WM_PARENTNOTIFY) \
1040 { \
1041 SetMsgHandled(TRUE); \
1042 func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
1043 lResult = 0; \
1044 if(IsMsgHandled()) \
1045 return TRUE; \
1046 }
1047
1048 // void OnMDIActivate(CWindow wndActivate, CWindow wndDeactivate)
1049 #define MSG_WM_MDIACTIVATE(func) \
1050 if (uMsg == WM_MDIACTIVATE) \
1051 { \
1052 SetMsgHandled(TRUE); \
1053 func((HWND)wParam, (HWND)lParam); \
1054 lResult = 0; \
1055 if(IsMsgHandled()) \
1056 return TRUE; \
1057 }
1058
1059 // void OnRenderFormat(UINT nFormat)
1060 #define MSG_WM_RENDERFORMAT(func) \
1061 if (uMsg == WM_RENDERFORMAT) \
1062 { \
1063 SetMsgHandled(TRUE); \
1064 func((UINT)wParam); \
1065 lResult = 0; \
1066 if(IsMsgHandled()) \
1067 return TRUE; \
1068 }
1069
1070 // void OnRenderAllFormats()
1071 #define MSG_WM_RENDERALLFORMATS(func) \
1072 if (uMsg == WM_RENDERALLFORMATS) \
1073 { \
1074 SetMsgHandled(TRUE); \
1075 func(); \
1076 lResult = 0; \
1077 if(IsMsgHandled()) \
1078 return TRUE; \
1079 }
1080
1081 // void OnDestroyClipboard()
1082 #define MSG_WM_DESTROYCLIPBOARD(func) \
1083 if (uMsg == WM_DESTROYCLIPBOARD) \
1084 { \
1085 SetMsgHandled(TRUE); \
1086 func(); \
1087 lResult = 0; \
1088 if(IsMsgHandled()) \
1089 return TRUE; \
1090 }
1091
1092 // void OnDrawClipboard()
1093 #define MSG_WM_DRAWCLIPBOARD(func) \
1094 if (uMsg == WM_DRAWCLIPBOARD) \
1095 { \
1096 SetMsgHandled(TRUE); \
1097 func(); \
1098 lResult = 0; \
1099 if(IsMsgHandled()) \
1100 return TRUE; \
1101 }
1102
1103 // void OnPaintClipboard(CWindow wndViewer, const LPPAINTSTRUCT lpPaintStruct)
1104 #define MSG_WM_PAINTCLIPBOARD(func) \
1105 if (uMsg == WM_PAINTCLIPBOARD) \
1106 { \
1107 SetMsgHandled(TRUE); \
1108 func((HWND)wParam, (const LPPAINTSTRUCT)::GlobalLock((HGLOBAL)lParam)); \
1109 ::GlobalUnlock((HGLOBAL)lParam); \
1110 lResult = 0; \
1111 if(IsMsgHandled()) \
1112 return TRUE; \
1113 }
1114
1115 // void OnVScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
1116 #define MSG_WM_VSCROLLCLIPBOARD(func) \
1117 if (uMsg == WM_VSCROLLCLIPBOARD) \
1118 { \
1119 SetMsgHandled(TRUE); \
1120 func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
1121 lResult = 0; \
1122 if(IsMsgHandled()) \
1123 return TRUE; \
1124 }
1125
1126 // void OnContextMenu(CWindow wnd, CPoint point)
1127 #define MSG_WM_CONTEXTMENU(func) \
1128 if (uMsg == WM_CONTEXTMENU) \
1129 { \
1130 SetMsgHandled(TRUE); \
1131 func((HWND)wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1132 lResult = 0; \
1133 if(IsMsgHandled()) \
1134 return TRUE; \
1135 }
1136
1137 // void OnSizeClipboard(CWindow wndViewer, const LPRECT lpRect)
1138 #define MSG_WM_SIZECLIPBOARD(func) \
1139 if (uMsg == WM_SIZECLIPBOARD) \
1140 { \
1141 SetMsgHandled(TRUE); \
1142 func((HWND)wParam, (const LPRECT)::GlobalLock((HGLOBAL)lParam)); \
1143 ::GlobalUnlock((HGLOBAL)lParam); \
1144 lResult = 0; \
1145 if(IsMsgHandled()) \
1146 return TRUE; \
1147 }
1148
1149 // void OnAskCbFormatName(UINT nMaxCount, LPTSTR lpszString)
1150 #define MSG_WM_ASKCBFORMATNAME(func) \
1151 if (uMsg == WM_ASKCBFORMATNAME) \
1152 { \
1153 SetMsgHandled(TRUE); \
1154 func((UINT)wParam, (LPTSTR)lParam); \
1155 lResult = 0; \
1156 if(IsMsgHandled()) \
1157 return TRUE; \
1158 }
1159
1160 // void OnChangeCbChain(CWindow wndRemove, CWindow wndAfter)
1161 #define MSG_WM_CHANGECBCHAIN(func) \
1162 if (uMsg == WM_CHANGECBCHAIN) \
1163 { \
1164 SetMsgHandled(TRUE); \
1165 func((HWND)wParam, (HWND)lParam); \
1166 lResult = 0; \
1167 if(IsMsgHandled()) \
1168 return TRUE; \
1169 }
1170
1171 // void OnHScrollClipboard(CWindow wndViewer, UINT nSBCode, UINT nPos)
1172 #define MSG_WM_HSCROLLCLIPBOARD(func) \
1173 if (uMsg == WM_HSCROLLCLIPBOARD) \
1174 { \
1175 SetMsgHandled(TRUE); \
1176 func((HWND)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
1177 lResult = 0; \
1178 if(IsMsgHandled()) \
1179 return TRUE; \
1180 }
1181
1182 // BOOL OnQueryNewPalette()
1183 #define MSG_WM_QUERYNEWPALETTE(func) \
1184 if (uMsg == WM_QUERYNEWPALETTE) \
1185 { \
1186 SetMsgHandled(TRUE); \
1187 lResult = (LRESULT)func(); \
1188 if(IsMsgHandled()) \
1189 return TRUE; \
1190 }
1191
1192 // void OnPaletteChanged(CWindow wndFocus)
1193 #define MSG_WM_PALETTECHANGED(func) \
1194 if (uMsg == WM_PALETTECHANGED) \
1195 { \
1196 SetMsgHandled(TRUE); \
1197 func((HWND)wParam); \
1198 lResult = 0; \
1199 if(IsMsgHandled()) \
1200 return TRUE; \
1201 }
1202
1203 // void OnPaletteIsChanging(CWindow wndPalChg)
1204 #define MSG_WM_PALETTEISCHANGING(func) \
1205 if (uMsg == WM_PALETTEISCHANGING) \
1206 { \
1207 SetMsgHandled(TRUE); \
1208 func((HWND)wParam); \
1209 lResult = 0; \
1210 if(IsMsgHandled()) \
1211 return TRUE; \
1212 }
1213
1214 // void OnDropFiles(HDROP hDropInfo)
1215 #define MSG_WM_DROPFILES(func) \
1216 if (uMsg == WM_DROPFILES) \
1217 { \
1218 SetMsgHandled(TRUE); \
1219 func((HDROP)wParam); \
1220 lResult = 0; \
1221 if(IsMsgHandled()) \
1222 return TRUE; \
1223 }
1224
1225 // void OnWindowPosChanging(LPWINDOWPOS lpWndPos)
1226 #define MSG_WM_WINDOWPOSCHANGING(func) \
1227 if (uMsg == WM_WINDOWPOSCHANGING) \
1228 { \
1229 SetMsgHandled(TRUE); \
1230 func((LPWINDOWPOS)lParam); \
1231 lResult = 0; \
1232 if(IsMsgHandled()) \
1233 return TRUE; \
1234 }
1235
1236 // void OnWindowPosChanged(LPWINDOWPOS lpWndPos)
1237 #define MSG_WM_WINDOWPOSCHANGED(func) \
1238 if (uMsg == WM_WINDOWPOSCHANGED) \
1239 { \
1240 SetMsgHandled(TRUE); \
1241 func((LPWINDOWPOS)lParam); \
1242 lResult = 0; \
1243 if(IsMsgHandled()) \
1244 return TRUE; \
1245 }
1246
1247 // void OnExitMenuLoop(BOOL fIsTrackPopupMenu)
1248 #define MSG_WM_EXITMENULOOP(func) \
1249 if (uMsg == WM_EXITMENULOOP) \
1250 { \
1251 SetMsgHandled(TRUE); \
1252 func((BOOL)wParam); \
1253 lResult = 0; \
1254 if(IsMsgHandled()) \
1255 return TRUE; \
1256 }
1257
1258 // void OnEnterMenuLoop(BOOL fIsTrackPopupMenu)
1259 #define MSG_WM_ENTERMENULOOP(func) \
1260 if (uMsg == WM_ENTERMENULOOP) \
1261 { \
1262 SetMsgHandled(TRUE); \
1263 func((BOOL)wParam); \
1264 lResult = 0; \
1265 if(IsMsgHandled()) \
1266 return TRUE; \
1267 }
1268
1269 // void OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
1270 #define MSG_WM_STYLECHANGED(func) \
1271 if (uMsg == WM_STYLECHANGED) \
1272 { \
1273 SetMsgHandled(TRUE); \
1274 func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
1275 lResult = 0; \
1276 if(IsMsgHandled()) \
1277 return TRUE; \
1278 }
1279
1280 // void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
1281 #define MSG_WM_STYLECHANGING(func) \
1282 if (uMsg == WM_STYLECHANGING) \
1283 { \
1284 SetMsgHandled(TRUE); \
1285 func((UINT)wParam, (LPSTYLESTRUCT)lParam); \
1286 lResult = 0; \
1287 if(IsMsgHandled()) \
1288 return TRUE; \
1289 }
1290
1291 // void OnSizing(UINT fwSide, LPRECT pRect)
1292 #define MSG_WM_SIZING(func) \
1293 if (uMsg == WM_SIZING) \
1294 { \
1295 SetMsgHandled(TRUE); \
1296 func((UINT)wParam, (LPRECT)lParam); \
1297 lResult = TRUE; \
1298 if(IsMsgHandled()) \
1299 return TRUE; \
1300 }
1301
1302 // void OnMoving(UINT fwSide, LPRECT pRect)
1303 #define MSG_WM_MOVING(func) \
1304 if (uMsg == WM_MOVING) \
1305 { \
1306 SetMsgHandled(TRUE); \
1307 func((UINT)wParam, (LPRECT)lParam); \
1308 lResult = TRUE; \
1309 if(IsMsgHandled()) \
1310 return TRUE; \
1311 }
1312
1313 // void OnCaptureChanged(CWindow wnd)
1314 #define MSG_WM_CAPTURECHANGED(func) \
1315 if (uMsg == WM_CAPTURECHANGED) \
1316 { \
1317 SetMsgHandled(TRUE); \
1318 func((HWND)lParam); \
1319 lResult = 0; \
1320 if(IsMsgHandled()) \
1321 return TRUE; \
1322 }
1323
1324 // BOOL OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
1325 #define MSG_WM_DEVICECHANGE(func) \
1326 if (uMsg == WM_DEVICECHANGE) \
1327 { \
1328 SetMsgHandled(TRUE); \
1329 lResult = (LRESULT)func((UINT)wParam, (DWORD_PTR)lParam); \
1330 if(IsMsgHandled()) \
1331 return TRUE; \
1332 }
1333
1334 // void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
1335 #define MSG_WM_COMMAND(func) \
1336 if (uMsg == WM_COMMAND) \
1337 { \
1338 SetMsgHandled(TRUE); \
1339 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
1340 lResult = 0; \
1341 if(IsMsgHandled()) \
1342 return TRUE; \
1343 }
1344
1345 // void OnDisplayChange(UINT uBitsPerPixel, CSize sizeScreen)
1346 #define MSG_WM_DISPLAYCHANGE(func) \
1347 if (uMsg == WM_DISPLAYCHANGE) \
1348 { \
1349 SetMsgHandled(TRUE); \
1350 func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1351 lResult = 0; \
1352 if(IsMsgHandled()) \
1353 return TRUE; \
1354 }
1355
1356 // void OnEnterSizeMove()
1357 #define MSG_WM_ENTERSIZEMOVE(func) \
1358 if (uMsg == WM_ENTERSIZEMOVE) \
1359 { \
1360 SetMsgHandled(TRUE); \
1361 func(); \
1362 lResult = 0; \
1363 if(IsMsgHandled()) \
1364 return TRUE; \
1365 }
1366
1367 // void OnExitSizeMove()
1368 #define MSG_WM_EXITSIZEMOVE(func) \
1369 if (uMsg == WM_EXITSIZEMOVE) \
1370 { \
1371 SetMsgHandled(TRUE); \
1372 func(); \
1373 lResult = 0; \
1374 if(IsMsgHandled()) \
1375 return TRUE; \
1376 }
1377
1378 // HFONT OnGetFont()
1379 #define MSG_WM_GETFONT(func) \
1380 if (uMsg == WM_GETFONT) \
1381 { \
1382 SetMsgHandled(TRUE); \
1383 lResult = (LRESULT)func(); \
1384 if(IsMsgHandled()) \
1385 return TRUE; \
1386 }
1387
1388 // LRESULT OnGetHotKey()
1389 #define MSG_WM_GETHOTKEY(func) \
1390 if (uMsg == WM_GETHOTKEY) \
1391 { \
1392 SetMsgHandled(TRUE); \
1393 lResult = func(); \
1394 if(IsMsgHandled()) \
1395 return TRUE; \
1396 }
1397
1398 // HICON OnGetIcon()
1399 #define MSG_WM_GETICON(func) \
1400 if (uMsg == WM_GETICON) \
1401 { \
1402 SetMsgHandled(TRUE); \
1403 lResult = (LRESULT)func((UINT)wParam); \
1404 if(IsMsgHandled()) \
1405 return TRUE; \
1406 }
1407
1408 // int OnGetText(int cchTextMax, LPTSTR lpszText)
1409 #define MSG_WM_GETTEXT(func) \
1410 if (uMsg == WM_GETTEXT) \
1411 { \
1412 SetMsgHandled(TRUE); \
1413 lResult = (LRESULT)func((int)wParam, (LPTSTR)lParam); \
1414 if(IsMsgHandled()) \
1415 return TRUE; \
1416 }
1417
1418 // int OnGetTextLength()
1419 #define MSG_WM_GETTEXTLENGTH(func) \
1420 if (uMsg == WM_GETTEXTLENGTH) \
1421 { \
1422 SetMsgHandled(TRUE); \
1423 lResult = (LRESULT)func(); \
1424 if(IsMsgHandled()) \
1425 return TRUE; \
1426 }
1427
1428 // void OnHelp(LPHELPINFO lpHelpInfo)
1429 #define MSG_WM_HELP(func) \
1430 if (uMsg == WM_HELP) \
1431 { \
1432 SetMsgHandled(TRUE); \
1433 func((LPHELPINFO)lParam); \
1434 lResult = TRUE; \
1435 if(IsMsgHandled()) \
1436 return TRUE; \
1437 }
1438
1439 // void OnHotKey(int nHotKeyID, UINT uModifiers, UINT uVirtKey)
1440 #define MSG_WM_HOTKEY(func) \
1441 if (uMsg == WM_HOTKEY) \
1442 { \
1443 SetMsgHandled(TRUE); \
1444 func((int)wParam, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); \
1445 lResult = 0; \
1446 if(IsMsgHandled()) \
1447 return TRUE; \
1448 }
1449
1450 // void OnInputLangChange(DWORD dwCharSet, HKL hKbdLayout)
1451 #define MSG_WM_INPUTLANGCHANGE(func) \
1452 if (uMsg == WM_INPUTLANGCHANGE) \
1453 { \
1454 SetMsgHandled(TRUE); \
1455 func((DWORD)wParam, (HKL)lParam); \
1456 lResult = TRUE; \
1457 if(IsMsgHandled()) \
1458 return TRUE; \
1459 }
1460
1461 // void OnInputLangChangeRequest(BOOL bSysCharSet, HKL hKbdLayout)
1462 #define MSG_WM_INPUTLANGCHANGEREQUEST(func) \
1463 if (uMsg == WM_INPUTLANGCHANGEREQUEST) \
1464 { \
1465 SetMsgHandled(TRUE); \
1466 func((BOOL)wParam, (HKL)lParam); \
1467 lResult = 0; \
1468 if(IsMsgHandled()) \
1469 return TRUE; \
1470 }
1471
1472 // void OnNextDlgCtl(BOOL bHandle, WPARAM wCtlFocus)
1473 #define MSG_WM_NEXTDLGCTL(func) \
1474 if (uMsg == WM_NEXTDLGCTL) \
1475 { \
1476 SetMsgHandled(TRUE); \
1477 func((BOOL)LOWORD(lParam), wParam); \
1478 lResult = 0; \
1479 if(IsMsgHandled()) \
1480 return TRUE; \
1481 }
1482
1483 // void OnNextMenu(int nVirtKey, LPMDINEXTMENU lpMdiNextMenu)
1484 #define MSG_WM_NEXTMENU(func) \
1485 if (uMsg == WM_NEXTMENU) \
1486 { \
1487 SetMsgHandled(TRUE); \
1488 func((int)wParam, (LPMDINEXTMENU)lParam); \
1489 lResult = 0; \
1490 if(IsMsgHandled()) \
1491 return TRUE; \
1492 }
1493
1494 // int OnNotifyFormat(CWindow wndFrom, int nCommand)
1495 #define MSG_WM_NOTIFYFORMAT(func) \
1496 if (uMsg == WM_NOTIFYFORMAT) \
1497 { \
1498 SetMsgHandled(TRUE); \
1499 lResult = (LRESULT)func((HWND)wParam, (int)lParam); \
1500 if(IsMsgHandled()) \
1501 return TRUE; \
1502 }
1503
1504 // BOOL OnPowerBroadcast(DWORD dwPowerEvent, DWORD_PTR dwData)
1505 #define MSG_WM_POWERBROADCAST(func) \
1506 if (uMsg == WM_POWERBROADCAST) \
1507 { \
1508 SetMsgHandled(TRUE); \
1509 lResult = (LRESULT)func((DWORD)wParam, (DWORD_PTR)lParam); \
1510 if(IsMsgHandled()) \
1511 return TRUE; \
1512 }
1513
1514 // void OnPrint(CDCHandle dc, UINT uFlags)
1515 #define MSG_WM_PRINT(func) \
1516 if (uMsg == WM_PRINT) \
1517 { \
1518 SetMsgHandled(TRUE); \
1519 func((HDC)wParam, (UINT)lParam); \
1520 lResult = 0; \
1521 if(IsMsgHandled()) \
1522 return TRUE; \
1523 }
1524
1525 // void OnPrintClient(CDCHandle dc, UINT uFlags)
1526 #define MSG_WM_PRINTCLIENT(func) \
1527 if (uMsg == WM_PRINTCLIENT) \
1528 { \
1529 SetMsgHandled(TRUE); \
1530 func((HDC)wParam, (UINT)lParam); \
1531 lResult = 0; \
1532 if(IsMsgHandled()) \
1533 return TRUE; \
1534 }
1535
1536 // void OnRasDialEvent(RASCONNSTATE rasconnstate, DWORD dwError)
1537 #define MSG_WM_RASDIALEVENT(func) \
1538 if (uMsg == WM_RASDIALEVENT) \
1539 { \
1540 SetMsgHandled(TRUE); \
1541 func((RASCONNSTATE)wParam, (DWORD)lParam); \
1542 lResult = TRUE; \
1543 if(IsMsgHandled()) \
1544 return TRUE; \
1545 }
1546
1547 // void OnSetFont(CFontHandle font, BOOL bRedraw)
1548 #define MSG_WM_SETFONT(func) \
1549 if (uMsg == WM_SETFONT) \
1550 { \
1551 SetMsgHandled(TRUE); \
1552 func((HFONT)wParam, (BOOL)LOWORD(lParam)); \
1553 lResult = 0; \
1554 if(IsMsgHandled()) \
1555 return TRUE; \
1556 }
1557
1558 // int OnSetHotKey(int nVirtKey, UINT uFlags)
1559 #define MSG_WM_SETHOTKEY(func) \
1560 if (uMsg == WM_SETHOTKEY) \
1561 { \
1562 SetMsgHandled(TRUE); \
1563 lResult = (LRESULT)func((int)LOBYTE(LOWORD(wParam)), (UINT)HIBYTE(LOWORD(wParam))); \
1564 if(IsMsgHandled()) \
1565 return TRUE; \
1566 }
1567
1568 // HICON OnSetIcon(UINT uType, HICON hIcon)
1569 #define MSG_WM_SETICON(func) \
1570 if (uMsg == WM_SETICON) \
1571 { \
1572 SetMsgHandled(TRUE); \
1573 lResult = (LRESULT)func((UINT)wParam, (HICON)lParam); \
1574 if(IsMsgHandled()) \
1575 return TRUE; \
1576 }
1577
1578 // void OnSetRedraw(BOOL bRedraw)
1579 #define MSG_WM_SETREDRAW(func) \
1580 if (uMsg == WM_SETREDRAW) \
1581 { \
1582 SetMsgHandled(TRUE); \
1583 func((BOOL)wParam); \
1584 lResult = 0; \
1585 if(IsMsgHandled()) \
1586 return TRUE; \
1587 }
1588
1589 // int OnSetText(LPCTSTR lpstrText)
1590 #define MSG_WM_SETTEXT(func) \
1591 if (uMsg == WM_SETTEXT) \
1592 { \
1593 SetMsgHandled(TRUE); \
1594 lResult = (LRESULT)func((LPCTSTR)lParam); \
1595 if(IsMsgHandled()) \
1596 return TRUE; \
1597 }
1598
1599 // void OnUserChanged()
1600 #define MSG_WM_USERCHANGED(func) \
1601 if (uMsg == WM_USERCHANGED) \
1602 { \
1603 SetMsgHandled(TRUE); \
1604 func(); \
1605 lResult = 0; \
1606 if(IsMsgHandled()) \
1607 return TRUE; \
1608 }
1609
1610 ///////////////////////////////////////////////////////////////////////////////
1611 // New NT4 & NT5 messages
1612
1613 #if (_WIN32_WINNT >= 0x0400)
1614
1615 // void OnMouseHover(WPARAM wParam, CPoint ptPos)
1616 #define MSG_WM_MOUSEHOVER(func) \
1617 if (uMsg == WM_MOUSEHOVER) \
1618 { \
1619 SetMsgHandled(TRUE); \
1620 func(wParam, _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1621 lResult = 0; \
1622 if(IsMsgHandled()) \
1623 return TRUE; \
1624 }
1625
1626 // void OnMouseLeave()
1627 #define MSG_WM_MOUSELEAVE(func) \
1628 if (uMsg == WM_MOUSELEAVE) \
1629 { \
1630 SetMsgHandled(TRUE); \
1631 func(); \
1632 lResult = 0; \
1633 if(IsMsgHandled()) \
1634 return TRUE; \
1635 }
1636
1637 #endif // _WIN32_WINNT >= 0x0400
1638
1639 #if (WINVER >= 0x0500)
1640
1641 // void OnMenuRButtonUp(WPARAM wParam, CMenuHandle menu)
1642 #define MSG_WM_MENURBUTTONUP(func) \
1643 if (uMsg == WM_MENURBUTTONUP) \
1644 { \
1645 SetMsgHandled(TRUE); \
1646 func(wParam, (HMENU)lParam); \
1647 lResult = 0; \
1648 if(IsMsgHandled()) \
1649 return TRUE; \
1650 }
1651
1652 // LRESULT OnMenuDrag(WPARAM wParam, CMenuHandle menu)
1653 #define MSG_WM_MENUDRAG(func) \
1654 if (uMsg == WM_MENUDRAG) \
1655 { \
1656 SetMsgHandled(TRUE); \
1657 lResult = func(wParam, (HMENU)lParam); \
1658 if(IsMsgHandled()) \
1659 return TRUE; \
1660 }
1661
1662 // LRESULT OnMenuGetObject(PMENUGETOBJECTINFO info)
1663 #define MSG_WM_MENUGETOBJECT(func) \
1664 if (uMsg == WM_MENUGETOBJECT) \
1665 { \
1666 SetMsgHandled(TRUE); \
1667 lResult = func((PMENUGETOBJECTINFO)lParam); \
1668 if(IsMsgHandled()) \
1669 return TRUE; \
1670 }
1671
1672 // void OnUnInitMenuPopup(UINT nID, CMenuHandle menu)
1673 #define MSG_WM_UNINITMENUPOPUP(func) \
1674 if (uMsg == WM_UNINITMENUPOPUP) \
1675 { \
1676 SetMsgHandled(TRUE); \
1677 func((UINT)HIWORD(lParam), (HMENU)wParam); \
1678 lResult = 0; \
1679 if(IsMsgHandled()) \
1680 return TRUE; \
1681 }
1682
1683 // void OnMenuCommand(WPARAM nIndex, CMenuHandle menu)
1684 #define MSG_WM_MENUCOMMAND(func) \
1685 if (uMsg == WM_MENUCOMMAND) \
1686 { \
1687 SetMsgHandled(TRUE); \
1688 func(wParam, (HMENU)lParam); \
1689 lResult = 0; \
1690 if(IsMsgHandled()) \
1691 return TRUE; \
1692 }
1693
1694 #endif // WINVER >= 0x0500
1695
1696 #if (_WIN32_WINNT >= 0x0500)
1697
1698 // BOOL OnAppCommand(CWindow wndFocus, short cmd, WORD uDevice, int dwKeys)
1699 #define MSG_WM_APPCOMMAND(func) \
1700 if (uMsg == WM_APPCOMMAND) \
1701 { \
1702 SetMsgHandled(TRUE); \
1703 lResult = (LRESULT)func((HWND)wParam, GET_APPCOMMAND_LPARAM(lParam), GET_DEVICE_LPARAM(lParam), GET_KEYSTATE_LPARAM(lParam)); \
1704 if(IsMsgHandled()) \
1705 return TRUE; \
1706 }
1707
1708 // void OnNCXButtonDown(int fwButton, short nHittest, CPoint ptPos)
1709 #define MSG_WM_NCXBUTTONDOWN(func) \
1710 if (uMsg == WM_NCXBUTTONDOWN) \
1711 { \
1712 SetMsgHandled(TRUE); \
1713 func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1714 lResult = 0; \
1715 if(IsMsgHandled()) \
1716 return TRUE; \
1717 }
1718
1719 // void OnNCXButtonUp(int fwButton, short nHittest, CPoint ptPos)
1720 #define MSG_WM_NCXBUTTONUP(func) \
1721 if (uMsg == WM_NCXBUTTONUP) \
1722 { \
1723 SetMsgHandled(TRUE); \
1724 func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1725 lResult = 0; \
1726 if(IsMsgHandled()) \
1727 return TRUE; \
1728 }
1729
1730 // void OnNCXButtonDblClk(int fwButton, short nHittest, CPoint ptPos)
1731 #define MSG_WM_NCXBUTTONDBLCLK(func) \
1732 if (uMsg == WM_NCXBUTTONDBLCLK) \
1733 { \
1734 SetMsgHandled(TRUE); \
1735 func(GET_XBUTTON_WPARAM(wParam), GET_NCHITTEST_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1736 lResult = 0; \
1737 if(IsMsgHandled()) \
1738 return TRUE; \
1739 }
1740
1741 // void OnXButtonDown(int fwButton, int dwKeys, CPoint ptPos)
1742 #define MSG_WM_XBUTTONDOWN(func) \
1743 if (uMsg == WM_XBUTTONDOWN) \
1744 { \
1745 SetMsgHandled(TRUE); \
1746 func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1747 lResult = 0; \
1748 if(IsMsgHandled()) \
1749 return TRUE; \
1750 }
1751
1752 // void OnXButtonUp(int fwButton, int dwKeys, CPoint ptPos)
1753 #define MSG_WM_XBUTTONUP(func) \
1754 if (uMsg == WM_XBUTTONUP) \
1755 { \
1756 SetMsgHandled(TRUE); \
1757 func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1758 lResult = 0; \
1759 if(IsMsgHandled()) \
1760 return TRUE; \
1761 }
1762
1763 // void OnXButtonDblClk(int fwButton, int dwKeys, CPoint ptPos)
1764 #define MSG_WM_XBUTTONDBLCLK(func) \
1765 if (uMsg == WM_XBUTTONDBLCLK) \
1766 { \
1767 SetMsgHandled(TRUE); \
1768 func(GET_XBUTTON_WPARAM(wParam), GET_KEYSTATE_WPARAM(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1769 lResult = 0; \
1770 if(IsMsgHandled()) \
1771 return TRUE; \
1772 }
1773
1774 // void OnChangeUIState(WORD nAction, WORD nState)
1775 #define MSG_WM_CHANGEUISTATE(func) \
1776 if (uMsg == WM_CHANGEUISTATE) \
1777 { \
1778 SetMsgHandled(TRUE); \
1779 func(LOWORD(wParam), HIWORD(wParam)); \
1780 lResult = 0; \
1781 if(IsMsgHandled()) \
1782 return TRUE; \
1783 }
1784
1785 // void OnUpdateUIState(WORD nAction, WORD nState)
1786 #define MSG_WM_UPDATEUISTATE(func) \
1787 if (uMsg == WM_UPDATEUISTATE) \
1788 { \
1789 SetMsgHandled(TRUE); \
1790 func(LOWORD(wParam), HIWORD(wParam)); \
1791 lResult = 0; \
1792 if(IsMsgHandled()) \
1793 return TRUE; \
1794 }
1795
1796 // LRESULT OnQueryUIState()
1797 #define MSG_WM_QUERYUISTATE(func) \
1798 if (uMsg == WM_QUERYUISTATE) \
1799 { \
1800 SetMsgHandled(TRUE); \
1801 lResult = func(); \
1802 if(IsMsgHandled()) \
1803 return TRUE; \
1804 }
1805
1806 #endif // (_WIN32_WINNT >= 0x0500)
1807
1808 #if(_WIN32_WINNT >= 0x0501)
1809
1810 // void OnInput(WPARAM RawInputCode, HRAWINPUT hRawInput)
1811 #define MSG_WM_INPUT(func) \
1812 if (uMsg == WM_INPUT) \
1813 { \
1814 SetMsgHandled(TRUE); \
1815 func(GET_RAWINPUT_CODE_WPARAM(wParam), (HRAWINPUT)lParam); \
1816 lResult = 0; \
1817 if(IsMsgHandled()) \
1818 return TRUE; \
1819 }
1820
1821 // void OnUniChar(TCHAR nChar, UINT nRepCnt, UINT nFlags)
1822 #define MSG_WM_UNICHAR(func) \
1823 if (uMsg == WM_UNICHAR) \
1824 { \
1825 SetMsgHandled(TRUE); \
1826 func((TCHAR)wParam, (UINT)lParam & 0xFFFF, (UINT)((lParam & 0xFFFF0000) >> 16)); \
1827 if(IsMsgHandled()) \
1828 { \
1829 lResult = (wParam == UNICODE_NOCHAR) ? TRUE : FALSE; \
1830 return TRUE; \
1831 } \
1832 }
1833
1834 // void OnWTSSessionChange(WPARAM nStatusCode, PWTSSESSION_NOTIFICATION nSessionID)
1835 #define MSG_WM_WTSSESSION_CHANGE(func) \
1836 if (uMsg == WM_WTSSESSION_CHANGE) \
1837 { \
1838 SetMsgHandled(TRUE); \
1839 func(wParam, (PWTSSESSION_NOTIFICATION)lParam); \
1840 lResult = 0; \
1841 if(IsMsgHandled()) \
1842 return TRUE; \
1843 }
1844
1845 // void OnThemeChanged()
1846 #define MSG_WM_THEMECHANGED(func) \
1847 if (uMsg == WM_THEMECHANGED) \
1848 { \
1849 SetMsgHandled(TRUE); \
1850 func(); \
1851 lResult = 0; \
1852 if(IsMsgHandled()) \
1853 return TRUE; \
1854 }
1855
1856 #endif // _WIN32_WINNT >= 0x0501
1857
1858 #if (_WIN32_WINNT >= 0x0600)
1859
1860 // BOOL OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt)
1861 #define MSG_WM_MOUSEHWHEEL(func) \
1862 if (uMsg == WM_MOUSEHWHEEL) \
1863 { \
1864 SetMsgHandled(TRUE); \
1865 lResult = (LRESULT)func((UINT)LOWORD(wParam), (short)HIWORD(wParam), _WTYPES_NS::CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
1866 if(IsMsgHandled()) \
1867 return TRUE; \
1868 }
1869
1870 #endif // (_WIN32_WINNT >= 0x0600)
1871
1872 ///////////////////////////////////////////////////////////////////////////////
1873 // ATL defined messages
1874
1875 // BOOL OnForwardMsg(LPMSG Msg, DWORD nUserData)
1876 #define MSG_WM_FORWARDMSG(func) \
1877 if (uMsg == WM_FORWARDMSG) \
1878 { \
1879 SetMsgHandled(TRUE); \
1880 lResult = (LRESULT)func((LPMSG)lParam, (DWORD)wParam); \
1881 if(IsMsgHandled()) \
1882 return TRUE; \
1883 }
1884
1885 ///////////////////////////////////////////////////////////////////////////////
1886 // Dialog specific messages
1887
1888 // LRESULT OnDMGetDefID()
1889 #define MSG_DM_GETDEFID(func) \
1890 if (uMsg == DM_GETDEFID) \
1891 { \
1892 SetMsgHandled(TRUE); \
1893 lResult = func(); \
1894 if(IsMsgHandled()) \
1895 return TRUE; \
1896 }
1897
1898 // void OnDMSetDefID(UINT DefID)
1899 #define MSG_DM_SETDEFID(func) \
1900 if (uMsg == DM_SETDEFID) \
1901 { \
1902 SetMsgHandled(TRUE); \
1903 func((UINT)wParam); \
1904 lResult = TRUE; \
1905 if(IsMsgHandled()) \
1906 return TRUE; \
1907 }
1908
1909 // void OnDMReposition()
1910 #define MSG_DM_REPOSITION(func) \
1911 if (uMsg == DM_REPOSITION) \
1912 { \
1913 SetMsgHandled(TRUE); \
1914 func(); \
1915 lResult = 0; \
1916 if(IsMsgHandled()) \
1917 return TRUE; \
1918 }
1919
1920 ///////////////////////////////////////////////////////////////////////////////
1921 // Reflected messages
1922
1923 // void OnReflectedCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
1924 #define MSG_OCM_COMMAND(func) \
1925 if (uMsg == OCM_COMMAND) \
1926 { \
1927 SetMsgHandled(TRUE); \
1928 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
1929 lResult = 0; \
1930 if(IsMsgHandled()) \
1931 return TRUE; \
1932 }
1933
1934 // LRESULT OnReflectedNotify(int idCtrl, LPNMHDR pnmh)
1935 #define MSG_OCM_NOTIFY(func) \
1936 if (uMsg == OCM_NOTIFY) \
1937 { \
1938 SetMsgHandled(TRUE); \
1939 lResult = func((int)wParam, (LPNMHDR)lParam); \
1940 if(IsMsgHandled()) \
1941 return TRUE; \
1942 }
1943
1944 // void OnReflectedParentNotify(UINT message, UINT nChildID, LPARAM lParam)
1945 #define MSG_OCM_PARENTNOTIFY(func) \
1946 if (uMsg == OCM_PARENTNOTIFY) \
1947 { \
1948 SetMsgHandled(TRUE); \
1949 func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), lParam); \
1950 lResult = 0; \
1951 if(IsMsgHandled()) \
1952 return TRUE; \
1953 }
1954
1955 // void OnReflectedDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
1956 #define MSG_OCM_DRAWITEM(func) \
1957 if (uMsg == OCM_DRAWITEM) \
1958 { \
1959 SetMsgHandled(TRUE); \
1960 func((UINT)wParam, (LPDRAWITEMSTRUCT)lParam); \
1961 lResult = TRUE; \
1962 if(IsMsgHandled()) \
1963 return TRUE; \
1964 }
1965
1966 // void OnReflectedMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
1967 #define MSG_OCM_MEASUREITEM(func) \
1968 if (uMsg == OCM_MEASUREITEM) \
1969 { \
1970 SetMsgHandled(TRUE); \
1971 func((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam); \
1972 lResult = TRUE; \
1973 if(IsMsgHandled()) \
1974 return TRUE; \
1975 }
1976
1977 // int OnReflectedCompareItem(int nIDCtl, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
1978 #define MSG_OCM_COMPAREITEM(func) \
1979 if (uMsg == OCM_COMPAREITEM) \
1980 { \
1981 SetMsgHandled(TRUE); \
1982 lResult = (LRESULT)func((UINT)wParam, (LPCOMPAREITEMSTRUCT)lParam); \
1983 if(IsMsgHandled()) \
1984 return TRUE; \
1985 }
1986
1987 // void OnReflectedDeleteItem(int nIDCtl, LPDELETEITEMSTRUCT lpDeleteItemStruct)
1988 #define MSG_OCM_DELETEITEM(func) \
1989 if (uMsg == OCM_DELETEITEM) \
1990 { \
1991 SetMsgHandled(TRUE); \
1992 func((UINT)wParam, (LPDELETEITEMSTRUCT)lParam); \
1993 lResult = TRUE; \
1994 if(IsMsgHandled()) \
1995 return TRUE; \
1996 }
1997
1998 // int OnReflectedVKeyToItem(UINT nKey, UINT nIndex, CListBox listBox)
1999 #define MSG_OCM_VKEYTOITEM(func) \
2000 if (uMsg == OCM_VKEYTOITEM) \
2001 { \
2002 SetMsgHandled(TRUE); \
2003 lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
2004 if(IsMsgHandled()) \
2005 return TRUE; \
2006 }
2007
2008 //int OnReflectedCharToItem(UINT nChar, UINT nIndex, CListBox listBox)
2009 #define MSG_OCM_CHARTOITEM(func) \
2010 if (uMsg == OCM_CHARTOITEM) \
2011 { \
2012 SetMsgHandled(TRUE); \
2013 lResult = (LRESULT)func((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); \
2014 if(IsMsgHandled()) \
2015 return TRUE; \
2016 }
2017
2018 // void OnReflectedHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
2019 #define MSG_OCM_HSCROLL(func) \
2020 if (uMsg == OCM_HSCROLL) \
2021 { \
2022 SetMsgHandled(TRUE); \
2023 func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
2024 lResult = 0; \
2025 if(IsMsgHandled()) \
2026 return TRUE; \
2027 }
2028
2029 // void OnReflectedVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)
2030 #define MSG_OCM_VSCROLL(func) \
2031 if (uMsg == OCM_VSCROLL) \
2032 { \
2033 SetMsgHandled(TRUE); \
2034 func((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); \
2035 lResult = 0; \
2036 if(IsMsgHandled()) \
2037 return TRUE; \
2038 }
2039
2040 // HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, CEdit edit)
2041 #define MSG_OCM_CTLCOLOREDIT(func) \
2042 if (uMsg == OCM_CTLCOLOREDIT) \
2043 { \
2044 SetMsgHandled(TRUE); \
2045 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
2046 if(IsMsgHandled()) \
2047 return TRUE; \
2048 }
2049
2050 // HBRUSH OnReflectedCtlColorListBox(CDCHandle dc, CListBox listBox)
2051 #define MSG_OCM_CTLCOLORLISTBOX(func) \
2052 if (uMsg == OCM_CTLCOLORLISTBOX) \
2053 { \
2054 SetMsgHandled(TRUE); \
2055 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
2056 if(IsMsgHandled()) \
2057 return TRUE; \
2058 }
2059
2060 // HBRUSH OnReflectedCtlColorBtn(CDCHandle dc, CButton button)
2061 #define MSG_OCM_CTLCOLORBTN(func) \
2062 if (uMsg == OCM_CTLCOLORBTN) \
2063 { \
2064 SetMsgHandled(TRUE); \
2065 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
2066 if(IsMsgHandled()) \
2067 return TRUE; \
2068 }
2069
2070 // HBRUSH OnReflectedCtlColorDlg(CDCHandle dc, CWindow wnd)
2071 #define MSG_OCM_CTLCOLORDLG(func) \
2072 if (uMsg == OCM_CTLCOLORDLG) \
2073 { \
2074 SetMsgHandled(TRUE); \
2075 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
2076 if(IsMsgHandled()) \
2077 return TRUE; \
2078 }
2079
2080 // HBRUSH OnReflectedCtlColorScrollBar(CDCHandle dc, CScrollBar scrollBar)
2081 #define MSG_OCM_CTLCOLORSCROLLBAR(func) \
2082 if (uMsg == OCM_CTLCOLORSCROLLBAR) \
2083 { \
2084 SetMsgHandled(TRUE); \
2085 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
2086 if(IsMsgHandled()) \
2087 return TRUE; \
2088 }
2089
2090 // HBRUSH OnReflectedCtlColorStatic(CDCHandle dc, CStatic wndStatic)
2091 #define MSG_OCM_CTLCOLORSTATIC(func) \
2092 if (uMsg == OCM_CTLCOLORSTATIC) \
2093 { \
2094 SetMsgHandled(TRUE); \
2095 lResult = (LRESULT)func((HDC)wParam, (HWND)lParam); \
2096 if(IsMsgHandled()) \
2097 return TRUE; \
2098 }
2099
2100 ///////////////////////////////////////////////////////////////////////////////
2101 // Edit specific messages
2102
2103 // void OnClear()
2104 #define MSG_WM_CLEAR(func) \
2105 if (uMsg == WM_CLEAR) \
2106 { \
2107 SetMsgHandled(TRUE); \
2108 func(); \
2109 lResult = 0; \
2110 if(IsMsgHandled()) \
2111 return TRUE; \
2112 }
2113
2114 // void OnCopy()
2115 #define MSG_WM_COPY(func) \
2116 if (uMsg == WM_COPY) \
2117 { \
2118 SetMsgHandled(TRUE); \
2119 func(); \
2120 lResult = 0; \
2121 if(IsMsgHandled()) \
2122 return TRUE; \
2123 }
2124
2125 // void OnCut()
2126 #define MSG_WM_CUT(func) \
2127 if (uMsg == WM_CUT) \
2128 { \
2129 SetMsgHandled(TRUE); \
2130 func(); \
2131 lResult = 0; \
2132 if(IsMsgHandled()) \
2133 return TRUE; \
2134 }
2135
2136 // void OnPaste()
2137 #define MSG_WM_PASTE(func) \
2138 if (uMsg == WM_PASTE) \
2139 { \
2140 SetMsgHandled(TRUE); \
2141 func(); \
2142 lResult = 0; \
2143 if(IsMsgHandled()) \
2144 return TRUE; \
2145 }
2146
2147 // void OnUndo()
2148 #define MSG_WM_UNDO(func) \
2149 if (uMsg == WM_UNDO) \
2150 { \
2151 SetMsgHandled(TRUE); \
2152 func(); \
2153 lResult = 0; \
2154 if(IsMsgHandled()) \
2155 return TRUE; \
2156 }
2157
2158 ///////////////////////////////////////////////////////////////////////////////
2159 // Generic message handlers
2160
2161 // LRESULT OnMessageHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
2162 #define MESSAGE_HANDLER_EX(msg, func) \
2163 if(uMsg == msg) \
2164 { \
2165 SetMsgHandled(TRUE); \
2166 lResult = func(uMsg, wParam, lParam); \
2167 if(IsMsgHandled()) \
2168 return TRUE; \
2169 }
2170
2171 // LRESULT OnMessageRangeHandlerEX(UINT uMsg, WPARAM wParam, LPARAM lParam)
2172 #define MESSAGE_RANGE_HANDLER_EX(msgFirst, msgLast, func) \
2173 if(uMsg >= msgFirst && uMsg <= msgLast) \
2174 { \
2175 SetMsgHandled(TRUE); \
2176 lResult = func(uMsg, wParam, lParam); \
2177 if(IsMsgHandled()) \
2178 return TRUE; \
2179 }
2180
2181 ///////////////////////////////////////////////////////////////////////////////
2182 // Commands and notifications
2183
2184 // void OnCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2185 #define COMMAND_HANDLER_EX(id, code, func) \
2186 if (uMsg == WM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
2187 { \
2188 SetMsgHandled(TRUE); \
2189 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2190 lResult = 0; \
2191 if(IsMsgHandled()) \
2192 return TRUE; \
2193 }
2194
2195 // void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2196 #define COMMAND_ID_HANDLER_EX(id, func) \
2197 if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
2198 { \
2199 SetMsgHandled(TRUE); \
2200 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2201 lResult = 0; \
2202 if(IsMsgHandled()) \
2203 return TRUE; \
2204 }
2205
2206 // void OnCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2207 #define COMMAND_CODE_HANDLER_EX(code, func) \
2208 if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \
2209 { \
2210 SetMsgHandled(TRUE); \
2211 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2212 lResult = 0; \
2213 if(IsMsgHandled()) \
2214 return TRUE; \
2215 }
2216
2217 // LRESULT OnNotifyHandlerEX(LPNMHDR pnmh)
2218 #define NOTIFY_HANDLER_EX(id, cd, func) \
2219 if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \
2220 { \
2221 SetMsgHandled(TRUE); \
2222 lResult = func((LPNMHDR)lParam); \
2223 if(IsMsgHandled()) \
2224 return TRUE; \
2225 }
2226
2227 // LRESULT OnNotifyIDHandlerEX(LPNMHDR pnmh)
2228 #define NOTIFY_ID_HANDLER_EX(id, func) \
2229 if (uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
2230 { \
2231 SetMsgHandled(TRUE); \
2232 lResult = func((LPNMHDR)lParam); \
2233 if(IsMsgHandled()) \
2234 return TRUE; \
2235 }
2236
2237 // LRESULT OnNotifyCodeHandlerEX(LPNMHDR pnmh)
2238 #define NOTIFY_CODE_HANDLER_EX(cd, func) \
2239 if (uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
2240 { \
2241 SetMsgHandled(TRUE); \
2242 lResult = func((LPNMHDR)lParam); \
2243 if(IsMsgHandled()) \
2244 return TRUE; \
2245 }
2246
2247 // void OnCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2248 #define COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
2249 if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
2250 { \
2251 SetMsgHandled(TRUE); \
2252 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2253 lResult = 0; \
2254 if(IsMsgHandled()) \
2255 return TRUE; \
2256 }
2257
2258 // void OnCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2259 #define COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
2260 if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
2261 { \
2262 SetMsgHandled(TRUE); \
2263 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2264 lResult = 0; \
2265 if(IsMsgHandled()) \
2266 return TRUE; \
2267 }
2268
2269 // LRESULT OnNotifyRangeHandlerEX(LPNMHDR pnmh)
2270 #define NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
2271 if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
2272 { \
2273 SetMsgHandled(TRUE); \
2274 lResult = func((LPNMHDR)lParam); \
2275 if(IsMsgHandled()) \
2276 return TRUE; \
2277 }
2278
2279 // LRESULT OnNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
2280 #define NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
2281 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
2282 { \
2283 SetMsgHandled(TRUE); \
2284 lResult = func((LPNMHDR)lParam); \
2285 if(IsMsgHandled()) \
2286 return TRUE; \
2287 }
2288
2289 // LRESULT OnReflectedCommandHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2290 #define REFLECTED_COMMAND_HANDLER_EX(id, code, func) \
2291 if (uMsg == OCM_COMMAND && code == HIWORD(wParam) && id == LOWORD(wParam)) \
2292 { \
2293 SetMsgHandled(TRUE); \
2294 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2295 lResult = 0; \
2296 if(IsMsgHandled()) \
2297 return TRUE; \
2298 }
2299
2300 // LRESULT OnReflectedCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2301 #define REFLECTED_COMMAND_ID_HANDLER_EX(id, func) \
2302 if (uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
2303 { \
2304 SetMsgHandled(TRUE); \
2305 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2306 lResult = 0; \
2307 if(IsMsgHandled()) \
2308 return TRUE; \
2309 }
2310
2311 // LRESULT OnReflectedCommandCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2312 #define REFLECTED_COMMAND_CODE_HANDLER_EX(code, func) \
2313 if (uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
2314 { \
2315 SetMsgHandled(TRUE); \
2316 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2317 lResult = 0; \
2318 if(IsMsgHandled()) \
2319 return TRUE; \
2320 }
2321
2322 // LRESULT OnReflectedNotifyHandlerEX(LPNMHDR pnmh)
2323 #define REFLECTED_NOTIFY_HANDLER_EX(id, cd, func) \
2324 if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && id == ((LPNMHDR)lParam)->idFrom) \
2325 { \
2326 SetMsgHandled(TRUE); \
2327 lResult = func((LPNMHDR)lParam); \
2328 if(IsMsgHandled()) \
2329 return TRUE; \
2330 }
2331
2332 // LRESULT OnReflectedNotifyIDHandlerEX(LPNMHDR pnmh)
2333 #define REFLECTED_NOTIFY_ID_HANDLER_EX(id, func) \
2334 if (uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
2335 { \
2336 SetMsgHandled(TRUE); \
2337 lResult = func((LPNMHDR)lParam); \
2338 if(IsMsgHandled()) \
2339 return TRUE; \
2340 }
2341
2342 // LRESULT OnReflectedNotifyCodeHandlerEX(LPNMHDR pnmh)
2343 #define REFLECTED_NOTIFY_CODE_HANDLER_EX(cd, func) \
2344 if (uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
2345 { \
2346 SetMsgHandled(TRUE); \
2347 lResult = func((LPNMHDR)lParam); \
2348 if(IsMsgHandled()) \
2349 return TRUE; \
2350 }
2351
2352 // void OnReflectedCommandRangeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2353 #define REFLECTED_COMMAND_RANGE_HANDLER_EX(idFirst, idLast, func) \
2354 if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
2355 { \
2356 SetMsgHandled(TRUE); \
2357 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2358 lResult = 0; \
2359 if(IsMsgHandled()) \
2360 return TRUE; \
2361 }
2362
2363 // void OnReflectedCommandRangeCodeHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
2364 #define REFLECTED_COMMAND_RANGE_CODE_HANDLER_EX(idFirst, idLast, code, func) \
2365 if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
2366 { \
2367 SetMsgHandled(TRUE); \
2368 func((UINT)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam); \
2369 lResult = 0; \
2370 if(IsMsgHandled()) \
2371 return TRUE; \
2372 }
2373
2374 // LRESULT OnReflectedNotifyRangeHandlerEX(LPNMHDR pnmh)
2375 #define REFLECTED_NOTIFY_RANGE_HANDLER_EX(idFirst, idLast, func) \
2376 if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
2377 { \
2378 SetMsgHandled(TRUE); \
2379 lResult = func((LPNMHDR)lParam); \
2380 if(IsMsgHandled()) \
2381 return TRUE; \
2382 }
2383
2384 // LRESULT OnReflectedNotifyRangeCodeHandlerEX(LPNMHDR pnmh)
2385 #define REFLECTED_NOTIFY_RANGE_CODE_HANDLER_EX(idFirst, idLast, cd, func) \
2386 if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
2387 { \
2388 SetMsgHandled(TRUE); \
2389 lResult = func((LPNMHDR)lParam); \
2390 if(IsMsgHandled()) \
2391 return TRUE; \
2392 }
2393
2394 #endif // __ATLCRACK_H__
+0
-10252
src/third_party/wtl/Include/atlctrls.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLCTRLS_H__
9 #define __ATLCTRLS_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlctrls.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLWIN_H__
18 #error atlctrls.h requires atlwin.h to be included first
19 #endif
20
21 #ifndef _WIN32_WCE
22 #include <richedit.h>
23 #include <richole.h>
24 #elif defined(WIN32_PLATFORM_WFSP) && !defined(_WINUSERM_H_)
25 #include <winuserm.h>
26 #endif // !_WIN32_WCE
27
28 // protect template members from windowsx.h macros
29 #ifdef _INC_WINDOWSX
30 #undef GetNextSibling
31 #undef GetPrevSibling
32 #endif // _INC_WINDOWSX
33
34
35 ///////////////////////////////////////////////////////////////////////////////
36 // Classes in this file:
37 //
38 // CStaticT<TBase> - CStatic
39 // CButtonT<TBase> - CButton
40 // CListBoxT<TBase> - CListBox
41 // CComboBoxT<TBase> - CComboBox
42 // CEditT<TBase> - CEdit
43 // CEditCommands<T>
44 // CScrollBarT<TBase> - CScrollBar
45 //
46 // CImageListT<t_bManaged> - CImageList, CImageListManaged
47 // CListViewCtrlT<TBase> - CListViewCtrl
48 // CTreeViewCtrlT<TBase> - CTreeViewCtrl
49 // CTreeItemT<TBase> - CTreeItem
50 // CTreeViewCtrlExT<TBase> - CTreeViewCtrlEx
51 // CHeaderCtrlT<TBase> - CHeaderCtrl
52 // CToolBarCtrlT<TBase> - CToolBarCtrl
53 // CStatusBarCtrlT<TBase> - CStatusBarCtrl
54 // CTabCtrlT<TBase> - CTabCtrl
55 // CToolInfo
56 // CToolTipCtrlT<TBase> - CToolTipCtrl
57 // CTrackBarCtrlT<TBase> - CTrackBarCtrl
58 // CUpDownCtrlT<TBase> - CUpDownCtrl
59 // CProgressBarCtrlT<TBase> - CProgressBarCtrl
60 // CHotKeyCtrlT<TBase> - CHotKeyCtrl
61 // CAnimateCtrlT<TBase> - CAnimateCtrl
62 // CRichEditCtrlT<TBase> - CRichEditCtrl
63 // CRichEditCommands<T>
64 // CDragListBoxT<TBase> - CDragListBox
65 // CDragListNotifyImpl<T>
66 // CReBarCtrlT<TBase> - CReBarCtrl
67 // CComboBoxExT<TBase> - CComboBoxEx
68 // CDateTimePickerCtrlT<TBase> - CDateTimePickerCtrl
69 // CMonthCalendarCtrlT<TBase> - CMonthCalendarCtrl
70 // CFlatScrollBarImpl<T>
71 // CFlatScrollBarT<TBase> - CFlatScrollBar
72 // CIPAddressCtrlT<TBase> - CIPAddressCtrl
73 // CPagerCtrlT<TBase> - CPagerCtrl
74 // CLinkCtrlT<TBase> - CLinkCtrl
75 //
76 // CCustomDraw<T>
77 //
78 // CCECommandBarCtrlT<TBase> - CCECommandBarCtrl
79 // CCECommandBandsCtrlT<TBase> - CCECommandBandsCtrl
80
81
82 namespace WTL
83 {
84
85 // These are wrapper classes for Windows standard and common controls.
86 // To implement a window based on a control, use following:
87 // Example: Implementing a window based on a list box
88 //
89 // class CMyListBox : CWindowImpl<CMyListBox, CListBox>
90 // {
91 // public:
92 // BEGIN_MSG_MAP(CMyListBox)
93 // // put your message handler entries here
94 // END_MSG_MAP()
95 // };
96
97
98
99 // --- Standard Windows controls ---
100
101 ///////////////////////////////////////////////////////////////////////////////
102 // CStatic - client side for a Windows STATIC control
103
104 template <class TBase>
105 class CStaticT : public TBase
106 {
107 public:
108 // Constructors
109 CStaticT(HWND hWnd = NULL) : TBase(hWnd)
110 { }
111
112 CStaticT< TBase >& operator =(HWND hWnd)
113 {
114 m_hWnd = hWnd;
115 return *this;
116 }
117
118 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
119 DWORD dwStyle = 0, DWORD dwExStyle = 0,
120 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
121 {
122 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
123 }
124
125 // Attributes
126 static LPCTSTR GetWndClassName()
127 {
128 return _T("STATIC");
129 }
130
131 #ifndef _WIN32_WCE
132 HICON GetIcon() const
133 {
134 ATLASSERT(::IsWindow(m_hWnd));
135 return (HICON)::SendMessage(m_hWnd, STM_GETICON, 0, 0L);
136 }
137
138 HICON SetIcon(HICON hIcon)
139 {
140 ATLASSERT(::IsWindow(m_hWnd));
141 return (HICON)::SendMessage(m_hWnd, STM_SETICON, (WPARAM)hIcon, 0L);
142 }
143
144 HENHMETAFILE GetEnhMetaFile() const
145 {
146 ATLASSERT(::IsWindow(m_hWnd));
147 return (HENHMETAFILE)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ENHMETAFILE, 0L);
148 }
149
150 HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile)
151 {
152 ATLASSERT(::IsWindow(m_hWnd));
153 return (HENHMETAFILE)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile);
154 }
155 #else // CE specific
156 HICON GetIcon() const
157 {
158 ATLASSERT(::IsWindow(m_hWnd));
159 return (HICON)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_ICON, 0L);
160 }
161
162 HICON SetIcon(HICON hIcon)
163 {
164 ATLASSERT(::IsWindow(m_hWnd));
165 return (HICON)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
166 }
167 #endif // _WIN32_WCE
168
169 CBitmapHandle GetBitmap() const
170 {
171 ATLASSERT(::IsWindow(m_hWnd));
172 return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_BITMAP, 0L));
173 }
174
175 CBitmapHandle SetBitmap(HBITMAP hBitmap)
176 {
177 ATLASSERT(::IsWindow(m_hWnd));
178 return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
179 }
180
181 HCURSOR GetCursor() const
182 {
183 ATLASSERT(::IsWindow(m_hWnd));
184 return (HCURSOR)::SendMessage(m_hWnd, STM_GETIMAGE, IMAGE_CURSOR, 0L);
185 }
186
187 HCURSOR SetCursor(HCURSOR hCursor)
188 {
189 ATLASSERT(::IsWindow(m_hWnd));
190 return (HCURSOR)::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
191 }
192 };
193
194 typedef CStaticT<ATL::CWindow> CStatic;
195
196
197 ///////////////////////////////////////////////////////////////////////////////
198 // CButton - client side for a Windows BUTTON control
199
200 template <class TBase>
201 class CButtonT : public TBase
202 {
203 public:
204 // Constructors
205 CButtonT(HWND hWnd = NULL) : TBase(hWnd)
206 { }
207
208 CButtonT< TBase >& operator =(HWND hWnd)
209 {
210 m_hWnd = hWnd;
211 return *this;
212 }
213
214 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
215 DWORD dwStyle = 0, DWORD dwExStyle = 0,
216 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
217 {
218 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
219 }
220
221 // Attributes
222 static LPCTSTR GetWndClassName()
223 {
224 return _T("BUTTON");
225 }
226
227 UINT GetState() const
228 {
229 ATLASSERT(::IsWindow(m_hWnd));
230 return (UINT)::SendMessage(m_hWnd, BM_GETSTATE, 0, 0L);
231 }
232
233 void SetState(BOOL bHighlight)
234 {
235 ATLASSERT(::IsWindow(m_hWnd));
236 ::SendMessage(m_hWnd, BM_SETSTATE, bHighlight, 0L);
237 }
238
239 int GetCheck() const
240 {
241 ATLASSERT(::IsWindow(m_hWnd));
242 return (int)::SendMessage(m_hWnd, BM_GETCHECK, 0, 0L);
243 }
244
245 void SetCheck(int nCheck)
246 {
247 ATLASSERT(::IsWindow(m_hWnd));
248 ::SendMessage(m_hWnd, BM_SETCHECK, nCheck, 0L);
249 }
250
251 UINT GetButtonStyle() const
252 {
253 ATLASSERT(::IsWindow(m_hWnd));
254 return (UINT)::GetWindowLong(m_hWnd, GWL_STYLE) & 0xFFFF;
255 }
256
257 void SetButtonStyle(UINT nStyle, BOOL bRedraw = TRUE)
258 {
259 ATLASSERT(::IsWindow(m_hWnd));
260 ::SendMessage(m_hWnd, BM_SETSTYLE, nStyle, (LPARAM)bRedraw);
261 }
262
263 #ifndef _WIN32_WCE
264 HICON GetIcon() const
265 {
266 ATLASSERT(::IsWindow(m_hWnd));
267 return (HICON)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_ICON, 0L);
268 }
269
270 HICON SetIcon(HICON hIcon)
271 {
272 ATLASSERT(::IsWindow(m_hWnd));
273 return (HICON)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
274 }
275
276 CBitmapHandle GetBitmap() const
277 {
278 ATLASSERT(::IsWindow(m_hWnd));
279 return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0L));
280 }
281
282 CBitmapHandle SetBitmap(HBITMAP hBitmap)
283 {
284 ATLASSERT(::IsWindow(m_hWnd));
285 return CBitmapHandle((HBITMAP)::SendMessage(m_hWnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap));
286 }
287 #endif // !_WIN32_WCE
288
289 #if (_WIN32_WINNT >= 0x0501)
290 BOOL GetIdealSize(LPSIZE lpSize) const
291 {
292 ATLASSERT(::IsWindow(m_hWnd));
293 return (BOOL)::SendMessage(m_hWnd, BCM_GETIDEALSIZE, 0, (LPARAM)lpSize);
294 }
295
296 BOOL GetImageList(PBUTTON_IMAGELIST pButtonImagelist) const
297 {
298 ATLASSERT(::IsWindow(m_hWnd));
299 return (BOOL)::SendMessage(m_hWnd, BCM_GETIMAGELIST, 0, (LPARAM)pButtonImagelist);
300 }
301
302 BOOL SetImageList(PBUTTON_IMAGELIST pButtonImagelist)
303 {
304 ATLASSERT(::IsWindow(m_hWnd));
305 return (BOOL)::SendMessage(m_hWnd, BCM_SETIMAGELIST, 0, (LPARAM)pButtonImagelist);
306 }
307
308 BOOL GetTextMargin(LPRECT lpRect) const
309 {
310 ATLASSERT(::IsWindow(m_hWnd));
311 return (BOOL)::SendMessage(m_hWnd, BCM_GETTEXTMARGIN, 0, (LPARAM)lpRect);
312 }
313
314 BOOL SetTextMargin(LPRECT lpRect)
315 {
316 ATLASSERT(::IsWindow(m_hWnd));
317 return (BOOL)::SendMessage(m_hWnd, BCM_SETTEXTMARGIN, 0, (LPARAM)lpRect);
318 }
319 #endif // (_WIN32_WINNT >= 0x0501)
320
321 #if (WINVER >= 0x0600)
322 void SetDontClick(BOOL bDontClick)
323 {
324 ATLASSERT(::IsWindow(m_hWnd));
325 ::SendMessage(m_hWnd, BM_SETDONTCLICK, (WPARAM)bDontClick, 0L);
326 }
327 #endif // (WINVER >= 0x0600)
328
329 #if (_WIN32_WINNT >= 0x0600)
330 BOOL SetDropDownState(BOOL bDropDown)
331 {
332 ATLASSERT(::IsWindow(m_hWnd));
333 ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
334 return (BOOL)::SendMessage(m_hWnd, BCM_SETDROPDOWNSTATE, (WPARAM)bDropDown, 0L);
335 }
336
337 BOOL GetSplitInfo(PBUTTON_SPLITINFO pSplitInfo) const
338 {
339 ATLASSERT(::IsWindow(m_hWnd));
340 ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
341 return (BOOL)::SendMessage(m_hWnd, BCM_GETSPLITINFO, 0, (LPARAM)pSplitInfo);
342 }
343
344 BOOL SetSplitInfo(PBUTTON_SPLITINFO pSplitInfo)
345 {
346 ATLASSERT(::IsWindow(m_hWnd));
347 ATLASSERT((GetStyle() & (BS_SPLITBUTTON | BS_DEFSPLITBUTTON)) != 0);
348 return (BOOL)::SendMessage(m_hWnd, BCM_SETSPLITINFO, 0, (LPARAM)pSplitInfo);
349 }
350
351 int GetNoteLength() const
352 {
353 ATLASSERT(::IsWindow(m_hWnd));
354 ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
355 return (int)::SendMessage(m_hWnd, BCM_GETNOTELENGTH, 0, 0L);
356 }
357
358 BOOL GetNote(LPWSTR lpstrNoteText, int cchNoteText) const
359 {
360 ATLASSERT(::IsWindow(m_hWnd));
361 ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
362 return (BOOL)::SendMessage(m_hWnd, BCM_GETNOTE, cchNoteText, (LPARAM)lpstrNoteText);
363 }
364
365 BOOL SetNote(LPCWSTR lpstrNoteText)
366 {
367 ATLASSERT(::IsWindow(m_hWnd));
368 ATLASSERT((GetStyle() & (BS_COMMANDLINK | BS_DEFCOMMANDLINK)) != 0);
369 return (BOOL)::SendMessage(m_hWnd, BCM_SETNOTE, 0, (LPARAM)lpstrNoteText);
370 }
371
372 LRESULT SetElevationRequiredState(BOOL bSet)
373 {
374 ATLASSERT(::IsWindow(m_hWnd));
375 return ::SendMessage(m_hWnd, BCM_SETSHIELD, 0, (LPARAM)bSet);
376 }
377 #endif // (_WIN32_WINNT >= 0x0600)
378
379 // Operations
380 void Click()
381 {
382 ATLASSERT(::IsWindow(m_hWnd));
383 ::SendMessage(m_hWnd, BM_CLICK, 0, 0L);
384 }
385 };
386
387 typedef CButtonT<ATL::CWindow> CButton;
388
389
390 ///////////////////////////////////////////////////////////////////////////////
391 // CListBox - client side for a Windows LISTBOX control
392
393 template <class TBase>
394 class CListBoxT : public TBase
395 {
396 public:
397 // Constructors
398 CListBoxT(HWND hWnd = NULL) : TBase(hWnd)
399 { }
400
401 CListBoxT< TBase >& operator =(HWND hWnd)
402 {
403 m_hWnd = hWnd;
404 return *this;
405 }
406
407 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
408 DWORD dwStyle = 0, DWORD dwExStyle = 0,
409 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
410 {
411 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
412 }
413
414 // Attributes
415 static LPCTSTR GetWndClassName()
416 {
417 return _T("LISTBOX");
418 }
419
420 // for entire listbox
421 int GetCount() const
422 {
423 ATLASSERT(::IsWindow(m_hWnd));
424 return (int)::SendMessage(m_hWnd, LB_GETCOUNT, 0, 0L);
425 }
426
427 #ifndef _WIN32_WCE
428 int SetCount(int cItems)
429 {
430 ATLASSERT(::IsWindow(m_hWnd));
431 ATLASSERT(((GetStyle() & LBS_NODATA) != 0) && ((GetStyle() & LBS_HASSTRINGS) == 0));
432 return (int)::SendMessage(m_hWnd, LB_SETCOUNT, cItems, 0L);
433 }
434 #endif // !_WIN32_WCE
435
436 int GetHorizontalExtent() const
437 {
438 ATLASSERT(::IsWindow(m_hWnd));
439 return (int)::SendMessage(m_hWnd, LB_GETHORIZONTALEXTENT, 0, 0L);
440 }
441
442 void SetHorizontalExtent(int cxExtent)
443 {
444 ATLASSERT(::IsWindow(m_hWnd));
445 ::SendMessage(m_hWnd, LB_SETHORIZONTALEXTENT, cxExtent, 0L);
446 }
447
448 int GetTopIndex() const
449 {
450 ATLASSERT(::IsWindow(m_hWnd));
451 return (int)::SendMessage(m_hWnd, LB_GETTOPINDEX, 0, 0L);
452 }
453
454 int SetTopIndex(int nIndex)
455 {
456 ATLASSERT(::IsWindow(m_hWnd));
457 return (int)::SendMessage(m_hWnd, LB_SETTOPINDEX, nIndex, 0L);
458 }
459
460 LCID GetLocale() const
461 {
462 ATLASSERT(::IsWindow(m_hWnd));
463 return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0L);
464 }
465
466 LCID SetLocale(LCID nNewLocale)
467 {
468 ATLASSERT(::IsWindow(m_hWnd));
469 return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0L);
470 }
471
472 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
473 DWORD GetListBoxInfo() const
474 {
475 ATLASSERT(::IsWindow(m_hWnd));
476 #if (_WIN32_WINNT >= 0x0501)
477 return (DWORD)::SendMessage(m_hWnd, LB_GETLISTBOXINFO, 0, 0L);
478 #else // !(_WIN32_WINNT >= 0x0501)
479 return ::GetListBoxInfo(m_hWnd);
480 #endif // !(_WIN32_WINNT >= 0x0501)
481 }
482 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
483
484 // for single-selection listboxes
485 int GetCurSel() const
486 {
487 ATLASSERT(::IsWindow(m_hWnd));
488 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
489 return (int)::SendMessage(m_hWnd, LB_GETCURSEL, 0, 0L);
490 }
491
492 int SetCurSel(int nSelect)
493 {
494 ATLASSERT(::IsWindow(m_hWnd));
495 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
496 return (int)::SendMessage(m_hWnd, LB_SETCURSEL, nSelect, 0L);
497 }
498
499 // for multiple-selection listboxes
500 int GetSel(int nIndex) const // also works for single-selection
501 {
502 ATLASSERT(::IsWindow(m_hWnd));
503 return (int)::SendMessage(m_hWnd, LB_GETSEL, nIndex, 0L);
504 }
505
506 int SetSel(int nIndex, BOOL bSelect = TRUE)
507 {
508 ATLASSERT(::IsWindow(m_hWnd));
509 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
510 return (int)::SendMessage(m_hWnd, LB_SETSEL, bSelect, nIndex);
511 }
512
513 int GetSelCount() const
514 {
515 ATLASSERT(::IsWindow(m_hWnd));
516 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
517 return (int)::SendMessage(m_hWnd, LB_GETSELCOUNT, 0, 0L);
518 }
519
520 int GetSelItems(int nMaxItems, LPINT rgIndex) const
521 {
522 ATLASSERT(::IsWindow(m_hWnd));
523 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
524 return (int)::SendMessage(m_hWnd, LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex);
525 }
526
527 int GetAnchorIndex() const
528 {
529 ATLASSERT(::IsWindow(m_hWnd));
530 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
531 return (int)::SendMessage(m_hWnd, LB_GETANCHORINDEX, 0, 0L);
532 }
533
534 void SetAnchorIndex(int nIndex)
535 {
536 ATLASSERT(::IsWindow(m_hWnd));
537 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
538 ::SendMessage(m_hWnd, LB_SETANCHORINDEX, nIndex, 0L);
539 }
540
541 int GetCaretIndex() const
542 {
543 ATLASSERT(::IsWindow(m_hWnd));
544 return (int)::SendMessage(m_hWnd, LB_GETCARETINDEX, 0, 0);
545 }
546
547 int SetCaretIndex(int nIndex, BOOL bScroll = TRUE)
548 {
549 ATLASSERT(::IsWindow(m_hWnd));
550 return (int)::SendMessage(m_hWnd, LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0));
551 }
552
553 // for listbox items
554 DWORD_PTR GetItemData(int nIndex) const
555 {
556 ATLASSERT(::IsWindow(m_hWnd));
557 return (DWORD_PTR)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L);
558 }
559
560 int SetItemData(int nIndex, DWORD_PTR dwItemData)
561 {
562 ATLASSERT(::IsWindow(m_hWnd));
563 return (int)::SendMessage(m_hWnd, LB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
564 }
565
566 void* GetItemDataPtr(int nIndex) const
567 {
568 ATLASSERT(::IsWindow(m_hWnd));
569 return (void*)::SendMessage(m_hWnd, LB_GETITEMDATA, nIndex, 0L);
570 }
571
572 int SetItemDataPtr(int nIndex, void* pData)
573 {
574 ATLASSERT(::IsWindow(m_hWnd));
575 return SetItemData(nIndex, (DWORD_PTR)pData);
576 }
577
578 int GetItemRect(int nIndex, LPRECT lpRect) const
579 {
580 ATLASSERT(::IsWindow(m_hWnd));
581 return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect);
582 }
583
584 int GetText(int nIndex, LPTSTR lpszBuffer) const
585 {
586 ATLASSERT(::IsWindow(m_hWnd));
587 return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer);
588 }
589
590 #ifndef _ATL_NO_COM
591 #ifdef _OLEAUTO_H_
592 BOOL GetTextBSTR(int nIndex, BSTR& bstrText) const
593 {
594 USES_CONVERSION;
595 ATLASSERT(::IsWindow(m_hWnd));
596 ATLASSERT(bstrText == NULL);
597
598 int nLen = GetTextLen(nIndex);
599 if(nLen == LB_ERR)
600 return FALSE;
601
602 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
603 LPTSTR lpstrText = buff.Allocate(nLen + 1);
604 if(lpstrText == NULL)
605 return FALSE;
606
607 if(GetText(nIndex, lpstrText) == LB_ERR)
608 return FALSE;
609
610 bstrText = ::SysAllocString(T2OLE(lpstrText));
611 return (bstrText != NULL) ? TRUE : FALSE;
612 }
613 #endif // _OLEAUTO_H_
614 #endif // !_ATL_NO_COM
615
616 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
617 int GetText(int nIndex, _CSTRING_NS::CString& strText) const
618 {
619 ATLASSERT(::IsWindow(m_hWnd));
620 int cchLen = GetTextLen(nIndex);
621 if(cchLen == LB_ERR)
622 return LB_ERR;
623 int nRet = LB_ERR;
624 LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
625 if(lpstr != NULL)
626 {
627 nRet = GetText(nIndex, lpstr);
628 strText.ReleaseBuffer();
629 }
630 return nRet;
631 }
632 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
633
634 int GetTextLen(int nIndex) const
635 {
636 ATLASSERT(::IsWindow(m_hWnd));
637 return (int)::SendMessage(m_hWnd, LB_GETTEXTLEN, nIndex, 0L);
638 }
639
640 int GetItemHeight(int nIndex) const
641 {
642 ATLASSERT(::IsWindow(m_hWnd));
643 return (int)::SendMessage(m_hWnd, LB_GETITEMHEIGHT, nIndex, 0L);
644 }
645
646 int SetItemHeight(int nIndex, UINT cyItemHeight)
647 {
648 ATLASSERT(::IsWindow(m_hWnd));
649 return (int)::SendMessage(m_hWnd, LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
650 }
651
652 // Settable only attributes
653 void SetColumnWidth(int cxWidth)
654 {
655 ATLASSERT(::IsWindow(m_hWnd));
656 ::SendMessage(m_hWnd, LB_SETCOLUMNWIDTH, cxWidth, 0L);
657 }
658
659 BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
660 {
661 ATLASSERT(::IsWindow(m_hWnd));
662 ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
663 return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
664 }
665
666 BOOL SetTabStops()
667 {
668 ATLASSERT(::IsWindow(m_hWnd));
669 ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
670 return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 0, 0L);
671 }
672
673 BOOL SetTabStops(const int& cxEachStop) // takes an 'int'
674 {
675 ATLASSERT(::IsWindow(m_hWnd));
676 ATLASSERT((GetStyle() & LBS_USETABSTOPS) != 0);
677 return (BOOL)::SendMessage(m_hWnd, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
678 }
679
680 // Operations
681 int InitStorage(int nItems, UINT nBytes)
682 {
683 ATLASSERT(::IsWindow(m_hWnd));
684 return (int)::SendMessage(m_hWnd, LB_INITSTORAGE, (WPARAM)nItems, nBytes);
685 }
686
687 void ResetContent()
688 {
689 ATLASSERT(::IsWindow(m_hWnd));
690 ::SendMessage(m_hWnd, LB_RESETCONTENT, 0, 0L);
691 }
692
693 UINT ItemFromPoint(POINT pt, BOOL& bOutside) const
694 {
695 ATLASSERT(::IsWindow(m_hWnd));
696 DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
697 bOutside = (BOOL)HIWORD(dw);
698 return (UINT)LOWORD(dw);
699 }
700
701 // manipulating listbox items
702 int AddString(LPCTSTR lpszItem)
703 {
704 ATLASSERT(::IsWindow(m_hWnd));
705 return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem);
706 }
707
708 int DeleteString(UINT nIndex)
709 {
710 ATLASSERT(::IsWindow(m_hWnd));
711 return (int)::SendMessage(m_hWnd, LB_DELETESTRING, nIndex, 0L);
712 }
713
714 int InsertString(int nIndex, LPCTSTR lpszItem)
715 {
716 ATLASSERT(::IsWindow(m_hWnd));
717 return (int)::SendMessage(m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)lpszItem);
718 }
719
720 #ifndef _WIN32_WCE
721 int Dir(UINT attr, LPCTSTR lpszWildCard)
722 {
723 ATLASSERT(::IsWindow(m_hWnd));
724 return (int)::SendMessage(m_hWnd, LB_DIR, attr, (LPARAM)lpszWildCard);
725 }
726
727 int AddFile(LPCTSTR lpstrFileName)
728 {
729 ATLASSERT(::IsWindow(m_hWnd));
730 return (int)::SendMessage(m_hWnd, LB_ADDFILE, 0, (LPARAM)lpstrFileName);
731 }
732 #endif // !_WIN32_WCE
733
734 // selection helpers
735 int FindString(int nStartAfter, LPCTSTR lpszItem) const
736 {
737 ATLASSERT(::IsWindow(m_hWnd));
738 return (int)::SendMessage(m_hWnd, LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem);
739 }
740
741 int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
742 {
743 ATLASSERT(::IsWindow(m_hWnd));
744 return (int)::SendMessage(m_hWnd, LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
745 }
746
747 int SelectString(int nStartAfter, LPCTSTR lpszItem)
748 {
749 ATLASSERT(::IsWindow(m_hWnd));
750 return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem);
751 }
752
753 int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem)
754 {
755 ATLASSERT(::IsWindow(m_hWnd));
756 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) != 0);
757 ATLASSERT(nFirstItem <= nLastItem);
758 return bSelect ? (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nFirstItem, nLastItem) : (int)::SendMessage(m_hWnd, LB_SELITEMRANGEEX, nLastItem, nFirstItem);
759 }
760
761 #ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages
762 DWORD GetInputMode(BOOL bCurrentMode = TRUE)
763 {
764 return SendMessage(LB_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
765 }
766
767 BOOL SetInputMode(DWORD dwMode)
768 {
769 return SendMessage(LB_SETINPUTMODE, 0, (LPARAM)dwMode);
770 }
771 #endif // WIN32_PLATFORM_WFSP
772 };
773
774 typedef CListBoxT<ATL::CWindow> CListBox;
775
776
777 ///////////////////////////////////////////////////////////////////////////////
778 // CComboBox - client side for a Windows COMBOBOX control
779
780 #ifndef WIN32_PLATFORM_WFSP // No COMBOBOX on SmartPhones
781
782 template <class TBase>
783 class CComboBoxT : public TBase
784 {
785 public:
786 // Constructors
787 CComboBoxT(HWND hWnd = NULL) : TBase(hWnd)
788 { }
789
790 CComboBoxT< TBase >& operator =(HWND hWnd)
791 {
792 m_hWnd = hWnd;
793 return *this;
794 }
795
796 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
797 DWORD dwStyle = 0, DWORD dwExStyle = 0,
798 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
799 {
800 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
801 }
802
803 // Attributes
804 static LPCTSTR GetWndClassName()
805 {
806 return _T("COMBOBOX");
807 }
808
809 // for entire combo box
810 int GetCount() const
811 {
812 ATLASSERT(::IsWindow(m_hWnd));
813 return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0L);
814 }
815
816 int GetCurSel() const
817 {
818 ATLASSERT(::IsWindow(m_hWnd));
819 return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0L);
820 }
821
822 int SetCurSel(int nSelect)
823 {
824 ATLASSERT(::IsWindow(m_hWnd));
825 return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0L);
826 }
827
828 LCID GetLocale() const
829 {
830 ATLASSERT(::IsWindow(m_hWnd));
831 return (LCID)::SendMessage(m_hWnd, CB_GETLOCALE, 0, 0L);
832 }
833
834 LCID SetLocale(LCID nNewLocale)
835 {
836 ATLASSERT(::IsWindow(m_hWnd));
837 return (LCID)::SendMessage(m_hWnd, CB_SETLOCALE, (WPARAM)nNewLocale, 0L);
838 }
839
840 int GetTopIndex() const
841 {
842 ATLASSERT(::IsWindow(m_hWnd));
843 return (int)::SendMessage(m_hWnd, CB_GETTOPINDEX, 0, 0L);
844 }
845
846 int SetTopIndex(int nIndex)
847 {
848 ATLASSERT(::IsWindow(m_hWnd));
849 return (int)::SendMessage(m_hWnd, CB_SETTOPINDEX, nIndex, 0L);
850 }
851
852 UINT GetHorizontalExtent() const
853 {
854 ATLASSERT(::IsWindow(m_hWnd));
855 return (UINT)::SendMessage(m_hWnd, CB_GETHORIZONTALEXTENT, 0, 0L);
856 }
857
858 void SetHorizontalExtent(UINT nExtent)
859 {
860 ATLASSERT(::IsWindow(m_hWnd));
861 ::SendMessage(m_hWnd, CB_SETHORIZONTALEXTENT, nExtent, 0L);
862 }
863
864 int GetDroppedWidth() const
865 {
866 ATLASSERT(::IsWindow(m_hWnd));
867 return (int)::SendMessage(m_hWnd, CB_GETDROPPEDWIDTH, 0, 0L);
868 }
869
870 int SetDroppedWidth(UINT nWidth)
871 {
872 ATLASSERT(::IsWindow(m_hWnd));
873 return (int)::SendMessage(m_hWnd, CB_SETDROPPEDWIDTH, nWidth, 0L);
874 }
875
876 #if ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
877 BOOL GetComboBoxInfo(PCOMBOBOXINFO pComboBoxInfo) const
878 {
879 ATLASSERT(::IsWindow(m_hWnd));
880 #if ((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
881 return (BOOL)::SendMessage(m_hWnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)pComboBoxInfo);
882 #else // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
883 return ::GetComboBoxInfo(m_hWnd, pComboBoxInfo);
884 #endif // !((_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
885 }
886 #endif // ((WINVER >= 0x0500) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 420))
887
888 // for edit control
889 DWORD GetEditSel() const
890 {
891 ATLASSERT(::IsWindow(m_hWnd));
892 return (DWORD)::SendMessage(m_hWnd, CB_GETEDITSEL, 0, 0L);
893 }
894
895 BOOL SetEditSel(int nStartChar, int nEndChar)
896 {
897 ATLASSERT(::IsWindow(m_hWnd));
898 return (BOOL)::SendMessage(m_hWnd, CB_SETEDITSEL, 0, MAKELONG(nStartChar, nEndChar));
899 }
900
901 // for combobox item
902 DWORD_PTR GetItemData(int nIndex) const
903 {
904 ATLASSERT(::IsWindow(m_hWnd));
905 return (DWORD_PTR)::SendMessage(m_hWnd, CB_GETITEMDATA, nIndex, 0L);
906 }
907
908 int SetItemData(int nIndex, DWORD_PTR dwItemData)
909 {
910 ATLASSERT(::IsWindow(m_hWnd));
911 return (int)::SendMessage(m_hWnd, CB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
912 }
913
914 void* GetItemDataPtr(int nIndex) const
915 {
916 ATLASSERT(::IsWindow(m_hWnd));
917 return (void*)GetItemData(nIndex);
918 }
919
920 int SetItemDataPtr(int nIndex, void* pData)
921 {
922 ATLASSERT(::IsWindow(m_hWnd));
923 return SetItemData(nIndex, (DWORD_PTR)pData);
924 }
925
926 int GetLBText(int nIndex, LPTSTR lpszText) const
927 {
928 ATLASSERT(::IsWindow(m_hWnd));
929 return (int)::SendMessage(m_hWnd, CB_GETLBTEXT, nIndex, (LPARAM)lpszText);
930 }
931
932 #ifndef _ATL_NO_COM
933 BOOL GetLBTextBSTR(int nIndex, BSTR& bstrText) const
934 {
935 USES_CONVERSION;
936 ATLASSERT(::IsWindow(m_hWnd));
937 ATLASSERT(bstrText == NULL);
938
939 int nLen = GetLBTextLen(nIndex);
940 if(nLen == CB_ERR)
941 return FALSE;
942
943 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
944 LPTSTR lpstrText = buff.Allocate(nLen + 1);
945 if(lpstrText == NULL)
946 return FALSE;
947
948 if(GetLBText(nIndex, lpstrText) == CB_ERR)
949 return FALSE;
950
951 bstrText = ::SysAllocString(T2OLE(lpstrText));
952 return (bstrText != NULL) ? TRUE : FALSE;
953 }
954 #endif // !_ATL_NO_COM
955
956 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
957 int GetLBText(int nIndex, _CSTRING_NS::CString& strText) const
958 {
959 ATLASSERT(::IsWindow(m_hWnd));
960 int cchLen = GetLBTextLen(nIndex);
961 if(cchLen == CB_ERR)
962 return CB_ERR;
963 int nRet = CB_ERR;
964 LPTSTR lpstr = strText.GetBufferSetLength(cchLen);
965 if(lpstr != NULL)
966 {
967 nRet = GetLBText(nIndex, lpstr);
968 strText.ReleaseBuffer();
969 }
970 return nRet;
971 }
972 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
973
974 int GetLBTextLen(int nIndex) const
975 {
976 ATLASSERT(::IsWindow(m_hWnd));
977 return (int)::SendMessage(m_hWnd, CB_GETLBTEXTLEN, nIndex, 0L);
978 }
979
980 int GetItemHeight(int nIndex) const
981 {
982 ATLASSERT(::IsWindow(m_hWnd));
983 return (int)::SendMessage(m_hWnd, CB_GETITEMHEIGHT, nIndex, 0L);
984 }
985
986 int SetItemHeight(int nIndex, UINT cyItemHeight)
987 {
988 ATLASSERT(::IsWindow(m_hWnd));
989 return (int)::SendMessage(m_hWnd, CB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
990 }
991
992 BOOL GetExtendedUI() const
993 {
994 ATLASSERT(::IsWindow(m_hWnd));
995 return (BOOL)::SendMessage(m_hWnd, CB_GETEXTENDEDUI, 0, 0L);
996 }
997
998 int SetExtendedUI(BOOL bExtended = TRUE)
999 {
1000 ATLASSERT(::IsWindow(m_hWnd));
1001 return (int)::SendMessage(m_hWnd, CB_SETEXTENDEDUI, bExtended, 0L);
1002 }
1003
1004 void GetDroppedControlRect(LPRECT lprect) const
1005 {
1006 ATLASSERT(::IsWindow(m_hWnd));
1007 ::SendMessage(m_hWnd, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)lprect);
1008 }
1009
1010 BOOL GetDroppedState() const
1011 {
1012 ATLASSERT(::IsWindow(m_hWnd));
1013 return (BOOL)::SendMessage(m_hWnd, CB_GETDROPPEDSTATE, 0, 0L);
1014 }
1015
1016 #if (_WIN32_WINNT >= 0x0501)
1017 int GetMinVisible() const
1018 {
1019 ATLASSERT(::IsWindow(m_hWnd));
1020 return (int)::SendMessage(m_hWnd, CB_GETMINVISIBLE, 0, 0L);
1021 }
1022
1023 BOOL SetMinVisible(int nMinVisible)
1024 {
1025 ATLASSERT(::IsWindow(m_hWnd));
1026 return (BOOL)::SendMessage(m_hWnd, CB_SETMINVISIBLE, nMinVisible, 0L);
1027 }
1028
1029 // Vista only
1030 BOOL GetCueBannerText(LPWSTR lpwText, int cchText) const
1031 {
1032 #ifndef CB_GETCUEBANNER
1033 const UINT CB_GETCUEBANNER = (CBM_FIRST + 4);
1034 #endif
1035 ATLASSERT(::IsWindow(m_hWnd));
1036 return (BOOL)::SendMessage(m_hWnd, CB_GETCUEBANNER, (WPARAM)lpwText, cchText);
1037 }
1038
1039 // Vista only
1040 BOOL SetCueBannerText(LPCWSTR lpcwText)
1041 {
1042 #ifndef CB_SETCUEBANNER
1043 const UINT CB_SETCUEBANNER = (CBM_FIRST + 3);
1044 #endif
1045 ATLASSERT(::IsWindow(m_hWnd));
1046 return (BOOL)::SendMessage(m_hWnd, CB_SETCUEBANNER, 0, (LPARAM)lpcwText);
1047 }
1048 #endif // (_WIN32_WINNT >= 0x0501)
1049
1050 // Operations
1051 int InitStorage(int nItems, UINT nBytes)
1052 {
1053 ATLASSERT(::IsWindow(m_hWnd));
1054 return (int)::SendMessage(m_hWnd, CB_INITSTORAGE, (WPARAM)nItems, nBytes);
1055 }
1056
1057 void ResetContent()
1058 {
1059 ATLASSERT(::IsWindow(m_hWnd));
1060 ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0L);
1061 }
1062
1063 // for edit control
1064 BOOL LimitText(int nMaxChars)
1065 {
1066 ATLASSERT(::IsWindow(m_hWnd));
1067 return (BOOL)::SendMessage(m_hWnd, CB_LIMITTEXT, nMaxChars, 0L);
1068 }
1069
1070 // for drop-down combo boxes
1071 void ShowDropDown(BOOL bShowIt = TRUE)
1072 {
1073 ATLASSERT(::IsWindow(m_hWnd));
1074 ::SendMessage(m_hWnd, CB_SHOWDROPDOWN, bShowIt, 0L);
1075 }
1076
1077 // manipulating listbox items
1078 int AddString(LPCTSTR lpszString)
1079 {
1080 ATLASSERT(::IsWindow(m_hWnd));
1081 return (int)::SendMessage(m_hWnd, CB_ADDSTRING, 0, (LPARAM)lpszString);
1082 }
1083
1084 int DeleteString(UINT nIndex)
1085 {
1086 ATLASSERT(::IsWindow(m_hWnd));
1087 return (int)::SendMessage(m_hWnd, CB_DELETESTRING, nIndex, 0L);
1088 }
1089
1090 int InsertString(int nIndex, LPCTSTR lpszString)
1091 {
1092 ATLASSERT(::IsWindow(m_hWnd));
1093 return (int)::SendMessage(m_hWnd, CB_INSERTSTRING, nIndex, (LPARAM)lpszString);
1094 }
1095
1096 #ifndef _WIN32_WCE
1097 int Dir(UINT attr, LPCTSTR lpszWildCard)
1098 {
1099 ATLASSERT(::IsWindow(m_hWnd));
1100 return (int)::SendMessage(m_hWnd, CB_DIR, attr, (LPARAM)lpszWildCard);
1101 }
1102 #endif // !_WIN32_WCE
1103
1104 // selection helpers
1105 int FindString(int nStartAfter, LPCTSTR lpszString) const
1106 {
1107 ATLASSERT(::IsWindow(m_hWnd));
1108 return (int)::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, (LPARAM)lpszString);
1109 }
1110
1111 int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
1112 {
1113 ATLASSERT(::IsWindow(m_hWnd));
1114 return (int)::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
1115 }
1116
1117 int SelectString(int nStartAfter, LPCTSTR lpszString)
1118 {
1119 ATLASSERT(::IsWindow(m_hWnd));
1120 return (int)::SendMessage(m_hWnd, CB_SELECTSTRING, nStartAfter, (LPARAM)lpszString);
1121 }
1122
1123 // Clipboard operations
1124 void Clear()
1125 {
1126 ATLASSERT(::IsWindow(m_hWnd));
1127 ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
1128 }
1129
1130 void Copy()
1131 {
1132 ATLASSERT(::IsWindow(m_hWnd));
1133 ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
1134 }
1135
1136 void Cut()
1137 {
1138 ATLASSERT(::IsWindow(m_hWnd));
1139 ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
1140 }
1141
1142 void Paste()
1143 {
1144 ATLASSERT(::IsWindow(m_hWnd));
1145 ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
1146 }
1147 };
1148
1149 typedef CComboBoxT<ATL::CWindow> CComboBox;
1150
1151 #endif // !WIN32_PLATFORM_WFSP
1152
1153 ///////////////////////////////////////////////////////////////////////////////
1154 // CEdit - client side for a Windows EDIT control
1155
1156 template <class TBase>
1157 class CEditT : public TBase
1158 {
1159 public:
1160 // Constructors
1161 CEditT(HWND hWnd = NULL) : TBase(hWnd)
1162 { }
1163
1164 CEditT< TBase >& operator =(HWND hWnd)
1165 {
1166 m_hWnd = hWnd;
1167 return *this;
1168 }
1169
1170 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1171 DWORD dwStyle = 0, DWORD dwExStyle = 0,
1172 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1173 {
1174 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
1175 }
1176
1177 // Attributes
1178 static LPCTSTR GetWndClassName()
1179 {
1180 return _T("EDIT");
1181 }
1182
1183 BOOL CanUndo() const
1184 {
1185 ATLASSERT(::IsWindow(m_hWnd));
1186 return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
1187 }
1188
1189 int GetLineCount() const
1190 {
1191 ATLASSERT(::IsWindow(m_hWnd));
1192 return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L);
1193 }
1194
1195 BOOL GetModify() const
1196 {
1197 ATLASSERT(::IsWindow(m_hWnd));
1198 return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
1199 }
1200
1201 void SetModify(BOOL bModified = TRUE)
1202 {
1203 ATLASSERT(::IsWindow(m_hWnd));
1204 ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L);
1205 }
1206
1207 void GetRect(LPRECT lpRect) const
1208 {
1209 ATLASSERT(::IsWindow(m_hWnd));
1210 ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
1211 }
1212
1213 DWORD GetSel() const
1214 {
1215 ATLASSERT(::IsWindow(m_hWnd));
1216 return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
1217 }
1218
1219 void GetSel(int& nStartChar, int& nEndChar) const
1220 {
1221 ATLASSERT(::IsWindow(m_hWnd));
1222 ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
1223 }
1224
1225 #ifndef _WIN32_WCE
1226 HLOCAL GetHandle() const
1227 {
1228 ATLASSERT(::IsWindow(m_hWnd));
1229 return (HLOCAL)::SendMessage(m_hWnd, EM_GETHANDLE, 0, 0L);
1230 }
1231
1232 void SetHandle(HLOCAL hBuffer)
1233 {
1234 ATLASSERT(::IsWindow(m_hWnd));
1235 ::SendMessage(m_hWnd, EM_SETHANDLE, (WPARAM)hBuffer, 0L);
1236 }
1237 #endif // !_WIN32_WCE
1238
1239 DWORD GetMargins() const
1240 {
1241 ATLASSERT(::IsWindow(m_hWnd));
1242 return (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L);
1243 }
1244
1245 void GetMargins(UINT& nLeft, UINT& nRight) const
1246 {
1247 ATLASSERT(::IsWindow(m_hWnd));
1248 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETMARGINS, 0, 0L);
1249 nLeft = LOWORD(dwRet);
1250 nRight = HIWORD(dwRet);
1251 }
1252
1253 void SetMargins(UINT nLeft, UINT nRight, WORD wFlags = EC_LEFTMARGIN | EC_RIGHTMARGIN)
1254 {
1255 ATLASSERT(::IsWindow(m_hWnd));
1256 ::SendMessage(m_hWnd, EM_SETMARGINS, wFlags, MAKELONG(nLeft, nRight));
1257 }
1258
1259 UINT GetLimitText() const
1260 {
1261 ATLASSERT(::IsWindow(m_hWnd));
1262 return (UINT)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L);
1263 }
1264
1265 void SetLimitText(UINT nMax)
1266 {
1267 ATLASSERT(::IsWindow(m_hWnd));
1268 ::SendMessage(m_hWnd, EM_SETLIMITTEXT, nMax, 0L);
1269 }
1270
1271 POINT PosFromChar(UINT nChar) const
1272 {
1273 ATLASSERT(::IsWindow(m_hWnd));
1274 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_POSFROMCHAR, nChar, 0);
1275 POINT point = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
1276 return point;
1277 }
1278
1279 int CharFromPos(POINT pt, int* pLine = NULL) const
1280 {
1281 ATLASSERT(::IsWindow(m_hWnd));
1282 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
1283 if(pLine != NULL)
1284 *pLine = (int)(short)HIWORD(dwRet);
1285 return (int)(short)LOWORD(dwRet);
1286 }
1287
1288 // NOTE: first word in lpszBuffer must contain the size of the buffer!
1289 int GetLine(int nIndex, LPTSTR lpszBuffer) const
1290 {
1291 ATLASSERT(::IsWindow(m_hWnd));
1292 return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
1293 }
1294
1295 int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
1296 {
1297 ATLASSERT(::IsWindow(m_hWnd));
1298 *(LPWORD)lpszBuffer = (WORD)nMaxLength;
1299 return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
1300 }
1301
1302 TCHAR GetPasswordChar() const
1303 {
1304 ATLASSERT(::IsWindow(m_hWnd));
1305 return (TCHAR)::SendMessage(m_hWnd, EM_GETPASSWORDCHAR, 0, 0L);
1306 }
1307
1308 void SetPasswordChar(TCHAR ch)
1309 {
1310 ATLASSERT(::IsWindow(m_hWnd));
1311 ::SendMessage(m_hWnd, EM_SETPASSWORDCHAR, ch, 0L);
1312 }
1313
1314 #ifndef _WIN32_WCE
1315 EDITWORDBREAKPROC GetWordBreakProc() const
1316 {
1317 ATLASSERT(::IsWindow(m_hWnd));
1318 return (EDITWORDBREAKPROC)::SendMessage(m_hWnd, EM_GETWORDBREAKPROC, 0, 0L);
1319 }
1320
1321 void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
1322 {
1323 ATLASSERT(::IsWindow(m_hWnd));
1324 ::SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
1325 }
1326 #endif // !_WIN32_WCE
1327
1328 int GetFirstVisibleLine() const
1329 {
1330 ATLASSERT(::IsWindow(m_hWnd));
1331 return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
1332 }
1333
1334 #ifndef _WIN32_WCE
1335 int GetThumb() const
1336 {
1337 ATLASSERT(::IsWindow(m_hWnd));
1338 ATLASSERT((GetStyle() & ES_MULTILINE) != 0);
1339 return (int)::SendMessage(m_hWnd, EM_GETTHUMB, 0, 0L);
1340 }
1341 #endif // !_WIN32_WCE
1342
1343 BOOL SetReadOnly(BOOL bReadOnly = TRUE)
1344 {
1345 ATLASSERT(::IsWindow(m_hWnd));
1346 return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
1347 }
1348
1349 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
1350 UINT GetImeStatus(UINT uStatus) const
1351 {
1352 ATLASSERT(::IsWindow(m_hWnd));
1353 return (UINT)::SendMessage(m_hWnd, EM_GETIMESTATUS, uStatus, 0L);
1354 }
1355
1356 UINT SetImeStatus(UINT uStatus, UINT uData)
1357 {
1358 ATLASSERT(::IsWindow(m_hWnd));
1359 return (UINT)::SendMessage(m_hWnd, EM_SETIMESTATUS, uStatus, uData);
1360 }
1361 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
1362
1363 #if (_WIN32_WINNT >= 0x0501)
1364 BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const
1365 {
1366 ATLASSERT(::IsWindow(m_hWnd));
1367 return (BOOL)::SendMessage(m_hWnd, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText);
1368 }
1369
1370 // bKeepWithFocus - Vista only
1371 BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE)
1372 {
1373 ATLASSERT(::IsWindow(m_hWnd));
1374 return (BOOL)::SendMessage(m_hWnd, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText));
1375 }
1376 #endif // (_WIN32_WINNT >= 0x0501)
1377
1378 // Operations
1379 void EmptyUndoBuffer()
1380 {
1381 ATLASSERT(::IsWindow(m_hWnd));
1382 ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
1383 }
1384
1385 BOOL FmtLines(BOOL bAddEOL)
1386 {
1387 ATLASSERT(::IsWindow(m_hWnd));
1388 return (BOOL)::SendMessage(m_hWnd, EM_FMTLINES, bAddEOL, 0L);
1389 }
1390
1391 void LimitText(int nChars = 0)
1392 {
1393 ATLASSERT(::IsWindow(m_hWnd));
1394 ::SendMessage(m_hWnd, EM_LIMITTEXT, nChars, 0L);
1395 }
1396
1397 int LineFromChar(int nIndex = -1) const
1398 {
1399 ATLASSERT(::IsWindow(m_hWnd));
1400 return (int)::SendMessage(m_hWnd, EM_LINEFROMCHAR, nIndex, 0L);
1401 }
1402
1403 int LineIndex(int nLine = -1) const
1404 {
1405 ATLASSERT(::IsWindow(m_hWnd));
1406 return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L);
1407 }
1408
1409 int LineLength(int nLine = -1) const
1410 {
1411 ATLASSERT(::IsWindow(m_hWnd));
1412 return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L);
1413 }
1414
1415 void LineScroll(int nLines, int nChars = 0)
1416 {
1417 ATLASSERT(::IsWindow(m_hWnd));
1418 ::SendMessage(m_hWnd, EM_LINESCROLL, nChars, nLines);
1419 }
1420
1421 void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
1422 {
1423 ATLASSERT(::IsWindow(m_hWnd));
1424 ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
1425 }
1426
1427 void SetRect(LPCRECT lpRect)
1428 {
1429 ATLASSERT(::IsWindow(m_hWnd));
1430 ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
1431 }
1432
1433 void SetRectNP(LPCRECT lpRect)
1434 {
1435 ATLASSERT(::IsWindow(m_hWnd));
1436 ::SendMessage(m_hWnd, EM_SETRECTNP, 0, (LPARAM)lpRect);
1437 }
1438
1439 void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE)
1440 {
1441 ATLASSERT(::IsWindow(m_hWnd));
1442 ::SendMessage(m_hWnd, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
1443 if(!bNoScroll)
1444 ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
1445 }
1446
1447 void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE)
1448 {
1449 ATLASSERT(::IsWindow(m_hWnd));
1450 ::SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar);
1451 if(!bNoScroll)
1452 ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
1453 }
1454
1455 void SetSelAll(BOOL bNoScroll = FALSE)
1456 {
1457 SetSel(0, -1, bNoScroll);
1458 }
1459
1460 void SetSelNone(BOOL bNoScroll = FALSE)
1461 {
1462 SetSel(-1, 0, bNoScroll);
1463 }
1464
1465 BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
1466 {
1467 ATLASSERT(::IsWindow(m_hWnd));
1468 return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
1469 }
1470
1471 BOOL SetTabStops()
1472 {
1473 ATLASSERT(::IsWindow(m_hWnd));
1474 return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L);
1475 }
1476
1477 BOOL SetTabStops(const int& cxEachStop) // takes an 'int'
1478 {
1479 ATLASSERT(::IsWindow(m_hWnd));
1480 return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
1481 }
1482
1483 void ScrollCaret()
1484 {
1485 ATLASSERT(::IsWindow(m_hWnd));
1486 ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
1487 }
1488
1489 int Scroll(int nScrollAction)
1490 {
1491 ATLASSERT(::IsWindow(m_hWnd));
1492 ATLASSERT((GetStyle() & ES_MULTILINE) != 0);
1493 LRESULT lRet = ::SendMessage(m_hWnd, EM_SCROLL, nScrollAction, 0L);
1494 if(!(BOOL)HIWORD(lRet))
1495 return -1; // failed
1496 return (int)(short)LOWORD(lRet);
1497
1498 }
1499
1500 void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
1501 {
1502 SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll);
1503 ReplaceSel(lpstrText, bCanUndo);
1504 }
1505
1506 void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
1507 {
1508 InsertText(GetWindowTextLength(), lpstrText, bNoScroll, bCanUndo);
1509 }
1510
1511 #if (_WIN32_WINNT >= 0x0501)
1512 BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip)
1513 {
1514 ATLASSERT(::IsWindow(m_hWnd));
1515 return (BOOL)::SendMessage(m_hWnd, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip);
1516 }
1517
1518 BOOL HideBalloonTip()
1519 {
1520 ATLASSERT(::IsWindow(m_hWnd));
1521 return (BOOL)::SendMessage(m_hWnd, EM_HIDEBALLOONTIP, 0, 0L);
1522 }
1523 #endif // (_WIN32_WINNT >= 0x0501)
1524
1525 #if (_WIN32_WINNT >= 0x0600)
1526 DWORD GetHilite() const
1527 {
1528 ATLASSERT(::IsWindow(m_hWnd));
1529 return (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L);
1530 }
1531
1532 void GetHilite(int& nStartChar, int& nEndChar) const
1533 {
1534 ATLASSERT(::IsWindow(m_hWnd));
1535 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, EM_GETHILITE, 0, 0L);
1536 nStartChar = (int)(short)LOWORD(dwRet);
1537 nEndChar = (int)(short)HIWORD(dwRet);
1538 }
1539
1540 void SetHilite(int nStartChar, int nEndChar)
1541 {
1542 ATLASSERT(::IsWindow(m_hWnd));
1543 ::SendMessage(m_hWnd, EM_SETHILITE, nStartChar, nEndChar);
1544 }
1545 #endif // (_WIN32_WINNT >= 0x0600)
1546
1547 // Clipboard operations
1548 BOOL Undo()
1549 {
1550 ATLASSERT(::IsWindow(m_hWnd));
1551 return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L);
1552 }
1553
1554 void Clear()
1555 {
1556 ATLASSERT(::IsWindow(m_hWnd));
1557 ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
1558 }
1559
1560 void Copy()
1561 {
1562 ATLASSERT(::IsWindow(m_hWnd));
1563 ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
1564 }
1565
1566 void Cut()
1567 {
1568 ATLASSERT(::IsWindow(m_hWnd));
1569 ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
1570 }
1571
1572 void Paste()
1573 {
1574 ATLASSERT(::IsWindow(m_hWnd));
1575 ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
1576 }
1577
1578 #ifdef WIN32_PLATFORM_WFSP // SmartPhone only messages
1579 DWORD GetExtendedStyle()
1580 {
1581 return SendMessage(EM_GETEXTENDEDSTYLE);
1582 }
1583
1584 DWORD SetExtendedStyle(DWORD dwMask, DWORD dwExStyle)
1585 {
1586 return SendMessage(EM_SETEXTENDEDSTYLE, (WPARAM)dwMask, (LPARAM)dwExStyle);
1587 }
1588
1589 DWORD GetInputMode(BOOL bCurrentMode = TRUE)
1590 {
1591 return SendMessage(EM_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
1592 }
1593
1594 BOOL SetInputMode(DWORD dwMode)
1595 {
1596 return SendMessage(EM_SETINPUTMODE, 0, (LPARAM)dwMode);
1597 }
1598
1599 BOOL SetSymbols(LPCTSTR szSymbols)
1600 {
1601 return SendMessage(EM_SETSYMBOLS, 0, (LPARAM)szSymbols);
1602 }
1603
1604 BOOL ResetSymbols()
1605 {
1606 return SendMessage(EM_SETSYMBOLS);
1607 }
1608 #endif // WIN32_PLATFORM_WFSP
1609 };
1610
1611 typedef CEditT<ATL::CWindow> CEdit;
1612
1613
1614 ///////////////////////////////////////////////////////////////////////////////
1615 // CEditCommands - message handlers for standard EDIT commands
1616
1617 // Chain to CEditCommands message map. Your class must also derive from CEdit.
1618 // Example:
1619 // class CMyEdit : public CWindowImpl<CMyEdit, CEdit>,
1620 // public CEditCommands<CMyEdit>
1621 // {
1622 // public:
1623 // BEGIN_MSG_MAP(CMyEdit)
1624 // // your handlers...
1625 // CHAIN_MSG_MAP_ALT(CEditCommands<CMyEdit>, 1)
1626 // END_MSG_MAP()
1627 // // other stuff...
1628 // };
1629
1630 template <class T>
1631 class CEditCommands
1632 {
1633 public:
1634 BEGIN_MSG_MAP(CEditCommands< T >)
1635 ALT_MSG_MAP(1)
1636 COMMAND_ID_HANDLER(ID_EDIT_CLEAR, OnEditClear)
1637 COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll)
1638 COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy)
1639 COMMAND_ID_HANDLER(ID_EDIT_CUT, OnEditCut)
1640 COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnEditPaste)
1641 COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnEditSelectAll)
1642 COMMAND_ID_HANDLER(ID_EDIT_UNDO, OnEditUndo)
1643 END_MSG_MAP()
1644
1645 LRESULT OnEditClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1646 {
1647 T* pT = static_cast<T*>(this);
1648 pT->Clear();
1649 return 0;
1650 }
1651
1652 LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1653 {
1654 T* pT = static_cast<T*>(this);
1655 pT->SetSel(0, -1);
1656 pT->Clear();
1657 return 0;
1658 }
1659
1660 LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1661 {
1662 T* pT = static_cast<T*>(this);
1663 pT->Copy();
1664 return 0;
1665 }
1666
1667 LRESULT OnEditCut(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1668 {
1669 T* pT = static_cast<T*>(this);
1670 pT->Cut();
1671 return 0;
1672 }
1673
1674 LRESULT OnEditPaste(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1675 {
1676 T* pT = static_cast<T*>(this);
1677 pT->Paste();
1678 return 0;
1679 }
1680
1681 LRESULT OnEditSelectAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1682 {
1683 T* pT = static_cast<T*>(this);
1684 pT->SetSel(0, -1);
1685 return 0;
1686 }
1687
1688 LRESULT OnEditUndo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
1689 {
1690 T* pT = static_cast<T*>(this);
1691 pT->Undo();
1692 return 0;
1693 }
1694
1695 // State (update UI) helpers
1696 BOOL CanCut() const
1697 { return HasSelection(); }
1698
1699 BOOL CanCopy() const
1700 { return HasSelection(); }
1701
1702 BOOL CanClear() const
1703 { return HasSelection(); }
1704
1705 BOOL CanSelectAll() const
1706 { return HasText(); }
1707
1708 BOOL CanFind() const
1709 { return HasText(); }
1710
1711 BOOL CanRepeat() const
1712 { return HasText(); }
1713
1714 BOOL CanReplace() const
1715 { return HasText(); }
1716
1717 BOOL CanClearAll() const
1718 { return HasText(); }
1719
1720 // Implementation
1721 BOOL HasSelection() const
1722 {
1723 const T* pT = static_cast<const T*>(this);
1724 int nMin = 0, nMax = 0;
1725 ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nMin, (LPARAM)&nMax);
1726 return (nMin != nMax);
1727 }
1728
1729 BOOL HasText() const
1730 {
1731 const T* pT = static_cast<const T*>(this);
1732 return (pT->GetWindowTextLength() > 0);
1733 }
1734 };
1735
1736
1737 ///////////////////////////////////////////////////////////////////////////////
1738 // CScrollBar - client side for a Windows SCROLLBAR control
1739
1740 template <class TBase>
1741 class CScrollBarT : public TBase
1742 {
1743 public:
1744 // Constructors
1745 CScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
1746 { }
1747
1748 CScrollBarT< TBase >& operator =(HWND hWnd)
1749 {
1750 m_hWnd = hWnd;
1751 return *this;
1752 }
1753
1754 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1755 DWORD dwStyle = 0, DWORD dwExStyle = 0,
1756 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1757 {
1758 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
1759 }
1760
1761 // Attributes
1762 static LPCTSTR GetWndClassName()
1763 {
1764 return _T("SCROLLBAR");
1765 }
1766
1767 #ifndef _WIN32_WCE
1768 int GetScrollPos() const
1769 {
1770 ATLASSERT(::IsWindow(m_hWnd));
1771 return ::GetScrollPos(m_hWnd, SB_CTL);
1772 }
1773 #endif // !_WIN32_WCE
1774
1775 int SetScrollPos(int nPos, BOOL bRedraw = TRUE)
1776 {
1777 ATLASSERT(::IsWindow(m_hWnd));
1778 return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw);
1779 }
1780
1781 #ifndef _WIN32_WCE
1782 void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const
1783 {
1784 ATLASSERT(::IsWindow(m_hWnd));
1785 ::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos);
1786 }
1787 #endif // !_WIN32_WCE
1788
1789 void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
1790 {
1791 ATLASSERT(::IsWindow(m_hWnd));
1792 ::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw);
1793 }
1794
1795 BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo) const
1796 {
1797 ATLASSERT(::IsWindow(m_hWnd));
1798 return ::GetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo);
1799 }
1800
1801 int SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1802 {
1803 ATLASSERT(::IsWindow(m_hWnd));
1804 return ::SetScrollInfo(m_hWnd, SB_CTL, lpScrollInfo, bRedraw);
1805 }
1806
1807 #ifndef _WIN32_WCE
1808 int GetScrollLimit() const
1809 {
1810 SCROLLINFO info = { sizeof(SCROLLINFO), SIF_RANGE | SIF_PAGE };
1811 ::GetScrollInfo(m_hWnd, SB_CTL, &info);
1812 if(info.nPage > 1)
1813 info.nMax -= info.nPage - 1;
1814
1815 return info.nMax;
1816 }
1817
1818 #if (WINVER >= 0x0500)
1819 BOOL GetScrollBarInfo(PSCROLLBARINFO pScrollBarInfo) const
1820 {
1821 ATLASSERT(::IsWindow(m_hWnd));
1822 #if (_WIN32_WINNT >= 0x0501)
1823 return (BOOL)::SendMessage(m_hWnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)pScrollBarInfo);
1824 #else // !(_WIN32_WINNT >= 0x0501)
1825 return ::GetScrollBarInfo(m_hWnd, OBJID_CLIENT, pScrollBarInfo);
1826 #endif // !(_WIN32_WINNT >= 0x0501)
1827 }
1828 #endif // (WINVER >= 0x0500)
1829
1830 // Operations
1831 void ShowScrollBar(BOOL bShow = TRUE)
1832 {
1833 ATLASSERT(::IsWindow(m_hWnd));
1834 ::ShowScrollBar(m_hWnd, SB_CTL, bShow);
1835 }
1836
1837 BOOL EnableScrollBar(UINT nArrowFlags = ESB_ENABLE_BOTH)
1838 {
1839 ATLASSERT(::IsWindow(m_hWnd));
1840 return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags);
1841 }
1842 #endif // !_WIN32_WCE
1843 };
1844
1845 typedef CScrollBarT<ATL::CWindow> CScrollBar;
1846
1847
1848 // --- Windows Common Controls ---
1849
1850 ///////////////////////////////////////////////////////////////////////////////
1851 // CImageList
1852
1853 // forward declarations
1854 template <bool t_bManaged> class CImageListT;
1855 typedef CImageListT<false> CImageList;
1856 typedef CImageListT<true> CImageListManaged;
1857
1858
1859 template <bool t_bManaged>
1860 class CImageListT
1861 {
1862 public:
1863 // Data members
1864 HIMAGELIST m_hImageList;
1865
1866 // Constructor/destructor/operators
1867 CImageListT(HIMAGELIST hImageList = NULL) : m_hImageList(hImageList)
1868 { }
1869
1870 ~CImageListT()
1871 {
1872 if(t_bManaged && (m_hImageList != NULL))
1873 Destroy();
1874 }
1875
1876 CImageListT<t_bManaged>& operator =(HIMAGELIST hImageList)
1877 {
1878 Attach(hImageList);
1879 return *this;
1880 }
1881
1882 void Attach(HIMAGELIST hImageList)
1883 {
1884 if(t_bManaged && (m_hImageList != NULL) && (m_hImageList != hImageList))
1885 ImageList_Destroy(m_hImageList);
1886 m_hImageList = hImageList;
1887 }
1888
1889 HIMAGELIST Detach()
1890 {
1891 HIMAGELIST hImageList = m_hImageList;
1892 m_hImageList = NULL;
1893 return hImageList;
1894 }
1895
1896 operator HIMAGELIST() const { return m_hImageList; }
1897
1898 bool IsNull() const { return (m_hImageList == NULL); }
1899
1900 // Attributes
1901 int GetImageCount() const
1902 {
1903 ATLASSERT(m_hImageList != NULL);
1904 return ImageList_GetImageCount(m_hImageList);
1905 }
1906
1907 COLORREF GetBkColor() const
1908 {
1909 ATLASSERT(m_hImageList != NULL);
1910 return ImageList_GetBkColor(m_hImageList);
1911 }
1912
1913 COLORREF SetBkColor(COLORREF cr)
1914 {
1915 ATLASSERT(m_hImageList != NULL);
1916 return ImageList_SetBkColor(m_hImageList, cr);
1917 }
1918
1919 BOOL GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const
1920 {
1921 ATLASSERT(m_hImageList != NULL);
1922 return ImageList_GetImageInfo(m_hImageList, nImage, pImageInfo);
1923 }
1924
1925 HICON GetIcon(int nIndex, UINT uFlags = ILD_NORMAL) const
1926 {
1927 ATLASSERT(m_hImageList != NULL);
1928 return ImageList_GetIcon(m_hImageList, nIndex, uFlags);
1929 }
1930
1931 BOOL GetIconSize(int& cx, int& cy) const
1932 {
1933 ATLASSERT(m_hImageList != NULL);
1934 return ImageList_GetIconSize(m_hImageList, &cx, &cy);
1935 }
1936
1937 BOOL GetIconSize(SIZE& size) const
1938 {
1939 ATLASSERT(m_hImageList != NULL);
1940 return ImageList_GetIconSize(m_hImageList, (int*)&size.cx, (int*)&size.cy);
1941 }
1942
1943 BOOL SetIconSize(int cx, int cy)
1944 {
1945 ATLASSERT(m_hImageList != NULL);
1946 return ImageList_SetIconSize(m_hImageList, cx, cy);
1947 }
1948
1949 BOOL SetIconSize(SIZE size)
1950 {
1951 ATLASSERT(m_hImageList != NULL);
1952 return ImageList_SetIconSize(m_hImageList, size.cx, size.cy);
1953 }
1954
1955 BOOL SetImageCount(UINT uNewCount)
1956 {
1957 ATLASSERT(m_hImageList != NULL);
1958 return ImageList_SetImageCount(m_hImageList, uNewCount);
1959 }
1960
1961 BOOL SetOverlayImage(int nImage, int nOverlay)
1962 {
1963 ATLASSERT(m_hImageList != NULL);
1964 return ImageList_SetOverlayImage(m_hImageList, nImage, nOverlay);
1965 }
1966
1967 // Operations
1968 BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow)
1969 {
1970 ATLASSERT(m_hImageList == NULL);
1971 m_hImageList = ImageList_Create(cx, cy, nFlags, nInitial, nGrow);
1972 return (m_hImageList != NULL) ? TRUE : FALSE;
1973 }
1974
1975 BOOL Create(ATL::_U_STRINGorID bitmap, int cx, int nGrow, COLORREF crMask)
1976 {
1977 ATLASSERT(m_hImageList == NULL);
1978 m_hImageList = ImageList_LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, cx, nGrow, crMask);
1979 return (m_hImageList != NULL) ? TRUE : FALSE;
1980 }
1981
1982 BOOL CreateFromImage(ATL::_U_STRINGorID image, int cx, int nGrow, COLORREF crMask, UINT uType, UINT uFlags = LR_DEFAULTCOLOR | LR_DEFAULTSIZE)
1983 {
1984 ATLASSERT(m_hImageList == NULL);
1985 m_hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, cx, nGrow, crMask, uType, uFlags);
1986 return (m_hImageList != NULL) ? TRUE : FALSE;
1987 }
1988
1989 BOOL Merge(HIMAGELIST hImageList1, int nImage1, HIMAGELIST hImageList2, int nImage2, int dx, int dy)
1990 {
1991 ATLASSERT(m_hImageList == NULL);
1992 m_hImageList = ImageList_Merge(hImageList1, nImage1, hImageList2, nImage2, dx, dy);
1993 return (m_hImageList != NULL) ? TRUE : FALSE;
1994 }
1995
1996 #ifndef _WIN32_WCE
1997 #ifdef __IStream_INTERFACE_DEFINED__
1998 BOOL CreateFromStream(LPSTREAM lpStream)
1999 {
2000 ATLASSERT(m_hImageList == NULL);
2001 m_hImageList = ImageList_Read(lpStream);
2002 return (m_hImageList != NULL) ? TRUE : FALSE;
2003 }
2004 #endif // __IStream_INTERFACE_DEFINED__
2005 #endif // !_WIN32_WCE
2006
2007 BOOL Destroy()
2008 {
2009 if (m_hImageList == NULL)
2010 return FALSE;
2011 BOOL bRet = ImageList_Destroy(m_hImageList);
2012 if(bRet)
2013 m_hImageList = NULL;
2014 return bRet;
2015 }
2016
2017 int Add(HBITMAP hBitmap, HBITMAP hBitmapMask = NULL)
2018 {
2019 ATLASSERT(m_hImageList != NULL);
2020 return ImageList_Add(m_hImageList, hBitmap, hBitmapMask);
2021 }
2022
2023 int Add(HBITMAP hBitmap, COLORREF crMask)
2024 {
2025 ATLASSERT(m_hImageList != NULL);
2026 return ImageList_AddMasked(m_hImageList, hBitmap, crMask);
2027 }
2028
2029 BOOL Remove(int nImage)
2030 {
2031 ATLASSERT(m_hImageList != NULL);
2032 return ImageList_Remove(m_hImageList, nImage);
2033 }
2034
2035 BOOL RemoveAll()
2036 {
2037 ATLASSERT(m_hImageList != NULL);
2038 return ImageList_RemoveAll(m_hImageList);
2039 }
2040
2041 BOOL Replace(int nImage, HBITMAP hBitmap, HBITMAP hBitmapMask)
2042 {
2043 ATLASSERT(m_hImageList != NULL);
2044 return ImageList_Replace(m_hImageList, nImage, hBitmap, hBitmapMask);
2045 }
2046
2047 int AddIcon(HICON hIcon)
2048 {
2049 ATLASSERT(m_hImageList != NULL);
2050 return ImageList_AddIcon(m_hImageList, hIcon);
2051 }
2052
2053 int ReplaceIcon(int nImage, HICON hIcon)
2054 {
2055 ATLASSERT(m_hImageList != NULL);
2056 return ImageList_ReplaceIcon(m_hImageList, nImage, hIcon);
2057 }
2058
2059 HICON ExtractIcon(int nImage)
2060 {
2061 ATLASSERT(m_hImageList != NULL);
2062 return ImageList_ExtractIcon(NULL, m_hImageList, nImage);
2063 }
2064
2065 BOOL Draw(HDC hDC, int nImage, int x, int y, UINT nStyle)
2066 {
2067 ATLASSERT(m_hImageList != NULL);
2068 ATLASSERT(hDC != NULL);
2069 return ImageList_Draw(m_hImageList, nImage, hDC, x, y, nStyle);
2070 }
2071
2072 BOOL Draw(HDC hDC, int nImage, POINT pt, UINT nStyle)
2073 {
2074 ATLASSERT(m_hImageList != NULL);
2075 ATLASSERT(hDC != NULL);
2076 return ImageList_Draw(m_hImageList, nImage, hDC, pt.x, pt.y, nStyle);
2077 }
2078
2079 BOOL DrawEx(int nImage, HDC hDC, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
2080 {
2081 ATLASSERT(m_hImageList != NULL);
2082 ATLASSERT(hDC != NULL);
2083 return ImageList_DrawEx(m_hImageList, nImage, hDC, x, y, dx, dy, rgbBk, rgbFg, fStyle);
2084 }
2085
2086 BOOL DrawEx(int nImage, HDC hDC, RECT& rect, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle)
2087 {
2088 ATLASSERT(m_hImageList != NULL);
2089 ATLASSERT(hDC != NULL);
2090 return ImageList_DrawEx(m_hImageList, nImage, hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rgbBk, rgbFg, fStyle);
2091 }
2092
2093 static BOOL DrawIndirect(IMAGELISTDRAWPARAMS* pimldp)
2094 {
2095 return ImageList_DrawIndirect(pimldp);
2096 }
2097
2098 BOOL Copy(int nSrc, int nDst, UINT uFlags = ILCF_MOVE)
2099 {
2100 ATLASSERT(m_hImageList != NULL);
2101 return ImageList_Copy(m_hImageList, nDst, m_hImageList, nSrc, uFlags);
2102 }
2103
2104 #ifdef __IStream_INTERFACE_DEFINED__
2105 #ifndef _WIN32_WCE
2106 static HIMAGELIST Read(LPSTREAM lpStream)
2107 {
2108 return ImageList_Read(lpStream);
2109 }
2110
2111 BOOL Write(LPSTREAM lpStream)
2112 {
2113 ATLASSERT(m_hImageList != NULL);
2114 return ImageList_Write(m_hImageList, lpStream);
2115 }
2116 #endif // !_WIN32_WCE
2117
2118 #if (_WIN32_WINNT >= 0x0501)
2119 static HRESULT ReadEx(DWORD dwFlags, LPSTREAM lpStream, REFIID riid, PVOID* ppv)
2120 {
2121 return ImageList_ReadEx(dwFlags, lpStream, riid, ppv);
2122 }
2123
2124 HRESULT WriteEx(DWORD dwFlags, LPSTREAM lpStream)
2125 {
2126 ATLASSERT(m_hImageList != NULL);
2127 return ImageList_WriteEx(m_hImageList, dwFlags, lpStream);
2128 }
2129 #endif // (_WIN32_WINNT >= 0x0501)
2130 #endif // __IStream_INTERFACE_DEFINED__
2131
2132 // Drag operations
2133 BOOL BeginDrag(int nImage, POINT ptHotSpot)
2134 {
2135 ATLASSERT(m_hImageList != NULL);
2136 return ImageList_BeginDrag(m_hImageList, nImage, ptHotSpot.x, ptHotSpot.y);
2137 }
2138
2139 BOOL BeginDrag(int nImage, int xHotSpot, int yHotSpot)
2140 {
2141 ATLASSERT(m_hImageList != NULL);
2142 return ImageList_BeginDrag(m_hImageList, nImage, xHotSpot, yHotSpot);
2143 }
2144
2145 static void EndDrag()
2146 {
2147 ImageList_EndDrag();
2148 }
2149
2150 static BOOL DragMove(POINT pt)
2151 {
2152 return ImageList_DragMove(pt.x, pt.y);
2153 }
2154
2155 static BOOL DragMove(int x, int y)
2156 {
2157 return ImageList_DragMove(x, y);
2158 }
2159
2160 BOOL SetDragCursorImage(int nDrag, POINT ptHotSpot)
2161 {
2162 ATLASSERT(m_hImageList != NULL);
2163 return ImageList_SetDragCursorImage(m_hImageList, nDrag, ptHotSpot.x, ptHotSpot.y);
2164 }
2165
2166 BOOL SetDragCursorImage(int nDrag, int xHotSpot, int yHotSpot)
2167 {
2168 ATLASSERT(m_hImageList != NULL);
2169 return ImageList_SetDragCursorImage(m_hImageList, nDrag, xHotSpot, yHotSpot);
2170 }
2171
2172 static BOOL DragShowNolock(BOOL bShow = TRUE)
2173 {
2174 return ImageList_DragShowNolock(bShow);
2175 }
2176
2177 static CImageList GetDragImage(LPPOINT lpPoint, LPPOINT lpPointHotSpot)
2178 {
2179 return CImageList(ImageList_GetDragImage(lpPoint, lpPointHotSpot));
2180 }
2181
2182 static BOOL DragEnter(HWND hWnd, POINT point)
2183 {
2184 return ImageList_DragEnter(hWnd, point.x, point.y);
2185 }
2186
2187 static BOOL DragEnter(HWND hWnd, int x, int y)
2188 {
2189 return ImageList_DragEnter(hWnd, x, y);
2190 }
2191
2192 static BOOL DragLeave(HWND hWnd)
2193 {
2194 return ImageList_DragLeave(hWnd);
2195 }
2196
2197 #if (_WIN32_IE >= 0x0400)
2198 CImageList Duplicate() const
2199 {
2200 ATLASSERT(m_hImageList != NULL);
2201 return CImageList(ImageList_Duplicate(m_hImageList));
2202 }
2203
2204 static CImageList Duplicate(HIMAGELIST hImageList)
2205 {
2206 ATLASSERT(hImageList != NULL);
2207 return CImageList(ImageList_Duplicate(hImageList));
2208 }
2209 #endif // (_WIN32_IE >= 0x0400)
2210 };
2211
2212
2213 ///////////////////////////////////////////////////////////////////////////////
2214 // CToolTipCtrl
2215
2216 #ifndef _WIN32_WCE
2217
2218 class CToolInfo : public TOOLINFO
2219 {
2220 public:
2221 CToolInfo(UINT nFlags, HWND hWnd, UINT_PTR nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
2222 {
2223 Init(nFlags, hWnd, nIDTool, lpRect, lpstrText, lUserParam);
2224 }
2225
2226 operator LPTOOLINFO() { return this; }
2227
2228 operator LPARAM() { return (LPARAM)this; }
2229
2230 void Init(UINT nFlags, HWND hWnd, UINT_PTR nIDTool = 0, LPRECT lpRect = NULL, LPTSTR lpstrText = LPSTR_TEXTCALLBACK, LPARAM lUserParam = NULL)
2231 {
2232 ATLASSERT(::IsWindow(hWnd));
2233 memset(this, 0, sizeof(TOOLINFO));
2234 cbSize = RunTimeHelper::SizeOf_TOOLINFO();
2235 uFlags = nFlags;
2236 if(nIDTool == 0)
2237 {
2238 hwnd = ::GetParent(hWnd);
2239 uFlags |= TTF_IDISHWND;
2240 uId = (UINT_PTR)hWnd;
2241 }
2242 else
2243 {
2244 hwnd = hWnd;
2245 uId = nIDTool;
2246 }
2247 if(lpRect != NULL)
2248 rect = *lpRect;
2249 hinst = ModuleHelper::GetResourceInstance();
2250 lpszText = lpstrText;
2251 lParam = lUserParam;
2252 }
2253 };
2254
2255 template <class TBase>
2256 class CToolTipCtrlT : public TBase
2257 {
2258 public:
2259 // Constructors
2260 CToolTipCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2261 { }
2262
2263 CToolTipCtrlT< TBase >& operator =(HWND hWnd)
2264 {
2265 m_hWnd = hWnd;
2266 return *this;
2267 }
2268
2269 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2270 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2271 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2272 {
2273 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2274 }
2275
2276 // Attributes
2277 static LPCTSTR GetWndClassName()
2278 {
2279 return TOOLTIPS_CLASS;
2280 }
2281
2282 void GetText(LPTOOLINFO lpToolInfo) const
2283 {
2284 ATLASSERT(::IsWindow(m_hWnd));
2285 ::SendMessage(m_hWnd, TTM_GETTEXT, 0, (LPARAM)&lpToolInfo);
2286 }
2287
2288 void GetText(LPTSTR lpstrText, HWND hWnd, UINT_PTR nIDTool = 0) const
2289 {
2290 ATLASSERT(::IsWindow(m_hWnd));
2291 ATLASSERT(hWnd != NULL);
2292 CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
2293 ::SendMessage(m_hWnd, TTM_GETTEXT, 0, ti);
2294 }
2295
2296 BOOL GetToolInfo(LPTOOLINFO lpToolInfo) const
2297 {
2298 ATLASSERT(::IsWindow(m_hWnd));
2299 return (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)lpToolInfo);
2300 }
2301
2302 BOOL GetToolInfo(HWND hWnd, UINT_PTR nIDTool, UINT* puFlags, LPRECT lpRect, LPTSTR lpstrText) const
2303 {
2304 ATLASSERT(::IsWindow(m_hWnd));
2305 ATLASSERT(hWnd != NULL);
2306 ATLASSERT(puFlags != NULL);
2307 ATLASSERT(lpRect != NULL);
2308 CToolInfo ti(0, hWnd, nIDTool, NULL, lpstrText);
2309 BOOL bRet = (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, ti);
2310 if(bRet != FALSE)
2311 {
2312 *puFlags = ti.uFlags;
2313 *lpRect = ti.rect;
2314 }
2315 return bRet;
2316 }
2317
2318 void SetToolInfo(LPTOOLINFO lpToolInfo)
2319 {
2320 ATLASSERT(::IsWindow(m_hWnd));
2321 ::SendMessage(m_hWnd, TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo);
2322 }
2323
2324 void SetToolRect(LPTOOLINFO lpToolInfo)
2325 {
2326 ATLASSERT(::IsWindow(m_hWnd));
2327 ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)lpToolInfo);
2328 }
2329
2330 void SetToolRect(HWND hWnd, UINT_PTR nIDTool, LPCRECT lpRect)
2331 {
2332 ATLASSERT(::IsWindow(m_hWnd));
2333 ATLASSERT(hWnd != NULL);
2334 ATLASSERT(nIDTool != 0);
2335
2336 CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRect, NULL);
2337 ::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, ti);
2338 }
2339
2340 int GetToolCount() const
2341 {
2342 ATLASSERT(::IsWindow(m_hWnd));
2343 return (int)::SendMessage(m_hWnd, TTM_GETTOOLCOUNT, 0, 0L);
2344 }
2345
2346 int GetDelayTime(DWORD dwType) const
2347 {
2348 ATLASSERT(::IsWindow(m_hWnd));
2349 return (int)::SendMessage(m_hWnd, TTM_GETDELAYTIME, dwType, 0L);
2350 }
2351
2352 void SetDelayTime(DWORD dwType, int nTime)
2353 {
2354 ATLASSERT(::IsWindow(m_hWnd));
2355 ::SendMessage(m_hWnd, TTM_SETDELAYTIME, dwType, MAKELPARAM(nTime, 0));
2356 }
2357
2358 void GetMargin(LPRECT lpRect) const
2359 {
2360 ATLASSERT(::IsWindow(m_hWnd));
2361 ::SendMessage(m_hWnd, TTM_GETMARGIN, 0, (LPARAM)lpRect);
2362 }
2363
2364 void SetMargin(LPRECT lpRect)
2365 {
2366 ATLASSERT(::IsWindow(m_hWnd));
2367 ::SendMessage(m_hWnd, TTM_SETMARGIN, 0, (LPARAM)lpRect);
2368 }
2369
2370 int GetMaxTipWidth() const
2371 {
2372 ATLASSERT(::IsWindow(m_hWnd));
2373 return (int)::SendMessage(m_hWnd, TTM_GETMAXTIPWIDTH, 0, 0L);
2374 }
2375
2376 int SetMaxTipWidth(int nWidth)
2377 {
2378 ATLASSERT(::IsWindow(m_hWnd));
2379 return (int)::SendMessage(m_hWnd, TTM_SETMAXTIPWIDTH, 0, nWidth);
2380 }
2381
2382 COLORREF GetTipBkColor() const
2383 {
2384 ATLASSERT(::IsWindow(m_hWnd));
2385 return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPBKCOLOR, 0, 0L);
2386 }
2387
2388 void SetTipBkColor(COLORREF clr)
2389 {
2390 ATLASSERT(::IsWindow(m_hWnd));
2391 ::SendMessage(m_hWnd, TTM_SETTIPBKCOLOR, (WPARAM)clr, 0L);
2392 }
2393
2394 COLORREF GetTipTextColor() const
2395 {
2396 ATLASSERT(::IsWindow(m_hWnd));
2397 return (COLORREF)::SendMessage(m_hWnd, TTM_GETTIPTEXTCOLOR, 0, 0L);
2398 }
2399
2400 void SetTipTextColor(COLORREF clr)
2401 {
2402 ATLASSERT(::IsWindow(m_hWnd));
2403 ::SendMessage(m_hWnd, TTM_SETTIPTEXTCOLOR, (WPARAM)clr, 0L);
2404 }
2405
2406 BOOL GetCurrentTool(LPTOOLINFO lpToolInfo) const
2407 {
2408 ATLASSERT(::IsWindow(m_hWnd));
2409 return (BOOL)::SendMessage(m_hWnd, TTM_GETCURRENTTOOL, 0, (LPARAM)lpToolInfo);
2410 }
2411
2412 #if (_WIN32_IE >= 0x0500)
2413 SIZE GetBubbleSize(LPTOOLINFO lpToolInfo) const
2414 {
2415 ATLASSERT(::IsWindow(m_hWnd));
2416 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TTM_GETBUBBLESIZE, 0, (LPARAM)lpToolInfo);
2417 SIZE size = { GET_X_LPARAM(dwRet), GET_Y_LPARAM(dwRet) };
2418 return size;
2419 }
2420
2421 BOOL SetTitle(UINT_PTR uIcon, LPCTSTR lpstrTitle)
2422 {
2423 ATLASSERT(::IsWindow(m_hWnd));
2424 return (BOOL)::SendMessage(m_hWnd, TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle);
2425 }
2426
2427 BOOL SetTitle(HICON hIcon, LPCTSTR lpstrTitle)
2428 {
2429 ATLASSERT(::IsWindow(m_hWnd));
2430 return (BOOL)::SendMessage(m_hWnd, TTM_SETTITLE, (WPARAM)hIcon, (LPARAM)lpstrTitle);
2431 }
2432 #endif // (_WIN32_IE >= 0x0500)
2433
2434 #if (_WIN32_WINNT >= 0x0501)
2435 void GetTitle(PTTGETTITLE pTTGetTitle) const
2436 {
2437 ATLASSERT(::IsWindow(m_hWnd));
2438 ::SendMessage(m_hWnd, TTM_GETTITLE, 0, (LPARAM)pTTGetTitle);
2439 }
2440
2441 void SetWindowTheme(LPCWSTR lpstrTheme)
2442 {
2443 ATLASSERT(::IsWindow(m_hWnd));
2444 ::SendMessage(m_hWnd, TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
2445 }
2446 #endif // (_WIN32_WINNT >= 0x0501)
2447
2448 // Operations
2449 void Activate(BOOL bActivate)
2450 {
2451 ATLASSERT(::IsWindow(m_hWnd));
2452 ::SendMessage(m_hWnd, TTM_ACTIVATE, bActivate, 0L);
2453 }
2454
2455 BOOL AddTool(LPTOOLINFO lpToolInfo)
2456 {
2457 ATLASSERT(::IsWindow(m_hWnd));
2458 return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)lpToolInfo);
2459 }
2460
2461 BOOL AddTool(HWND hWnd, ATL::_U_STRINGorID text = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT_PTR nIDTool = 0)
2462 {
2463 ATLASSERT(::IsWindow(m_hWnd));
2464 ATLASSERT(hWnd != NULL);
2465 // the toolrect and toolid must both be zero or both valid
2466 ATLASSERT((lpRectTool != NULL && nIDTool != 0) || (lpRectTool == NULL && nIDTool == 0));
2467
2468 CToolInfo ti(0, hWnd, nIDTool, (LPRECT)lpRectTool, (LPTSTR)text.m_lpstr);
2469 return (BOOL)::SendMessage(m_hWnd, TTM_ADDTOOL, 0, ti);
2470 }
2471
2472 void DelTool(LPTOOLINFO lpToolInfo)
2473 {
2474 ATLASSERT(::IsWindow(m_hWnd));
2475 ::SendMessage(m_hWnd, TTM_DELTOOL, 0, (LPARAM)lpToolInfo);
2476 }
2477
2478 void DelTool(HWND hWnd, UINT_PTR nIDTool = 0)
2479 {
2480 ATLASSERT(::IsWindow(m_hWnd));
2481 ATLASSERT(hWnd != NULL);
2482
2483 CToolInfo ti(0, hWnd, nIDTool, NULL, NULL);
2484 ::SendMessage(m_hWnd, TTM_DELTOOL, 0, ti);
2485 }
2486
2487 BOOL HitTest(LPTTHITTESTINFO lpHitTestInfo) const
2488 {
2489 ATLASSERT(::IsWindow(m_hWnd));
2490 return (BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)lpHitTestInfo);
2491 }
2492
2493 BOOL HitTest(HWND hWnd, POINT pt, LPTOOLINFO lpToolInfo) const
2494 {
2495 ATLASSERT(::IsWindow(m_hWnd));
2496 ATLASSERT(hWnd != NULL);
2497 ATLASSERT(lpToolInfo != NULL);
2498
2499 TTHITTESTINFO hti = { 0 };
2500 hti.ti.cbSize = RunTimeHelper::SizeOf_TOOLINFO();
2501 hti.hwnd = hWnd;
2502 hti.pt.x = pt.x;
2503 hti.pt.y = pt.y;
2504 if((BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti) != FALSE)
2505 {
2506 *lpToolInfo = hti.ti;
2507 return TRUE;
2508 }
2509 return FALSE;
2510 }
2511
2512 void RelayEvent(LPMSG lpMsg)
2513 {
2514 ATLASSERT(::IsWindow(m_hWnd));
2515 ::SendMessage(m_hWnd, TTM_RELAYEVENT, 0, (LPARAM)lpMsg);
2516 }
2517
2518 void UpdateTipText(LPTOOLINFO lpToolInfo)
2519 {
2520 ATLASSERT(::IsWindow(m_hWnd));
2521 ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)lpToolInfo);
2522 }
2523
2524 void UpdateTipText(ATL::_U_STRINGorID text, HWND hWnd, UINT_PTR nIDTool = 0)
2525 {
2526 ATLASSERT(::IsWindow(m_hWnd));
2527 ATLASSERT(hWnd != NULL);
2528
2529 CToolInfo ti(0, hWnd, nIDTool, NULL, (LPTSTR)text.m_lpstr);
2530 ::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, ti);
2531 }
2532
2533 BOOL EnumTools(UINT_PTR nTool, LPTOOLINFO lpToolInfo) const
2534 {
2535 ATLASSERT(::IsWindow(m_hWnd));
2536 return (BOOL)::SendMessage(m_hWnd, TTM_ENUMTOOLS, nTool, (LPARAM)lpToolInfo);
2537 }
2538
2539 void Pop()
2540 {
2541 ATLASSERT(::IsWindow(m_hWnd));
2542 ::SendMessage(m_hWnd, TTM_POP, 0, 0L);
2543 }
2544
2545 void TrackActivate(LPTOOLINFO lpToolInfo, BOOL bActivate)
2546 {
2547 ATLASSERT(::IsWindow(m_hWnd));
2548 ::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, (LPARAM)lpToolInfo);
2549 }
2550
2551 void TrackActivate(HWND hWnd, UINT_PTR nIDTool, BOOL bActivate)
2552 {
2553 ATLASSERT(::IsWindow(m_hWnd));
2554 ATLASSERT(hWnd != NULL);
2555
2556 CToolInfo ti(0, hWnd, nIDTool);
2557 ::SendMessage(m_hWnd, TTM_TRACKACTIVATE, bActivate, ti);
2558 }
2559
2560 void TrackPosition(int xPos, int yPos)
2561 {
2562 ATLASSERT(::IsWindow(m_hWnd));
2563 ::SendMessage(m_hWnd, TTM_TRACKPOSITION, 0, MAKELPARAM(xPos, yPos));
2564 }
2565
2566 #if (_WIN32_IE >= 0x0400)
2567 void Update()
2568 {
2569 ATLASSERT(::IsWindow(m_hWnd));
2570 ::SendMessage(m_hWnd, TTM_UPDATE, 0, 0L);
2571 }
2572 #endif // (_WIN32_IE >= 0x0400)
2573
2574 #if (_WIN32_IE >= 0x0500)
2575 BOOL AdjustRect(LPRECT lpRect, BOOL bLarger /*= TRUE*/)
2576 {
2577 ATLASSERT(::IsWindow(m_hWnd));
2578 return (BOOL)::SendMessage(m_hWnd, TTM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
2579 }
2580 #endif // (_WIN32_IE >= 0x0500)
2581
2582 #if (_WIN32_WINNT >= 0x0501)
2583 void Popup()
2584 {
2585 ATLASSERT(::IsWindow(m_hWnd));
2586 ::SendMessage(m_hWnd, TTM_POPUP, 0, 0L);
2587 }
2588 #endif // (_WIN32_WINNT >= 0x0501)
2589 };
2590
2591 typedef CToolTipCtrlT<ATL::CWindow> CToolTipCtrl;
2592
2593 #endif // !_WIN32_WCE
2594
2595
2596 ///////////////////////////////////////////////////////////////////////////////
2597 // CHeaderCtrl
2598
2599 template <class TBase>
2600 class CHeaderCtrlT : public TBase
2601 {
2602 public:
2603 // Constructors
2604 CHeaderCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2605 { }
2606
2607 CHeaderCtrlT< TBase >& operator =(HWND hWnd)
2608 {
2609 m_hWnd = hWnd;
2610 return *this;
2611 }
2612
2613 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2614 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2615 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2616 {
2617 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2618 }
2619
2620 // Attributes
2621 static LPCTSTR GetWndClassName()
2622 {
2623 return WC_HEADER;
2624 }
2625
2626 int GetItemCount() const
2627 {
2628 ATLASSERT(::IsWindow(m_hWnd));
2629 return (int)::SendMessage(m_hWnd, HDM_GETITEMCOUNT, 0, 0L);
2630 }
2631
2632 BOOL GetItem(int nIndex, LPHDITEM pHeaderItem) const
2633 {
2634 ATLASSERT(::IsWindow(m_hWnd));
2635 return (BOOL)::SendMessage(m_hWnd, HDM_GETITEM, nIndex, (LPARAM)pHeaderItem);
2636 }
2637
2638 BOOL SetItem(int nIndex, LPHDITEM pHeaderItem)
2639 {
2640 ATLASSERT(::IsWindow(m_hWnd));
2641 return (BOOL)::SendMessage(m_hWnd, HDM_SETITEM, nIndex, (LPARAM)pHeaderItem);
2642 }
2643
2644 CImageList GetImageList() const
2645 {
2646 ATLASSERT(::IsWindow(m_hWnd));
2647 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_GETIMAGELIST, 0, 0L));
2648 }
2649
2650 CImageList SetImageList(HIMAGELIST hImageList)
2651 {
2652 ATLASSERT(::IsWindow(m_hWnd));
2653 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_SETIMAGELIST, 0, (LPARAM)hImageList));
2654 }
2655
2656 BOOL GetOrderArray(int nSize, int* lpnArray) const
2657 {
2658 ATLASSERT(::IsWindow(m_hWnd));
2659 return (BOOL)::SendMessage(m_hWnd, HDM_GETORDERARRAY, nSize, (LPARAM)lpnArray);
2660 }
2661
2662 BOOL SetOrderArray(int nSize, int* lpnArray)
2663 {
2664 ATLASSERT(::IsWindow(m_hWnd));
2665 return (BOOL)::SendMessage(m_hWnd, HDM_SETORDERARRAY, nSize, (LPARAM)lpnArray);
2666 }
2667
2668 BOOL GetItemRect(int nIndex, LPRECT lpItemRect) const
2669 {
2670 ATLASSERT(::IsWindow(m_hWnd));
2671 return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMRECT, nIndex, (LPARAM)lpItemRect);
2672 }
2673
2674 int SetHotDivider(BOOL bPos, DWORD dwInputValue)
2675 {
2676 ATLASSERT(::IsWindow(m_hWnd));
2677 return (int)::SendMessage(m_hWnd, HDM_SETHOTDIVIDER, bPos, dwInputValue);
2678 }
2679
2680 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
2681 BOOL GetUnicodeFormat() const
2682 {
2683 ATLASSERT(::IsWindow(m_hWnd));
2684 return (BOOL)::SendMessage(m_hWnd, HDM_GETUNICODEFORMAT, 0, 0L);
2685 }
2686
2687 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
2688 {
2689 ATLASSERT(::IsWindow(m_hWnd));
2690 return (BOOL)::SendMessage(m_hWnd, HDM_SETUNICODEFORMAT, bUnicode, 0L);
2691 }
2692 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
2693
2694 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
2695 int GetBitmapMargin() const
2696 {
2697 ATLASSERT(::IsWindow(m_hWnd));
2698 return (int)::SendMessage(m_hWnd, HDM_GETBITMAPMARGIN, 0, 0L);
2699 }
2700
2701 int SetBitmapMargin(int nWidth)
2702 {
2703 ATLASSERT(::IsWindow(m_hWnd));
2704 return (int)::SendMessage(m_hWnd, HDM_SETBITMAPMARGIN, nWidth, 0L);
2705 }
2706
2707 int SetFilterChangeTimeout(DWORD dwTimeOut)
2708 {
2709 ATLASSERT(::IsWindow(m_hWnd));
2710 return (int)::SendMessage(m_hWnd, HDM_SETFILTERCHANGETIMEOUT, 0, dwTimeOut);
2711 }
2712 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
2713
2714 #if (_WIN32_WINNT >= 0x0600)
2715 BOOL GetItemDropDownRect(int nIndex, LPRECT lpRect) const
2716 {
2717 ATLASSERT(::IsWindow(m_hWnd));
2718 return (BOOL)::SendMessage(m_hWnd, HDM_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect);
2719 }
2720
2721 BOOL GetOverflowRect(LPRECT lpRect) const
2722 {
2723 ATLASSERT(::IsWindow(m_hWnd));
2724 return (BOOL)::SendMessage(m_hWnd, HDM_GETOVERFLOWRECT, 0, (LPARAM)lpRect);
2725 }
2726
2727 int GetFocusedItem() const
2728 {
2729 ATLASSERT(::IsWindow(m_hWnd));
2730 return (int)::SendMessage(m_hWnd, HDM_GETFOCUSEDITEM, 0, 0L);
2731 }
2732
2733 BOOL SetFocusedItem(int nIndex)
2734 {
2735 ATLASSERT(::IsWindow(m_hWnd));
2736 return (BOOL)::SendMessage(m_hWnd, HDM_SETFOCUSEDITEM, 0, nIndex);
2737 }
2738 #endif // (_WIN32_WINNT >= 0x0600)
2739
2740 // Operations
2741 int InsertItem(int nIndex, LPHDITEM phdi)
2742 {
2743 ATLASSERT(::IsWindow(m_hWnd));
2744 return (int)::SendMessage(m_hWnd, HDM_INSERTITEM, nIndex, (LPARAM)phdi);
2745 }
2746
2747 int AddItem(LPHDITEM phdi)
2748 {
2749 return InsertItem(GetItemCount(), phdi);
2750 }
2751
2752 BOOL DeleteItem(int nIndex)
2753 {
2754 ATLASSERT(::IsWindow(m_hWnd));
2755 return (BOOL)::SendMessage(m_hWnd, HDM_DELETEITEM, nIndex, 0L);
2756 }
2757
2758 BOOL Layout(HD_LAYOUT* pHeaderLayout)
2759 {
2760 ATLASSERT(::IsWindow(m_hWnd));
2761 return (BOOL)::SendMessage(m_hWnd, HDM_LAYOUT, 0, (LPARAM)pHeaderLayout);
2762 }
2763
2764 int HitTest(LPHDHITTESTINFO lpHitTestInfo) const
2765 {
2766 ATLASSERT(::IsWindow(m_hWnd));
2767 return (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)lpHitTestInfo);
2768 }
2769
2770 int OrderToIndex(int nOrder)
2771 {
2772 ATLASSERT(::IsWindow(m_hWnd));
2773 return (int)::SendMessage(m_hWnd, HDM_ORDERTOINDEX, nOrder, 0L);
2774 }
2775
2776 CImageList CreateDragImage(int nIndex)
2777 {
2778 ATLASSERT(::IsWindow(m_hWnd));
2779 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, HDM_CREATEDRAGIMAGE, nIndex, 0L));
2780 }
2781
2782 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
2783 int EditFilter(int nColumn, BOOL bDiscardChanges)
2784 {
2785 ATLASSERT(::IsWindow(m_hWnd));
2786 return (int)::SendMessage(m_hWnd, HDM_EDITFILTER, nColumn, MAKELPARAM(bDiscardChanges, 0));
2787 }
2788
2789 int ClearFilter(int nColumn)
2790 {
2791 ATLASSERT(::IsWindow(m_hWnd));
2792 return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, nColumn, 0L);
2793 }
2794
2795 int ClearAllFilters()
2796 {
2797 ATLASSERT(::IsWindow(m_hWnd));
2798 return (int)::SendMessage(m_hWnd, HDM_CLEARFILTER, (WPARAM)-1, 0L);
2799 }
2800 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
2801 };
2802
2803 typedef CHeaderCtrlT<ATL::CWindow> CHeaderCtrl;
2804
2805
2806 ///////////////////////////////////////////////////////////////////////////////
2807 // CListViewCtrl
2808
2809 template <class TBase>
2810 class CListViewCtrlT : public TBase
2811 {
2812 public:
2813 // Constructors
2814 CListViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2815 { }
2816
2817 CListViewCtrlT< TBase >& operator =(HWND hWnd)
2818 {
2819 m_hWnd = hWnd;
2820 return *this;
2821 }
2822
2823 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2824 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2825 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2826 {
2827 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2828 }
2829
2830 // Attributes
2831 static LPCTSTR GetWndClassName()
2832 {
2833 return WC_LISTVIEW;
2834 }
2835
2836 COLORREF GetBkColor() const
2837 {
2838 ATLASSERT(::IsWindow(m_hWnd));
2839 return (COLORREF)::SendMessage(m_hWnd, LVM_GETBKCOLOR, 0, 0L);
2840 }
2841
2842 BOOL SetBkColor(COLORREF cr)
2843 {
2844 ATLASSERT(::IsWindow(m_hWnd));
2845 return (BOOL)::SendMessage(m_hWnd, LVM_SETBKCOLOR, 0, cr);
2846 }
2847
2848 CImageList GetImageList(int nImageListType) const
2849 {
2850 ATLASSERT(::IsWindow(m_hWnd));
2851 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_GETIMAGELIST, nImageListType, 0L));
2852 }
2853
2854 CImageList SetImageList(HIMAGELIST hImageList, int nImageList)
2855 {
2856 ATLASSERT(::IsWindow(m_hWnd));
2857 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList));
2858 }
2859
2860 int GetItemCount() const
2861 {
2862 ATLASSERT(::IsWindow(m_hWnd));
2863 return (int)::SendMessage(m_hWnd, LVM_GETITEMCOUNT, 0, 0L);
2864 }
2865
2866 BOOL SetItemCount(int nItems)
2867 {
2868 ATLASSERT(::IsWindow(m_hWnd));
2869 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, 0L);
2870 }
2871
2872 BOOL GetItem(LPLVITEM pItem) const
2873 {
2874 ATLASSERT(::IsWindow(m_hWnd));
2875 return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
2876 }
2877
2878 BOOL SetItem(const LVITEM* pItem)
2879 {
2880 ATLASSERT(::IsWindow(m_hWnd));
2881 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)pItem);
2882 }
2883
2884 BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
2885 int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
2886 {
2887 ATLASSERT(::IsWindow(m_hWnd));
2888 LVITEM lvi = { 0 };
2889 lvi.mask = nMask;
2890 lvi.iItem = nItem;
2891 lvi.iSubItem = nSubItem;
2892 lvi.stateMask = nStateMask;
2893 lvi.state = nState;
2894 lvi.pszText = (LPTSTR) lpszItem;
2895 lvi.iImage = nImage;
2896 lvi.lParam = lParam;
2897 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEM, 0, (LPARAM)&lvi);
2898 }
2899
2900 UINT GetItemState(int nItem, UINT nMask) const
2901 {
2902 ATLASSERT(::IsWindow(m_hWnd));
2903 return (UINT)::SendMessage(m_hWnd, LVM_GETITEMSTATE, nItem, nMask);
2904 }
2905
2906 BOOL SetItemState(int nItem, UINT nState, UINT nStateMask)
2907 {
2908 ATLASSERT(::IsWindow(m_hWnd));
2909 LVITEM lvi = { 0 };
2910 lvi.state = nState;
2911 lvi.stateMask = nStateMask;
2912 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi);
2913 }
2914
2915 BOOL SetItemState(int nItem, LPLVITEM pItem)
2916 {
2917 ATLASSERT(::IsWindow(m_hWnd));
2918 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, nItem, (LPARAM)pItem);
2919 }
2920
2921 #ifndef _ATL_NO_COM
2922 BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const
2923 {
2924 USES_CONVERSION;
2925 ATLASSERT(::IsWindow(m_hWnd));
2926 ATLASSERT(bstrText == NULL);
2927 LVITEM lvi = { 0 };
2928 lvi.iSubItem = nSubItem;
2929
2930 LPTSTR lpstrText = NULL;
2931 int nRes = 0;
2932 for(int nLen = 256; ; nLen *= 2)
2933 {
2934 ATLTRY(lpstrText = new TCHAR[nLen]);
2935 if(lpstrText == NULL)
2936 break;
2937 lpstrText[0] = NULL;
2938 lvi.cchTextMax = nLen;
2939 lvi.pszText = lpstrText;
2940 nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
2941 if(nRes < nLen - 1)
2942 break;
2943 delete [] lpstrText;
2944 lpstrText = NULL;
2945 }
2946
2947 if(lpstrText != NULL)
2948 {
2949 if(nRes != 0)
2950 bstrText = ::SysAllocString(T2OLE(lpstrText));
2951 delete [] lpstrText;
2952 }
2953
2954 return (bstrText != NULL) ? TRUE : FALSE;
2955 }
2956 #endif // !_ATL_NO_COM
2957
2958 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
2959 int GetItemText(int nItem, int nSubItem, _CSTRING_NS::CString& strText) const
2960 {
2961 ATLASSERT(::IsWindow(m_hWnd));
2962 LVITEM lvi = { 0 };
2963 lvi.iSubItem = nSubItem;
2964
2965 strText.Empty();
2966 int nRes = 0;
2967 for(int nLen = 256; ; nLen *= 2)
2968 {
2969 lvi.cchTextMax = nLen;
2970 lvi.pszText = strText.GetBufferSetLength(nLen);
2971 if(lvi.pszText == NULL)
2972 {
2973 nRes = 0;
2974 break;
2975 }
2976 nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
2977 if(nRes < nLen - 1)
2978 break;
2979 }
2980 strText.ReleaseBuffer();
2981 return nRes;
2982 }
2983 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
2984
2985 int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const
2986 {
2987 ATLASSERT(::IsWindow(m_hWnd));
2988 LVITEM lvi = { 0 };
2989 lvi.iSubItem = nSubItem;
2990 lvi.cchTextMax = nLen;
2991 lvi.pszText = lpszText;
2992 return (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
2993 }
2994
2995 BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
2996 {
2997 ATLASSERT(::IsWindow(m_hWnd));
2998 return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0);
2999 }
3000
3001 DWORD_PTR GetItemData(int nItem) const
3002 {
3003 ATLASSERT(::IsWindow(m_hWnd));
3004 LVITEM lvi = { 0 };
3005 lvi.iItem = nItem;
3006 lvi.mask = LVIF_PARAM;
3007 BOOL bRet = (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)&lvi);
3008 return (DWORD_PTR)(bRet ? lvi.lParam : NULL);
3009 }
3010
3011 BOOL SetItemData(int nItem, DWORD_PTR dwData)
3012 {
3013 ATLASSERT(::IsWindow(m_hWnd));
3014 return SetItem(nItem, 0, LVIF_PARAM, NULL, 0, 0, 0, (LPARAM)dwData);
3015 }
3016
3017 UINT GetCallbackMask() const
3018 {
3019 ATLASSERT(::IsWindow(m_hWnd));
3020 return (UINT)::SendMessage(m_hWnd, LVM_GETCALLBACKMASK, 0, 0L);
3021 }
3022
3023 BOOL SetCallbackMask(UINT nMask)
3024 {
3025 ATLASSERT(::IsWindow(m_hWnd));
3026 return (BOOL)::SendMessage(m_hWnd, LVM_SETCALLBACKMASK, nMask, 0L);
3027 }
3028
3029 BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const
3030 {
3031 ATLASSERT(::IsWindow(m_hWnd));
3032 return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint);
3033 }
3034
3035 BOOL SetItemPosition(int nItem, POINT pt)
3036 {
3037 ATLASSERT(::IsWindow(m_hWnd));
3038 ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
3039 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
3040 }
3041
3042 BOOL SetItemPosition(int nItem, int x, int y)
3043 {
3044 ATLASSERT(::IsWindow(m_hWnd));
3045 ATLASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
3046 POINT pt = { x, y };
3047 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
3048 }
3049
3050 int GetStringWidth(LPCTSTR lpsz) const
3051 {
3052 ATLASSERT(::IsWindow(m_hWnd));
3053 return (int)::SendMessage(m_hWnd, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz);
3054 }
3055
3056 CEdit GetEditControl() const
3057 {
3058 ATLASSERT(::IsWindow(m_hWnd));
3059 return CEdit((HWND)::SendMessage(m_hWnd, LVM_GETEDITCONTROL, 0, 0L));
3060 }
3061
3062 BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const
3063 {
3064 ATLASSERT(::IsWindow(m_hWnd));
3065 return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMN, nCol, (LPARAM)pColumn);
3066 }
3067
3068 BOOL SetColumn(int nCol, const LVCOLUMN* pColumn)
3069 {
3070 ATLASSERT(::IsWindow(m_hWnd));
3071 return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMN, nCol, (LPARAM)pColumn);
3072 }
3073
3074 int GetColumnWidth(int nCol) const
3075 {
3076 ATLASSERT(::IsWindow(m_hWnd));
3077 return (int)::SendMessage(m_hWnd, LVM_GETCOLUMNWIDTH, nCol, 0L);
3078 }
3079
3080 BOOL SetColumnWidth(int nCol, int cx)
3081 {
3082 ATLASSERT(::IsWindow(m_hWnd));
3083 return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0));
3084 }
3085
3086 BOOL GetViewRect(LPRECT lpRect) const
3087 {
3088 ATLASSERT(::IsWindow(m_hWnd));
3089 return (BOOL)::SendMessage(m_hWnd, LVM_GETVIEWRECT, 0, (LPARAM)lpRect);
3090 }
3091
3092 COLORREF GetTextColor() const
3093 {
3094 ATLASSERT(::IsWindow(m_hWnd));
3095 return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTCOLOR, 0, 0L);
3096 }
3097
3098 BOOL SetTextColor(COLORREF cr)
3099 {
3100 ATLASSERT(::IsWindow(m_hWnd));
3101 return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTCOLOR, 0, cr);
3102 }
3103
3104 COLORREF GetTextBkColor() const
3105 {
3106 ATLASSERT(::IsWindow(m_hWnd));
3107 return (COLORREF)::SendMessage(m_hWnd, LVM_GETTEXTBKCOLOR, 0, 0L);
3108 }
3109
3110 BOOL SetTextBkColor(COLORREF cr)
3111 {
3112 ATLASSERT(::IsWindow(m_hWnd));
3113 return (BOOL)::SendMessage(m_hWnd, LVM_SETTEXTBKCOLOR, 0, cr);
3114 }
3115
3116 int GetTopIndex() const
3117 {
3118 ATLASSERT(::IsWindow(m_hWnd));
3119 return (int)::SendMessage(m_hWnd, LVM_GETTOPINDEX, 0, 0L);
3120 }
3121
3122 int GetCountPerPage() const
3123 {
3124 ATLASSERT(::IsWindow(m_hWnd));
3125 return (int)::SendMessage(m_hWnd, LVM_GETCOUNTPERPAGE, 0, 0L);
3126 }
3127
3128 BOOL GetOrigin(LPPOINT lpPoint) const
3129 {
3130 ATLASSERT(::IsWindow(m_hWnd));
3131 return (BOOL)::SendMessage(m_hWnd, LVM_GETORIGIN, 0, (LPARAM)lpPoint);
3132 }
3133
3134 UINT GetSelectedCount() const
3135 {
3136 ATLASSERT(::IsWindow(m_hWnd));
3137 return (UINT)::SendMessage(m_hWnd, LVM_GETSELECTEDCOUNT, 0, 0L);
3138 }
3139
3140 BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const
3141 {
3142 ATLASSERT(::IsWindow(m_hWnd));
3143 lpRect->left = nCode;
3144 return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect);
3145 }
3146
3147 #ifndef _WIN32_WCE
3148 HCURSOR GetHotCursor() const
3149 {
3150 ATLASSERT(::IsWindow(m_hWnd));
3151 return (HCURSOR)::SendMessage(m_hWnd, LVM_GETHOTCURSOR, 0, 0L);
3152 }
3153
3154 HCURSOR SetHotCursor(HCURSOR hHotCursor)
3155 {
3156 ATLASSERT(::IsWindow(m_hWnd));
3157 return (HCURSOR)::SendMessage(m_hWnd, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor);
3158 }
3159
3160 int GetHotItem() const
3161 {
3162 ATLASSERT(::IsWindow(m_hWnd));
3163 return (int)::SendMessage(m_hWnd, LVM_GETHOTITEM, 0, 0L);
3164 }
3165
3166 int SetHotItem(int nIndex)
3167 {
3168 ATLASSERT(::IsWindow(m_hWnd));
3169 return (int)::SendMessage(m_hWnd, LVM_SETHOTITEM, nIndex, 0L);
3170 }
3171 #endif // !_WIN32_WCE
3172
3173 BOOL GetColumnOrderArray(int nCount, int* lpnArray) const
3174 {
3175 ATLASSERT(::IsWindow(m_hWnd));
3176 return (BOOL)::SendMessage(m_hWnd, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
3177 }
3178
3179 BOOL SetColumnOrderArray(int nCount, int* lpnArray)
3180 {
3181 ATLASSERT(::IsWindow(m_hWnd));
3182 return (BOOL)::SendMessage(m_hWnd, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
3183 }
3184
3185 CHeaderCtrl GetHeader() const
3186 {
3187 ATLASSERT(::IsWindow(m_hWnd));
3188 return CHeaderCtrl((HWND)::SendMessage(m_hWnd, LVM_GETHEADER, 0, 0L));
3189 }
3190
3191 BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const
3192 {
3193 ATLASSERT(::IsWindow(m_hWnd));
3194 ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_REPORT);
3195 ATLASSERT(lpRect != NULL);
3196 lpRect->top = nSubItem;
3197 lpRect->left = nFlag;
3198 return (BOOL)::SendMessage(m_hWnd, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect);
3199 }
3200
3201 DWORD SetIconSpacing(int cx, int cy)
3202 {
3203 ATLASSERT(::IsWindow(m_hWnd));
3204 ATLASSERT((GetStyle() & LVS_TYPEMASK) == LVS_ICON);
3205 return (DWORD)::SendMessage(m_hWnd, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy));
3206 }
3207
3208 int GetISearchString(LPTSTR lpstr) const
3209 {
3210 ATLASSERT(::IsWindow(m_hWnd));
3211 return (int)::SendMessage(m_hWnd, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
3212 }
3213
3214 void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const
3215 {
3216 ATLASSERT(::IsWindow(m_hWnd));
3217 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, LVM_GETITEMSPACING, bSmallIconView, 0L);
3218 sizeSpacing.cx = GET_X_LPARAM(dwRet);
3219 sizeSpacing.cy = GET_Y_LPARAM(dwRet);
3220 }
3221
3222 #if (_WIN32_WCE >= 410)
3223 void SetItemSpacing(INT cySpacing)
3224 {
3225 ATLASSERT(::IsWindow(m_hWnd));
3226 ListView_SetItemSpacing(m_hWnd, cySpacing);
3227 }
3228 #endif // (_WIN32_WCE >= 410)
3229
3230 // single-selection only
3231 int GetSelectedIndex() const
3232 {
3233 ATLASSERT(::IsWindow(m_hWnd));
3234 ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
3235 return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
3236 }
3237
3238 BOOL GetSelectedItem(LPLVITEM pItem) const
3239 {
3240 ATLASSERT(::IsWindow(m_hWnd));
3241 ATLASSERT((GetStyle() & LVS_SINGLESEL) != 0);
3242 ATLASSERT(pItem != NULL);
3243 pItem->iItem = (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
3244 if(pItem->iItem == -1)
3245 return FALSE;
3246 return (BOOL)::SendMessage(m_hWnd, LVM_GETITEM, 0, (LPARAM)pItem);
3247 }
3248
3249 // extended list view styles
3250 DWORD GetExtendedListViewStyle() const
3251 {
3252 ATLASSERT(::IsWindow(m_hWnd));
3253 return (DWORD)::SendMessage(m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L);
3254 }
3255
3256 // dwExMask = 0 means all styles
3257 DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0)
3258 {
3259 ATLASSERT(::IsWindow(m_hWnd));
3260 return (DWORD)::SendMessage(m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle);
3261 }
3262
3263 // checkboxes only
3264 BOOL GetCheckState(int nIndex) const
3265 {
3266 ATLASSERT(::IsWindow(m_hWnd));
3267 ATLASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0);
3268 UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK);
3269 return (uRet >> 12) - 1;
3270 }
3271
3272 BOOL SetCheckState(int nItem, BOOL bCheck)
3273 {
3274 int nCheck = bCheck ? 2 : 1; // one based index
3275 return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK);
3276 }
3277
3278 // view type
3279 DWORD GetViewType() const
3280 {
3281 ATLASSERT(::IsWindow(m_hWnd));
3282 return (GetStyle() & LVS_TYPEMASK);
3283 }
3284
3285 DWORD SetViewType(DWORD dwType)
3286 {
3287 ATLASSERT(::IsWindow(m_hWnd));
3288 ATLASSERT(dwType == LVS_ICON || dwType == LVS_SMALLICON || dwType == LVS_LIST || dwType == LVS_REPORT);
3289 DWORD dwOldType = GetViewType();
3290 if(dwType != dwOldType)
3291 ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK));
3292 return dwOldType;
3293 }
3294
3295 #if (_WIN32_IE >= 0x0400)
3296 #ifndef _WIN32_WCE
3297 BOOL GetBkImage(LPLVBKIMAGE plvbki) const
3298 {
3299 ATLASSERT(::IsWindow(m_hWnd));
3300 return (BOOL)::SendMessage(m_hWnd, LVM_GETBKIMAGE, 0, (LPARAM)plvbki);
3301 }
3302
3303 BOOL SetBkImage(LPLVBKIMAGE plvbki)
3304 {
3305 ATLASSERT(::IsWindow(m_hWnd));
3306 return (BOOL)::SendMessage(m_hWnd, LVM_SETBKIMAGE, 0, (LPARAM)plvbki);
3307 }
3308 #endif // !_WIN32_WCE
3309
3310 int GetSelectionMark() const
3311 {
3312 ATLASSERT(::IsWindow(m_hWnd));
3313 return (int)::SendMessage(m_hWnd, LVM_GETSELECTIONMARK, 0, 0L);
3314 }
3315
3316 int SetSelectionMark(int nIndex)
3317 {
3318 ATLASSERT(::IsWindow(m_hWnd));
3319 return (int)::SendMessage(m_hWnd, LVM_SETSELECTIONMARK, 0, nIndex);
3320 }
3321
3322 #ifndef _WIN32_WCE
3323 BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const
3324 {
3325 ATLASSERT(::IsWindow(m_hWnd));
3326 return (BOOL)::SendMessage(m_hWnd, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
3327 }
3328
3329 BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect)
3330 {
3331 ATLASSERT(::IsWindow(m_hWnd));
3332 return (BOOL)::SendMessage(m_hWnd, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
3333 }
3334
3335 DWORD GetHoverTime() const
3336 {
3337 ATLASSERT(::IsWindow(m_hWnd));
3338 ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
3339 return (DWORD)::SendMessage(m_hWnd, LVM_GETHOVERTIME, 0, 0L);
3340 }
3341
3342 DWORD SetHoverTime(DWORD dwHoverTime)
3343 {
3344 ATLASSERT(::IsWindow(m_hWnd));
3345 ATLASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
3346 return (DWORD)::SendMessage(m_hWnd, LVM_SETHOVERTIME, 0, dwHoverTime);
3347 }
3348
3349 BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const
3350 {
3351 ATLASSERT(::IsWindow(m_hWnd));
3352 return (BOOL)::SendMessage(m_hWnd, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas);
3353 }
3354 #endif // !_WIN32_WCE
3355
3356 BOOL SetItemCountEx(int nItems, DWORD dwFlags)
3357 {
3358 ATLASSERT(::IsWindow(m_hWnd));
3359 ATLASSERT(((GetStyle() & LVS_OWNERDATA) != 0) && (((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((GetStyle() & LVS_TYPEMASK) == LVS_LIST)));
3360 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMCOUNT, nItems, dwFlags);
3361 }
3362
3363 #ifndef _WIN32_WCE
3364 CToolTipCtrl GetToolTips() const
3365 {
3366 ATLASSERT(::IsWindow(m_hWnd));
3367 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_GETTOOLTIPS, 0, 0L));
3368 }
3369
3370 CToolTipCtrl SetToolTips(HWND hWndTT)
3371 {
3372 ATLASSERT(::IsWindow(m_hWnd));
3373 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
3374 }
3375
3376 BOOL GetUnicodeFormat() const
3377 {
3378 ATLASSERT(::IsWindow(m_hWnd));
3379 return (BOOL)::SendMessage(m_hWnd, LVM_GETUNICODEFORMAT, 0, 0L);
3380 }
3381
3382 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
3383 {
3384 ATLASSERT(::IsWindow(m_hWnd));
3385 return (BOOL)::SendMessage(m_hWnd, LVM_SETUNICODEFORMAT, bUnicode, 0L);
3386 }
3387 #endif // !_WIN32_WCE
3388 #endif // (_WIN32_IE >= 0x0400)
3389
3390 #if (_WIN32_WINNT >= 0x0501)
3391 int GetSelectedColumn() const
3392 {
3393 ATLASSERT(::IsWindow(m_hWnd));
3394 return (int)::SendMessage(m_hWnd, LVM_GETSELECTEDCOLUMN, 0, 0L);
3395 }
3396
3397 void SetSelectedColumn(int nColumn)
3398 {
3399 ATLASSERT(::IsWindow(m_hWnd));
3400 ::SendMessage(m_hWnd, LVM_SETSELECTEDCOLUMN, nColumn, 0L);
3401 }
3402
3403 DWORD GetView() const
3404 {
3405 ATLASSERT(::IsWindow(m_hWnd));
3406 return (DWORD)::SendMessage(m_hWnd, LVM_GETVIEW, 0, 0L);
3407 }
3408
3409 int SetView(DWORD dwView)
3410 {
3411 ATLASSERT(::IsWindow(m_hWnd));
3412 return (int)::SendMessage(m_hWnd, LVM_SETVIEW, dwView, 0L);
3413 }
3414
3415 BOOL IsGroupViewEnabled() const
3416 {
3417 ATLASSERT(::IsWindow(m_hWnd));
3418 return (BOOL)::SendMessage(m_hWnd, LVM_ISGROUPVIEWENABLED, 0, 0L);
3419 }
3420
3421 int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const
3422 {
3423 ATLASSERT(::IsWindow(m_hWnd));
3424 return (int)::SendMessage(m_hWnd, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup);
3425 }
3426
3427 int SetGroupInfo(int nGroupID, PLVGROUP pGroup)
3428 {
3429 ATLASSERT(::IsWindow(m_hWnd));
3430 return (int)::SendMessage(m_hWnd, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup);
3431 }
3432
3433 void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const
3434 {
3435 ATLASSERT(::IsWindow(m_hWnd));
3436 ::SendMessage(m_hWnd, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
3437 }
3438
3439 void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
3440 {
3441 ATLASSERT(::IsWindow(m_hWnd));
3442 ::SendMessage(m_hWnd, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
3443 }
3444
3445 void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const
3446 {
3447 ATLASSERT(::IsWindow(m_hWnd));
3448 ::SendMessage(m_hWnd, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
3449 }
3450
3451 BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo)
3452 {
3453 ATLASSERT(::IsWindow(m_hWnd));
3454 return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
3455 }
3456
3457 void GetTileInfo(PLVTILEINFO pTileInfo) const
3458 {
3459 ATLASSERT(::IsWindow(m_hWnd));
3460 ::SendMessage(m_hWnd, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo);
3461 }
3462
3463 BOOL SetTileInfo(PLVTILEINFO pTileInfo)
3464 {
3465 ATLASSERT(::IsWindow(m_hWnd));
3466 return (BOOL)::SendMessage(m_hWnd, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo);
3467 }
3468
3469 BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const
3470 {
3471 ATLASSERT(::IsWindow(m_hWnd));
3472 return (BOOL)::SendMessage(m_hWnd, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark);
3473 }
3474
3475 BOOL SetInsertMark(LPLVINSERTMARK pInsertMark)
3476 {
3477 ATLASSERT(::IsWindow(m_hWnd));
3478 return (BOOL)::SendMessage(m_hWnd, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark);
3479 }
3480
3481 int GetInsertMarkRect(LPRECT lpRect) const
3482 {
3483 ATLASSERT(::IsWindow(m_hWnd));
3484 return (int)::SendMessage(m_hWnd, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect);
3485 }
3486
3487 COLORREF GetInsertMarkColor() const
3488 {
3489 ATLASSERT(::IsWindow(m_hWnd));
3490 return (COLORREF)::SendMessage(m_hWnd, LVM_GETINSERTMARKCOLOR, 0, 0L);
3491 }
3492
3493 COLORREF SetInsertMarkColor(COLORREF clr)
3494 {
3495 ATLASSERT(::IsWindow(m_hWnd));
3496 return (COLORREF)::SendMessage(m_hWnd, LVM_SETINSERTMARKCOLOR, 0, clr);
3497 }
3498
3499 COLORREF GetOutlineColor() const
3500 {
3501 ATLASSERT(::IsWindow(m_hWnd));
3502 return (COLORREF)::SendMessage(m_hWnd, LVM_GETOUTLINECOLOR, 0, 0L);
3503 }
3504
3505 COLORREF SetOutlineColor(COLORREF clr)
3506 {
3507 ATLASSERT(::IsWindow(m_hWnd));
3508 return (COLORREF)::SendMessage(m_hWnd, LVM_SETOUTLINECOLOR, 0, clr);
3509 }
3510 #endif // (_WIN32_WINNT >= 0x0501)
3511
3512 #if (_WIN32_WINNT >= 0x0600)
3513 int GetGroupCount() const
3514 {
3515 ATLASSERT(::IsWindow(m_hWnd));
3516 return (int)::SendMessage(m_hWnd, LVM_GETGROUPCOUNT, 0, 0L);
3517 }
3518
3519 BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const
3520 {
3521 ATLASSERT(::IsWindow(m_hWnd));
3522 return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup);
3523 }
3524
3525 BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const
3526 {
3527 ATLASSERT(::IsWindow(m_hWnd));
3528 ATLASSERT(lpRect != NULL);
3529 if(lpRect != NULL)
3530 lpRect->top = nType;
3531 return (BOOL)::SendMessage(m_hWnd, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect);
3532 }
3533
3534 UINT GetGroupState(int nGroupID, UINT uMask) const
3535 {
3536 ATLASSERT(::IsWindow(m_hWnd));
3537 return (UINT)::SendMessage(m_hWnd, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask);
3538 }
3539
3540 int GetFocusedGroup() const
3541 {
3542 ATLASSERT(::IsWindow(m_hWnd));
3543 return (int)::SendMessage(m_hWnd, LVM_GETFOCUSEDGROUP, 0, 0L);
3544 }
3545
3546 BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const
3547 {
3548 ATLASSERT(::IsWindow(m_hWnd));
3549 return (BOOL)::SendMessage(m_hWnd, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText);
3550 }
3551
3552 BOOL GetFooterRect(LPRECT lpRect) const
3553 {
3554 ATLASSERT(::IsWindow(m_hWnd));
3555 return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect);
3556 }
3557
3558 BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const
3559 {
3560 ATLASSERT(::IsWindow(m_hWnd));
3561 return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo);
3562 }
3563
3564 BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const
3565 {
3566 ATLASSERT(::IsWindow(m_hWnd));
3567 return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect);
3568 }
3569
3570 BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const
3571 {
3572 ATLASSERT(::IsWindow(m_hWnd));
3573 return (BOOL)::SendMessage(m_hWnd, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem);
3574 }
3575
3576 BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const
3577 {
3578 ATLASSERT(::IsWindow(m_hWnd));
3579 ATLASSERT(pItemIndex != NULL);
3580 ATLASSERT(lpRect != NULL);
3581 if(lpRect != NULL)
3582 {
3583 lpRect->top = nSubItem;
3584 lpRect->left = nType;
3585 }
3586 return (BOOL)::SendMessage(m_hWnd, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect);
3587 }
3588
3589 BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask)
3590 {
3591 ATLASSERT(::IsWindow(m_hWnd));
3592 LVITEM lvi = { 0 };
3593 lvi.state = uState;
3594 lvi.stateMask = dwMask;
3595 return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi);
3596 }
3597
3598 BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const
3599 {
3600 ATLASSERT(::IsWindow(m_hWnd));
3601 return (BOOL)::SendMessage(m_hWnd, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0));
3602 }
3603 #endif // (_WIN32_WINNT >= 0x0600)
3604
3605 // Operations
3606 int InsertColumn(int nCol, const LVCOLUMN* pColumn)
3607 {
3608 ATLASSERT(::IsWindow(m_hWnd));
3609 return (int)::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn);
3610 }
3611
3612 int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT,
3613 int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1)
3614 {
3615 LVCOLUMN column = { 0 };
3616 column.mask = LVCF_TEXT|LVCF_FMT;
3617 column.pszText = (LPTSTR)lpszColumnHeading;
3618 column.fmt = nFormat;
3619 if (nWidth != -1)
3620 {
3621 column.mask |= LVCF_WIDTH;
3622 column.cx = nWidth;
3623 }
3624 if (nSubItem != -1)
3625 {
3626 column.mask |= LVCF_SUBITEM;
3627 column.iSubItem = nSubItem;
3628 }
3629 if (iImage != -1)
3630 {
3631 column.mask |= LVCF_IMAGE;
3632 column.iImage = iImage;
3633 }
3634 if (iOrder != -1)
3635 {
3636 column.mask |= LVCF_ORDER;
3637 column.iOrder = iOrder;
3638 }
3639 return InsertColumn(nCol, &column);
3640 }
3641
3642 BOOL DeleteColumn(int nCol)
3643 {
3644 ATLASSERT(::IsWindow(m_hWnd));
3645 return (BOOL)::SendMessage(m_hWnd, LVM_DELETECOLUMN, nCol, 0L);
3646 }
3647
3648 int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
3649 {
3650 ATLASSERT(::IsWindow(m_hWnd));
3651 LVITEM item = { 0 };
3652 item.mask = nMask;
3653 item.iItem = nItem;
3654 item.iSubItem = 0;
3655 item.pszText = (LPTSTR)lpszItem;
3656 item.state = nState;
3657 item.stateMask = nStateMask;
3658 item.iImage = nImage;
3659 item.lParam = lParam;
3660 return InsertItem(&item);
3661 }
3662
3663 int InsertItem(const LVITEM* pItem)
3664 {
3665 ATLASSERT(::IsWindow(m_hWnd));
3666 return (int)::SendMessage(m_hWnd, LVM_INSERTITEM, 0, (LPARAM)pItem);
3667 }
3668
3669 int InsertItem(int nItem, LPCTSTR lpszItem)
3670 {
3671 ATLASSERT(::IsWindow(m_hWnd));
3672 return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0);
3673 }
3674
3675 int InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
3676 {
3677 ATLASSERT(::IsWindow(m_hWnd));
3678 return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0);
3679 }
3680
3681 int GetNextItem(int nItem, int nFlags) const
3682 {
3683 ATLASSERT(::IsWindow(m_hWnd));
3684 return (int)::SendMessage(m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0));
3685 }
3686
3687 BOOL DeleteItem(int nItem)
3688 {
3689 ATLASSERT(::IsWindow(m_hWnd));
3690 return (BOOL)::SendMessage(m_hWnd, LVM_DELETEITEM, nItem, 0L);
3691 }
3692
3693 BOOL DeleteAllItems()
3694 {
3695 ATLASSERT(::IsWindow(m_hWnd));
3696 return (BOOL)::SendMessage(m_hWnd, LVM_DELETEALLITEMS, 0, 0L);
3697 }
3698
3699 int FindItem(LVFINDINFO* pFindInfo, int nStart = -1) const
3700 {
3701 ATLASSERT(::IsWindow(m_hWnd));
3702 return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo);
3703 }
3704
3705 int FindItem(LPCTSTR lpstrFind, bool bPartial = true, bool bWrap = false, int nStart = -1) const
3706 {
3707 ATLASSERT(::IsWindow(m_hWnd));
3708 LVFINDINFO lvfi = { 0 };
3709 lvfi.flags = LVFI_STRING | (bWrap ? LVFI_WRAP : 0) | (bPartial ? LVFI_PARTIAL : 0);
3710 lvfi.psz = lpstrFind;
3711 return (int)::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)&lvfi);
3712 }
3713
3714 int HitTest(LVHITTESTINFO* pHitTestInfo) const
3715 {
3716 ATLASSERT(::IsWindow(m_hWnd));
3717 return (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)pHitTestInfo);
3718 }
3719
3720 int HitTest(POINT pt, UINT* pFlags) const
3721 {
3722 ATLASSERT(::IsWindow(m_hWnd));
3723 LVHITTESTINFO hti = { 0 };
3724 hti.pt = pt;
3725 int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, 0, (LPARAM)&hti);
3726 if (pFlags != NULL)
3727 *pFlags = hti.flags;
3728 return nRes;
3729 }
3730
3731 BOOL EnsureVisible(int nItem, BOOL bPartialOK)
3732 {
3733 ATLASSERT(::IsWindow(m_hWnd));
3734 return (BOOL)::SendMessage(m_hWnd, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0));
3735 }
3736
3737 BOOL Scroll(SIZE size)
3738 {
3739 ATLASSERT(::IsWindow(m_hWnd));
3740 return (BOOL)::SendMessage(m_hWnd, LVM_SCROLL, size.cx, size.cy);
3741 }
3742
3743 BOOL RedrawItems(int nFirst, int nLast)
3744 {
3745 ATLASSERT(::IsWindow(m_hWnd));
3746 return (BOOL)::SendMessage(m_hWnd, LVM_REDRAWITEMS, nFirst, nLast);
3747 }
3748
3749 BOOL Arrange(UINT nCode)
3750 {
3751 ATLASSERT(::IsWindow(m_hWnd));
3752 return (BOOL)::SendMessage(m_hWnd, LVM_ARRANGE, nCode, 0L);
3753 }
3754
3755 CEdit EditLabel(int nItem)
3756 {
3757 ATLASSERT(::IsWindow(m_hWnd));
3758 return CEdit((HWND)::SendMessage(m_hWnd, LVM_EDITLABEL, nItem, 0L));
3759 }
3760
3761 BOOL Update(int nItem)
3762 {
3763 ATLASSERT(::IsWindow(m_hWnd));
3764 return (BOOL)::SendMessage(m_hWnd, LVM_UPDATE, nItem, 0L);
3765 }
3766
3767 BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
3768 {
3769 ATLASSERT(::IsWindow(m_hWnd));
3770 return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare);
3771 }
3772
3773 CImageList RemoveImageList(int nImageList)
3774 {
3775 ATLASSERT(::IsWindow(m_hWnd));
3776 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
3777 }
3778
3779 CImageList CreateDragImage(int nItem, LPPOINT lpPoint)
3780 {
3781 ATLASSERT(::IsWindow(m_hWnd));
3782 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint));
3783 }
3784
3785 DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1)
3786 {
3787 ATLASSERT(::IsWindow(m_hWnd));
3788 return (DWORD)::SendMessage(m_hWnd, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy));
3789 }
3790
3791 int SubItemHitTest(LPLVHITTESTINFO lpInfo) const
3792 {
3793 ATLASSERT(::IsWindow(m_hWnd));
3794 return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo);
3795 }
3796
3797 int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1,
3798 int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
3799 int nFmt = LVCFMT_LEFT)
3800 {
3801 const int cxOffset = 15;
3802 ATLASSERT(::IsWindow(m_hWnd));
3803 LVCOLUMN lvc = { 0 };
3804 lvc.mask = nMask;
3805 lvc.fmt = nFmt;
3806 lvc.pszText = (LPTSTR)strItem;
3807 lvc.cx = GetStringWidth(lvc.pszText) + cxOffset;
3808 if(nMask & LVCF_SUBITEM)
3809 lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem;
3810 return InsertColumn(nItem, &lvc);
3811 }
3812
3813 int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -3)
3814 {
3815 ATLASSERT(::IsWindow(m_hWnd));
3816 LVITEM lvItem = { 0 };
3817 lvItem.mask = LVIF_TEXT;
3818 lvItem.iItem = nItem;
3819 lvItem.iSubItem = nSubItem;
3820 lvItem.pszText = (LPTSTR)strItem;
3821 if(nImageIndex != -3)
3822 {
3823 lvItem.mask |= LVIF_IMAGE;
3824 lvItem.iImage = nImageIndex;
3825 }
3826 if(nSubItem == 0)
3827 return InsertItem(&lvItem);
3828 return SetItem(&lvItem) ? nItem : -1;
3829 }
3830
3831 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3832 BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
3833 {
3834 ATLASSERT(::IsWindow(m_hWnd));
3835 return (BOOL)::SendMessage(m_hWnd, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare);
3836 }
3837 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3838
3839 #if (_WIN32_WINNT >= 0x0501)
3840 int InsertGroup(int nItem, PLVGROUP pGroup)
3841 {
3842 ATLASSERT(::IsWindow(m_hWnd));
3843 return (int)::SendMessage(m_hWnd, LVM_INSERTGROUP, nItem, (LPARAM)pGroup);
3844 }
3845
3846 int AddGroup(PLVGROUP pGroup)
3847 {
3848 return InsertGroup(-1, pGroup);
3849 }
3850
3851 int RemoveGroup(int nGroupID)
3852 {
3853 ATLASSERT(::IsWindow(m_hWnd));
3854 return (int)::SendMessage(m_hWnd, LVM_REMOVEGROUP, nGroupID, 0L);
3855 }
3856
3857 void MoveGroup(int nGroupID, int nItem)
3858 {
3859 ATLASSERT(::IsWindow(m_hWnd));
3860 ::SendMessage(m_hWnd, LVM_MOVEGROUP, nGroupID, nItem);
3861 }
3862
3863 void MoveItemToGroup(int nItem, int nGroupID)
3864 {
3865 ATLASSERT(::IsWindow(m_hWnd));
3866 ::SendMessage(m_hWnd, LVM_MOVEITEMTOGROUP, nItem, nGroupID);
3867 }
3868
3869 int EnableGroupView(BOOL bEnable)
3870 {
3871 ATLASSERT(::IsWindow(m_hWnd));
3872 return (int)::SendMessage(m_hWnd, LVM_ENABLEGROUPVIEW, bEnable, 0L);
3873 }
3874
3875 int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = NULL)
3876 {
3877 ATLASSERT(::IsWindow(m_hWnd));
3878 return (int)::SendMessage(m_hWnd, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid);
3879 }
3880
3881 void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted)
3882 {
3883 ATLASSERT(::IsWindow(m_hWnd));
3884 ::SendMessage(m_hWnd, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L);
3885 }
3886
3887 void RemoveAllGroups()
3888 {
3889 ATLASSERT(::IsWindow(m_hWnd));
3890 ::SendMessage(m_hWnd, LVM_REMOVEALLGROUPS, 0, 0L);
3891 }
3892
3893 BOOL HasGroup(int nGroupID)
3894 {
3895 ATLASSERT(::IsWindow(m_hWnd));
3896 return (BOOL)::SendMessage(m_hWnd, LVM_HASGROUP, nGroupID, 0L);
3897 }
3898
3899 BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const
3900 {
3901 ATLASSERT(::IsWindow(m_hWnd));
3902 return (BOOL)::SendMessage(m_hWnd, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark);
3903 }
3904
3905 BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip)
3906 {
3907 ATLASSERT(::IsWindow(m_hWnd));
3908 return (BOOL)::SendMessage(m_hWnd, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip);
3909 }
3910
3911 void CancelEditLabel()
3912 {
3913 ATLASSERT(::IsWindow(m_hWnd));
3914 ::SendMessage(m_hWnd, LVM_CANCELEDITLABEL, 0, 0L);
3915 }
3916
3917 UINT MapIndexToID(int nIndex) const
3918 {
3919 ATLASSERT(::IsWindow(m_hWnd));
3920 return (UINT)::SendMessage(m_hWnd, LVM_MAPINDEXTOID, nIndex, 0L);
3921 }
3922
3923 int MapIDToIndex(UINT uID) const
3924 {
3925 ATLASSERT(::IsWindow(m_hWnd));
3926 return (int)::SendMessage(m_hWnd, LVM_MAPIDTOINDEX, uID, 0L);
3927 }
3928 #endif // (_WIN32_WINNT >= 0x0501)
3929
3930 #if (_WIN32_WINNT >= 0x0600)
3931 int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
3932 {
3933 ATLASSERT(::IsWindow(m_hWnd));
3934 return (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
3935 }
3936
3937 int HitTestEx(POINT pt, UINT* pFlags) const
3938 {
3939 ATLASSERT(::IsWindow(m_hWnd));
3940 LVHITTESTINFO hti = { 0 };
3941 hti.pt = pt;
3942 int nRes = (int)::SendMessage(m_hWnd, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti);
3943 if (pFlags != NULL)
3944 *pFlags = hti.flags;
3945 return nRes;
3946 }
3947
3948 int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
3949 {
3950 ATLASSERT(::IsWindow(m_hWnd));
3951 return (int)::SendMessage(m_hWnd, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
3952 }
3953 #endif // (_WIN32_WINNT >= 0x0600)
3954
3955 // Note: selects only one item
3956 BOOL SelectItem(int nIndex)
3957 {
3958 ATLASSERT(::IsWindow(m_hWnd));
3959
3960 // multi-selection only: de-select all items
3961 if((GetStyle() & LVS_SINGLESEL) == 0)
3962 SetItemState(-1, 0, LVIS_SELECTED);
3963
3964 BOOL bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
3965 if(bRet)
3966 bRet = EnsureVisible(nIndex, FALSE);
3967
3968 return bRet;
3969 }
3970 };
3971
3972 typedef CListViewCtrlT<ATL::CWindow> CListViewCtrl;
3973
3974
3975 ///////////////////////////////////////////////////////////////////////////////
3976 // CTreeViewCtrl
3977
3978 template <class TBase>
3979 class CTreeViewCtrlT : public TBase
3980 {
3981 public:
3982 // Constructors
3983 CTreeViewCtrlT(HWND hWnd = NULL) : TBase(hWnd)
3984 { }
3985
3986 CTreeViewCtrlT< TBase >& operator =(HWND hWnd)
3987 {
3988 m_hWnd = hWnd;
3989 return *this;
3990 }
3991
3992 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
3993 DWORD dwStyle = 0, DWORD dwExStyle = 0,
3994 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
3995 {
3996 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
3997 }
3998
3999 // Attributes
4000 static LPCTSTR GetWndClassName()
4001 {
4002 return WC_TREEVIEW;
4003 }
4004
4005 UINT GetCount() const
4006 {
4007 ATLASSERT(::IsWindow(m_hWnd));
4008 return (UINT)::SendMessage(m_hWnd, TVM_GETCOUNT, 0, 0L);
4009 }
4010
4011 UINT GetIndent() const
4012 {
4013 ATLASSERT(::IsWindow(m_hWnd));
4014 return (UINT)::SendMessage(m_hWnd, TVM_GETINDENT, 0, 0L);
4015 }
4016
4017 void SetIndent(UINT nIndent)
4018 {
4019 ATLASSERT(::IsWindow(m_hWnd));
4020 ::SendMessage(m_hWnd, TVM_SETINDENT, nIndent, 0L);
4021 }
4022
4023 CImageList GetImageList(int nImageListType = TVSIL_NORMAL) const
4024 {
4025 ATLASSERT(::IsWindow(m_hWnd));
4026 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_GETIMAGELIST, (WPARAM)nImageListType, 0L));
4027 }
4028
4029 CImageList SetImageList(HIMAGELIST hImageList, int nImageListType = TVSIL_NORMAL)
4030 {
4031 ATLASSERT(::IsWindow(m_hWnd));
4032 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageListType, (LPARAM)hImageList));
4033 }
4034
4035 BOOL GetItem(LPTVITEM pItem) const
4036 {
4037 ATLASSERT(::IsWindow(m_hWnd));
4038 return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
4039 }
4040
4041 BOOL SetItem(LPTVITEM pItem)
4042 {
4043 ATLASSERT(::IsWindow(m_hWnd));
4044 return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
4045 }
4046
4047 BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage,
4048 int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
4049 {
4050 ATLASSERT(::IsWindow(m_hWnd));
4051 TVITEM item = { 0 };
4052 item.hItem = hItem;
4053 item.mask = nMask;
4054 item.pszText = (LPTSTR) lpszItem;
4055 item.iImage = nImage;
4056 item.iSelectedImage = nSelectedImage;
4057 item.state = nState;
4058 item.stateMask = nStateMask;
4059 item.lParam = lParam;
4060 return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)&item);
4061 }
4062
4063 BOOL GetItemText(HTREEITEM hItem, LPTSTR lpstrText, int nLen) const
4064 {
4065 ATLASSERT(::IsWindow(m_hWnd));
4066 ATLASSERT(lpstrText != NULL);
4067
4068 TVITEM item = { 0 };
4069 item.hItem = hItem;
4070 item.mask = TVIF_TEXT;
4071 item.pszText = lpstrText;
4072 item.cchTextMax = nLen;
4073
4074 return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4075 }
4076
4077 #ifndef _ATL_NO_COM
4078 BOOL GetItemText(HTREEITEM hItem, BSTR& bstrText) const
4079 {
4080 USES_CONVERSION;
4081 ATLASSERT(::IsWindow(m_hWnd));
4082 ATLASSERT(bstrText == NULL);
4083 TVITEM item = { 0 };
4084 item.hItem = hItem;
4085 item.mask = TVIF_TEXT;
4086
4087 LPTSTR lpstrText = NULL;
4088 BOOL bRet = FALSE;
4089 for(int nLen = 256; ; nLen *= 2)
4090 {
4091 ATLTRY(lpstrText = new TCHAR[nLen]);
4092 if(lpstrText == NULL)
4093 break;
4094 lpstrText[0] = NULL;
4095 item.pszText = lpstrText;
4096 item.cchTextMax = nLen;
4097 bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4098 if(!bRet || (lstrlen(item.pszText) < nLen - 1))
4099 break;
4100 delete [] lpstrText;
4101 lpstrText = NULL;
4102 }
4103
4104 if(lpstrText != NULL)
4105 {
4106 if(bRet)
4107 bstrText = ::SysAllocString(T2OLE(lpstrText));
4108 delete [] lpstrText;
4109 }
4110
4111 return (bstrText != NULL) ? TRUE : FALSE;
4112 }
4113 #endif // !_ATL_NO_COM
4114
4115 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
4116 BOOL GetItemText(HTREEITEM hItem, _CSTRING_NS::CString& strText) const
4117 {
4118 ATLASSERT(::IsWindow(m_hWnd));
4119 TVITEM item = { 0 };
4120 item.hItem = hItem;
4121 item.mask = TVIF_TEXT;
4122
4123 strText.Empty();
4124 BOOL bRet = FALSE;
4125 for(int nLen = 256; ; nLen *= 2)
4126 {
4127 item.pszText = strText.GetBufferSetLength(nLen);
4128 if(item.pszText == NULL)
4129 {
4130 bRet = FALSE;
4131 break;
4132 }
4133 item.cchTextMax = nLen;
4134 bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4135 if(!bRet || (lstrlen(item.pszText) < nLen - 1))
4136 break;
4137 }
4138 strText.ReleaseBuffer();
4139 return bRet;
4140 }
4141 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
4142
4143 BOOL SetItemText(HTREEITEM hItem, LPCTSTR lpszItem)
4144 {
4145 ATLASSERT(::IsWindow(m_hWnd));
4146 return SetItem(hItem, TVIF_TEXT, lpszItem, 0, 0, 0, 0, NULL);
4147 }
4148
4149 BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage) const
4150 {
4151 ATLASSERT(::IsWindow(m_hWnd));
4152 TVITEM item = { 0 };
4153 item.hItem = hItem;
4154 item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE;
4155 BOOL bRes = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4156 if (bRes)
4157 {
4158 nImage = item.iImage;
4159 nSelectedImage = item.iSelectedImage;
4160 }
4161 return bRes;
4162 }
4163
4164 BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage)
4165 {
4166 ATLASSERT(::IsWindow(m_hWnd));
4167 return SetItem(hItem, TVIF_IMAGE|TVIF_SELECTEDIMAGE, NULL, nImage, nSelectedImage, 0, 0, NULL);
4168 }
4169
4170 UINT GetItemState(HTREEITEM hItem, UINT nStateMask) const
4171 {
4172 ATLASSERT(::IsWindow(m_hWnd));
4173 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4174 return (((UINT)::SendMessage(m_hWnd, TVM_GETITEMSTATE, (WPARAM)hItem, (LPARAM)nStateMask)) & nStateMask);
4175 #else // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE))
4176 TVITEM item = { 0 };
4177 item.hItem = hItem;
4178 item.mask = TVIF_STATE;
4179 item.state = 0;
4180 item.stateMask = nStateMask;
4181 ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4182 return (item.state & nStateMask);
4183 #endif // !((_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE))
4184 }
4185
4186 BOOL SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask)
4187 {
4188 ATLASSERT(::IsWindow(m_hWnd));
4189 return SetItem(hItem, TVIF_STATE, NULL, 0, 0, nState, nStateMask, NULL);
4190 }
4191
4192 DWORD_PTR GetItemData(HTREEITEM hItem) const
4193 {
4194 ATLASSERT(::IsWindow(m_hWnd));
4195 TVITEM item = { 0 };
4196 item.hItem = hItem;
4197 item.mask = TVIF_PARAM;
4198 BOOL bRet = (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4199 return (DWORD_PTR)(bRet ? item.lParam : NULL);
4200 }
4201
4202 BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData)
4203 {
4204 ATLASSERT(::IsWindow(m_hWnd));
4205 return SetItem(hItem, TVIF_PARAM, NULL, 0, 0, 0, 0, (LPARAM)dwData);
4206 }
4207
4208 CEdit GetEditControl() const
4209 {
4210 ATLASSERT(::IsWindow(m_hWnd));
4211 return CEdit((HWND)::SendMessage(m_hWnd, TVM_GETEDITCONTROL, 0, 0L));
4212 }
4213
4214 UINT GetVisibleCount() const
4215 {
4216 ATLASSERT(::IsWindow(m_hWnd));
4217 return (UINT)::SendMessage(m_hWnd, TVM_GETVISIBLECOUNT, 0, 0L);
4218 }
4219
4220 BOOL GetItemRect(HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly) const
4221 {
4222 ATLASSERT(::IsWindow(m_hWnd));
4223 *(HTREEITEM*)lpRect = hItem;
4224 return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMRECT, (WPARAM)bTextOnly, (LPARAM)lpRect);
4225 }
4226
4227 BOOL ItemHasChildren(HTREEITEM hItem) const
4228 {
4229 ATLASSERT(::IsWindow(m_hWnd));
4230 TVITEM item = { 0 };
4231 item.hItem = hItem;
4232 item.mask = TVIF_CHILDREN;
4233 ::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)&item);
4234 return item.cChildren;
4235 }
4236
4237 #ifndef _WIN32_WCE
4238 CToolTipCtrl GetToolTips() const
4239 {
4240 ATLASSERT(::IsWindow(m_hWnd));
4241 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L));
4242 }
4243
4244 CToolTipCtrl SetToolTips(HWND hWndTT)
4245 {
4246 ATLASSERT(::IsWindow(m_hWnd));
4247 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
4248 }
4249 #endif // !_WIN32_WCE
4250
4251 int GetISearchString(LPTSTR lpstr) const
4252 {
4253 ATLASSERT(::IsWindow(m_hWnd));
4254 return (int)::SendMessage(m_hWnd, TVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
4255 }
4256
4257 // checkboxes only
4258 BOOL GetCheckState(HTREEITEM hItem) const
4259 {
4260 ATLASSERT(::IsWindow(m_hWnd));
4261 ATLASSERT((GetStyle() & TVS_CHECKBOXES) != 0);
4262 UINT uRet = GetItemState(hItem, TVIS_STATEIMAGEMASK);
4263 return (uRet >> 12) - 1;
4264 }
4265
4266 BOOL SetCheckState(HTREEITEM hItem, BOOL bCheck)
4267 {
4268 int nCheck = bCheck ? 2 : 1; // one based index
4269 return SetItemState(hItem, INDEXTOSTATEIMAGEMASK(nCheck), TVIS_STATEIMAGEMASK);
4270 }
4271
4272 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4273 COLORREF GetBkColor() const
4274 {
4275 ATLASSERT(::IsWindow(m_hWnd));
4276 return (COLORREF)::SendMessage(m_hWnd, TVM_GETBKCOLOR, 0, 0L);
4277 }
4278
4279 COLORREF SetBkColor(COLORREF clr)
4280 {
4281 ATLASSERT(::IsWindow(m_hWnd));
4282 return (COLORREF)::SendMessage(m_hWnd, TVM_SETBKCOLOR, 0, (LPARAM)clr);
4283 }
4284
4285 COLORREF GetInsertMarkColor() const
4286 {
4287 ATLASSERT(::IsWindow(m_hWnd));
4288 return (COLORREF)::SendMessage(m_hWnd, TVM_GETINSERTMARKCOLOR, 0, 0L);
4289 }
4290
4291 COLORREF SetInsertMarkColor(COLORREF clr)
4292 {
4293 ATLASSERT(::IsWindow(m_hWnd));
4294 return (COLORREF)::SendMessage(m_hWnd, TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
4295 }
4296
4297 int GetItemHeight() const
4298 {
4299 ATLASSERT(::IsWindow(m_hWnd));
4300 return (int)::SendMessage(m_hWnd, TVM_GETITEMHEIGHT, 0, 0L);
4301 }
4302
4303 int SetItemHeight(int cyHeight)
4304 {
4305 ATLASSERT(::IsWindow(m_hWnd));
4306 return (int)::SendMessage(m_hWnd, TVM_SETITEMHEIGHT, cyHeight, 0L);
4307 }
4308
4309 int GetScrollTime() const
4310 {
4311 ATLASSERT(::IsWindow(m_hWnd));
4312 return (int)::SendMessage(m_hWnd, TVM_GETSCROLLTIME, 0, 0L);
4313 }
4314
4315 int SetScrollTime(int nScrollTime)
4316 {
4317 ATLASSERT(::IsWindow(m_hWnd));
4318 return (int)::SendMessage(m_hWnd, TVM_SETSCROLLTIME, nScrollTime, 0L);
4319 }
4320
4321 COLORREF GetTextColor() const
4322 {
4323 ATLASSERT(::IsWindow(m_hWnd));
4324 return (COLORREF)::SendMessage(m_hWnd, TVM_GETTEXTCOLOR, 0, 0L);
4325 }
4326
4327 COLORREF SetTextColor(COLORREF clr)
4328 {
4329 ATLASSERT(::IsWindow(m_hWnd));
4330 return (COLORREF)::SendMessage(m_hWnd, TVM_SETTEXTCOLOR, 0, (LPARAM)clr);
4331 }
4332
4333 BOOL GetUnicodeFormat() const
4334 {
4335 ATLASSERT(::IsWindow(m_hWnd));
4336 return (BOOL)::SendMessage(m_hWnd, TVM_GETUNICODEFORMAT, 0, 0L);
4337 }
4338
4339 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
4340 {
4341 ATLASSERT(::IsWindow(m_hWnd));
4342 return (BOOL)::SendMessage(m_hWnd, TVM_SETUNICODEFORMAT, bUnicode, 0L);
4343 }
4344 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4345
4346 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4347 COLORREF GetLineColor() const
4348 {
4349 ATLASSERT(::IsWindow(m_hWnd));
4350 return (COLORREF)::SendMessage(m_hWnd, TVM_GETLINECOLOR, 0, 0L);
4351 }
4352
4353 COLORREF SetLineColor(COLORREF clrNew /*= CLR_DEFAULT*/)
4354 {
4355 ATLASSERT(::IsWindow(m_hWnd));
4356 return (COLORREF)::SendMessage(m_hWnd, TVM_SETLINECOLOR, 0, (LPARAM)clrNew);
4357 }
4358 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4359
4360 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4361 BOOL GetItem(LPTVITEMEX pItem) const
4362 {
4363 ATLASSERT(::IsWindow(m_hWnd));
4364 return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem);
4365 }
4366
4367 BOOL SetItem(LPTVITEMEX pItem)
4368 {
4369 ATLASSERT(::IsWindow(m_hWnd));
4370 return (BOOL)::SendMessage(m_hWnd, TVM_SETITEM, 0, (LPARAM)pItem);
4371 }
4372 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4373
4374 DWORD GetExtendedStyle() const
4375 {
4376 #ifndef TVM_GETEXTENDEDSTYLE
4377 const UINT TVM_GETEXTENDEDSTYLE = (TV_FIRST + 45);
4378 #endif
4379 ATLASSERT(::IsWindow(m_hWnd));
4380 return (DWORD)::SendMessage(m_hWnd, TVM_GETEXTENDEDSTYLE, 0, 0L);
4381 }
4382
4383 DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
4384 {
4385 #ifndef TVM_SETEXTENDEDSTYLE
4386 const UINT TVM_SETEXTENDEDSTYLE = (TV_FIRST + 44);
4387 #endif
4388 ATLASSERT(::IsWindow(m_hWnd));
4389 return (DWORD)::SendMessage(m_hWnd, TVM_SETEXTENDEDSTYLE, dwMask, dwStyle);
4390 }
4391
4392 #if (_WIN32_WINNT >= 0x0600)
4393 BOOL SetAutoScrollInfo(UINT uPixPerSec, UINT uUpdateTime)
4394 {
4395 ATLASSERT(::IsWindow(m_hWnd));
4396 return (BOOL)::SendMessage(m_hWnd, TVM_SETAUTOSCROLLINFO, (WPARAM)uPixPerSec, (LPARAM)uUpdateTime);
4397 }
4398
4399 DWORD GetSelectedCount() const
4400 {
4401 ATLASSERT(::IsWindow(m_hWnd));
4402 return (DWORD)::SendMessage(m_hWnd, TVM_GETSELECTEDCOUNT, 0, 0L);
4403 }
4404
4405 BOOL GetItemPartRect(HTREEITEM hItem, TVITEMPART partID, LPRECT lpRect) const
4406 {
4407 ATLASSERT(::IsWindow(m_hWnd));
4408 TVGETITEMPARTRECTINFO gipri = { hItem, lpRect, partID };
4409 return (BOOL)::SendMessage(m_hWnd, TVM_GETITEMPARTRECT, 0, (LPARAM)&gipri);
4410 }
4411 #endif // (_WIN32_WINNT >= 0x0600)
4412
4413 // Operations
4414 HTREEITEM InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
4415 {
4416 ATLASSERT(::IsWindow(m_hWnd));
4417 return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
4418 }
4419
4420 HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage,
4421 int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
4422 {
4423 ATLASSERT(::IsWindow(m_hWnd));
4424 return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter);
4425 }
4426
4427 HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
4428 {
4429 ATLASSERT(::IsWindow(m_hWnd));
4430 return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
4431 }
4432
4433 HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
4434 int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
4435 HTREEITEM hParent, HTREEITEM hInsertAfter)
4436 {
4437 ATLASSERT(::IsWindow(m_hWnd));
4438 TVINSERTSTRUCT tvis = { 0 };
4439 tvis.hParent = hParent;
4440 tvis.hInsertAfter = hInsertAfter;
4441 tvis.item.mask = nMask;
4442 tvis.item.pszText = (LPTSTR) lpszItem;
4443 tvis.item.iImage = nImage;
4444 tvis.item.iSelectedImage = nSelectedImage;
4445 tvis.item.state = nState;
4446 tvis.item.stateMask = nStateMask;
4447 tvis.item.lParam = lParam;
4448 return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
4449 }
4450
4451 BOOL DeleteItem(HTREEITEM hItem)
4452 {
4453 ATLASSERT(::IsWindow(m_hWnd));
4454 return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)hItem);
4455 }
4456
4457 BOOL DeleteAllItems()
4458 {
4459 ATLASSERT(::IsWindow(m_hWnd));
4460 return (BOOL)::SendMessage(m_hWnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
4461 }
4462
4463 BOOL Expand(HTREEITEM hItem, UINT nCode = TVE_EXPAND)
4464 {
4465 ATLASSERT(::IsWindow(m_hWnd));
4466 return (BOOL)::SendMessage(m_hWnd, TVM_EXPAND, nCode, (LPARAM)hItem);
4467 }
4468
4469 HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const
4470 {
4471 ATLASSERT(::IsWindow(m_hWnd));
4472 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
4473 }
4474
4475 HTREEITEM GetChildItem(HTREEITEM hItem) const
4476 {
4477 ATLASSERT(::IsWindow(m_hWnd));
4478 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
4479 }
4480
4481 HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const
4482 {
4483 ATLASSERT(::IsWindow(m_hWnd));
4484 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
4485 }
4486
4487 HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const
4488 {
4489 ATLASSERT(::IsWindow(m_hWnd));
4490 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
4491 }
4492
4493 HTREEITEM GetParentItem(HTREEITEM hItem) const
4494 {
4495 ATLASSERT(::IsWindow(m_hWnd));
4496 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
4497 }
4498
4499 HTREEITEM GetFirstVisibleItem() const
4500 {
4501 ATLASSERT(::IsWindow(m_hWnd));
4502 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
4503 }
4504
4505 HTREEITEM GetNextVisibleItem(HTREEITEM hItem) const
4506 {
4507 ATLASSERT(::IsWindow(m_hWnd));
4508 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
4509 }
4510
4511 HTREEITEM GetPrevVisibleItem(HTREEITEM hItem) const
4512 {
4513 ATLASSERT(::IsWindow(m_hWnd));
4514 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
4515 }
4516
4517 HTREEITEM GetSelectedItem() const
4518 {
4519 ATLASSERT(::IsWindow(m_hWnd));
4520 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
4521 }
4522
4523 HTREEITEM GetDropHilightItem() const
4524 {
4525 ATLASSERT(::IsWindow(m_hWnd));
4526 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
4527 }
4528
4529 HTREEITEM GetRootItem() const
4530 {
4531 ATLASSERT(::IsWindow(m_hWnd));
4532 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
4533 }
4534
4535 #if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
4536 HTREEITEM GetLastVisibleItem() const
4537 {
4538 ATLASSERT(::IsWindow(m_hWnd));
4539 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
4540 }
4541 #endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
4542
4543 #if (_WIN32_IE >= 0x0600)
4544 HTREEITEM GetNextSelectedItem() const
4545 {
4546 #ifndef TVGN_NEXTSELECTED
4547 const WORD TVGN_NEXTSELECTED = 0x000B;
4548 #endif
4549 ATLASSERT(::IsWindow(m_hWnd));
4550 return (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L);
4551 }
4552 #endif // (_WIN32_IE >= 0x0600)
4553
4554 BOOL Select(HTREEITEM hItem, UINT nCode)
4555 {
4556 ATLASSERT(::IsWindow(m_hWnd));
4557 return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, nCode, (LPARAM)hItem);
4558 }
4559
4560 BOOL SelectItem(HTREEITEM hItem)
4561 {
4562 ATLASSERT(::IsWindow(m_hWnd));
4563 return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem);
4564 }
4565
4566 BOOL SelectDropTarget(HTREEITEM hItem)
4567 {
4568 ATLASSERT(::IsWindow(m_hWnd));
4569 return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItem);
4570 }
4571
4572 BOOL SelectSetFirstVisible(HTREEITEM hItem)
4573 {
4574 ATLASSERT(::IsWindow(m_hWnd));
4575 return (BOOL)::SendMessage(m_hWnd, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hItem);
4576 }
4577
4578 CEdit EditLabel(HTREEITEM hItem)
4579 {
4580 ATLASSERT(::IsWindow(m_hWnd));
4581 return CEdit((HWND)::SendMessage(m_hWnd, TVM_EDITLABEL, 0, (LPARAM)hItem));
4582 }
4583
4584 BOOL EndEditLabelNow(BOOL bCancel)
4585 {
4586 ATLASSERT(::IsWindow(m_hWnd));
4587 return (BOOL)::SendMessage(m_hWnd, TVM_ENDEDITLABELNOW, bCancel, 0L);
4588 }
4589
4590 HTREEITEM HitTest(TVHITTESTINFO* pHitTestInfo) const
4591 {
4592 ATLASSERT(::IsWindow(m_hWnd));
4593 return (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
4594 }
4595
4596 HTREEITEM HitTest(POINT pt, UINT* pFlags) const
4597 {
4598 ATLASSERT(::IsWindow(m_hWnd));
4599 TVHITTESTINFO hti = { 0 };
4600 hti.pt = pt;
4601 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
4602 if (pFlags != NULL)
4603 *pFlags = hti.flags;
4604 return hTreeItem;
4605 }
4606
4607 BOOL SortChildren(HTREEITEM hItem, BOOL bRecurse = FALSE)
4608 {
4609 ATLASSERT(::IsWindow(m_hWnd));
4610 return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDREN, (WPARAM)bRecurse, (LPARAM)hItem);
4611 }
4612
4613 BOOL EnsureVisible(HTREEITEM hItem)
4614 {
4615 ATLASSERT(::IsWindow(m_hWnd));
4616 return (BOOL)::SendMessage(m_hWnd, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem);
4617 }
4618
4619 BOOL SortChildrenCB(LPTVSORTCB pSort, BOOL bRecurse = FALSE)
4620 {
4621 ATLASSERT(::IsWindow(m_hWnd));
4622 return (BOOL)::SendMessage(m_hWnd, TVM_SORTCHILDRENCB, (WPARAM)bRecurse, (LPARAM)pSort);
4623 }
4624
4625 CImageList RemoveImageList(int nImageList)
4626 {
4627 ATLASSERT(::IsWindow(m_hWnd));
4628 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList, NULL));
4629 }
4630
4631 CImageList CreateDragImage(HTREEITEM hItem)
4632 {
4633 ATLASSERT(::IsWindow(m_hWnd));
4634 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItem));
4635 }
4636
4637 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4638 BOOL SetInsertMark(HTREEITEM hTreeItem, BOOL bAfter)
4639 {
4640 ATLASSERT(::IsWindow(m_hWnd));
4641 return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, bAfter, (LPARAM)hTreeItem);
4642 }
4643
4644 BOOL RemoveInsertMark()
4645 {
4646 ATLASSERT(::IsWindow(m_hWnd));
4647 return (BOOL)::SendMessage(m_hWnd, TVM_SETINSERTMARK, 0, 0L);
4648 }
4649 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4650
4651 #if (_WIN32_WINNT >= 0x0501)
4652 HTREEITEM MapAccIDToHTREEITEM(UINT uID) const
4653 {
4654 ATLASSERT(::IsWindow(m_hWnd));
4655 return (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
4656 }
4657
4658 UINT MapHTREEITEMToAccID(HTREEITEM hTreeItem) const
4659 {
4660 ATLASSERT(::IsWindow(m_hWnd));
4661 return (UINT)::SendMessage(m_hWnd, TVM_MAPHTREEITEMTOACCID, (WPARAM)hTreeItem, 0L);
4662 }
4663 #endif // (_WIN32_WINNT >= 0x0501)
4664
4665 #if (_WIN32_WINNT >= 0x0600)
4666 void ShowInfoTip(HTREEITEM hItem)
4667 {
4668 ATLASSERT(::IsWindow(m_hWnd));
4669 ::SendMessage(m_hWnd, TVM_SHOWINFOTIP, 0, (LPARAM)hItem);
4670 }
4671 #endif // (_WIN32_WINNT >= 0x0600)
4672 };
4673
4674 typedef CTreeViewCtrlT<ATL::CWindow> CTreeViewCtrl;
4675
4676
4677 ///////////////////////////////////////////////////////////////////////////////
4678 // CTreeViewCtrlEx
4679
4680 // forward declaration
4681 template <class TBase> class CTreeViewCtrlExT;
4682
4683 // Note: TBase here is for CTreeViewCtrlExT, and not for CTreeItemT itself
4684 template <class TBase>
4685 class CTreeItemT
4686 {
4687 public:
4688 HTREEITEM m_hTreeItem;
4689 CTreeViewCtrlExT<TBase>* m_pTreeView;
4690
4691 // Construction
4692 CTreeItemT(HTREEITEM hTreeItem = NULL, CTreeViewCtrlExT<TBase>* pTreeView = NULL) : m_hTreeItem(hTreeItem), m_pTreeView(pTreeView)
4693 { }
4694
4695 CTreeItemT(const CTreeItemT<TBase>& posSrc)
4696 {
4697 *this = posSrc;
4698 }
4699
4700 operator HTREEITEM() { return m_hTreeItem; }
4701
4702 CTreeItemT<TBase>& operator =(const CTreeItemT<TBase>& itemSrc)
4703 {
4704 m_hTreeItem = itemSrc.m_hTreeItem;
4705 m_pTreeView = itemSrc.m_pTreeView;
4706 return *this;
4707 }
4708
4709 // Attributes
4710 CTreeViewCtrlExT<TBase>* GetTreeView() const { return m_pTreeView; }
4711
4712 BOOL operator !() const { return m_hTreeItem == NULL; }
4713
4714 BOOL IsNull() const { return m_hTreeItem == NULL; }
4715
4716 BOOL GetRect(LPRECT lpRect, BOOL bTextOnly) const;
4717 BOOL GetText(LPTSTR lpstrText, int nLen) const;
4718 #ifndef _ATL_NO_COM
4719 BOOL GetText(BSTR& bstrText) const;
4720 #endif // !_ATL_NO_COM
4721 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
4722 BOOL GetText(_CSTRING_NS::CString& strText) const;
4723 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
4724 BOOL SetText(LPCTSTR lpszItem);
4725 BOOL GetImage(int& nImage, int& nSelectedImage) const;
4726 BOOL SetImage(int nImage, int nSelectedImage);
4727 UINT GetState(UINT nStateMask) const;
4728 BOOL SetState(UINT nState, UINT nStateMask);
4729 DWORD_PTR GetData() const;
4730 BOOL SetData(DWORD_PTR dwData);
4731 BOOL SetItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam);
4732
4733 // Operations
4734 CTreeItemT<TBase> InsertAfter(LPCTSTR lpstrItem, HTREEITEM hItemAfter, int nImageIndex)
4735 {
4736 return _Insert(lpstrItem, nImageIndex, hItemAfter);
4737 }
4738
4739 CTreeItemT<TBase> AddHead(LPCTSTR lpstrItem, int nImageIndex)
4740 {
4741 return _Insert(lpstrItem, nImageIndex, TVI_FIRST);
4742 }
4743
4744 CTreeItemT<TBase> AddTail(LPCTSTR lpstrItem, int nImageIndex)
4745 {
4746 return _Insert(lpstrItem, nImageIndex, TVI_LAST);
4747 }
4748
4749 CTreeItemT<TBase> GetChild() const;
4750 CTreeItemT<TBase> GetNext(UINT nCode) const;
4751 CTreeItemT<TBase> GetNextSibling() const;
4752 CTreeItemT<TBase> GetPrevSibling() const;
4753 CTreeItemT<TBase> GetParent() const;
4754 CTreeItemT<TBase> GetFirstVisible() const;
4755 CTreeItemT<TBase> GetNextVisible() const;
4756 CTreeItemT<TBase> GetPrevVisible() const;
4757 CTreeItemT<TBase> GetSelected() const;
4758 CTreeItemT<TBase> GetDropHilight() const;
4759 CTreeItemT<TBase> GetRoot() const;
4760 #if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
4761 CTreeItemT<TBase> GetLastVisible() const;
4762 #endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
4763 #if (_WIN32_IE >= 0x0600)
4764 CTreeItemT<TBase> GetNextSelected() const;
4765 #endif // (_WIN32_IE >= 0x0600)
4766 BOOL HasChildren() const;
4767 BOOL Delete();
4768 BOOL Expand(UINT nCode = TVE_EXPAND);
4769 BOOL Select(UINT nCode);
4770 BOOL Select();
4771 BOOL SelectDropTarget();
4772 BOOL SelectSetFirstVisible();
4773 HWND EditLabel();
4774 HIMAGELIST CreateDragImage();
4775 BOOL SortChildren(BOOL bRecurse = FALSE);
4776 BOOL EnsureVisible();
4777 CTreeItemT<TBase> _Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter);
4778 int GetImageIndex() const;
4779 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4780 BOOL SetInsertMark(BOOL bAfter);
4781 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4782 #if (_WIN32_WINNT >= 0x0501)
4783 UINT MapHTREEITEMToAccID() const;
4784 #endif // (_WIN32_WINNT >= 0x0501)
4785 #if (_WIN32_WINNT >= 0x0600)
4786 void ShowInfoTip();
4787 BOOL GetPartRect(TVITEMPART partID, LPRECT lpRect) const;
4788 #endif // (_WIN32_WINNT >= 0x0600)
4789 };
4790
4791 typedef CTreeItemT<ATL::CWindow> CTreeItem;
4792
4793
4794 template <class TBase>
4795 class CTreeViewCtrlExT : public CTreeViewCtrlT< TBase >
4796 {
4797 public:
4798 // Constructors
4799 CTreeViewCtrlExT(HWND hWnd = NULL) : CTreeViewCtrlT< TBase >(hWnd)
4800 { }
4801
4802 CTreeViewCtrlExT< TBase >& operator =(HWND hWnd)
4803 {
4804 m_hWnd = hWnd;
4805 return *this;
4806 }
4807
4808 // Operations (overides that return CTreeItem)
4809 CTreeItemT<TBase> InsertItem(LPTVINSERTSTRUCT lpInsertStruct)
4810 {
4811 ATLASSERT(::IsWindow(m_hWnd));
4812 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)lpInsertStruct);
4813 return CTreeItemT<TBase>(hTreeItem, this);
4814 }
4815
4816 CTreeItemT<TBase> InsertItem(LPCTSTR lpszItem, int nImage,
4817 int nSelectedImage, HTREEITEM hParent, HTREEITEM hInsertAfter)
4818 {
4819 ATLASSERT(::IsWindow(m_hWnd));
4820 return InsertItem(TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE, lpszItem, nImage, nSelectedImage, 0, 0, 0, hParent, hInsertAfter);
4821 }
4822
4823 CTreeItemT<TBase> InsertItem(LPCTSTR lpszItem, HTREEITEM hParent, HTREEITEM hInsertAfter)
4824 {
4825 ATLASSERT(::IsWindow(m_hWnd));
4826 return InsertItem(TVIF_TEXT, lpszItem, 0, 0, 0, 0, 0, hParent, hInsertAfter);
4827 }
4828
4829 CTreeItemT<TBase> GetNextItem(HTREEITEM hItem, UINT nCode) const
4830 {
4831 ATLASSERT(::IsWindow(m_hWnd));
4832 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, nCode, (LPARAM)hItem);
4833 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4834 }
4835
4836 CTreeItemT<TBase> GetChildItem(HTREEITEM hItem) const
4837 {
4838 ATLASSERT(::IsWindow(m_hWnd));
4839 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
4840 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4841 }
4842
4843 CTreeItemT<TBase> GetNextSiblingItem(HTREEITEM hItem) const
4844 {
4845 ATLASSERT(::IsWindow(m_hWnd));
4846 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
4847 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4848 }
4849
4850 CTreeItemT<TBase> GetPrevSiblingItem(HTREEITEM hItem) const
4851 {
4852 ATLASSERT(::IsWindow(m_hWnd));
4853 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)hItem);
4854 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4855 }
4856
4857 CTreeItemT<TBase> GetParentItem(HTREEITEM hItem) const
4858 {
4859 ATLASSERT(::IsWindow(m_hWnd));
4860 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
4861 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4862 }
4863
4864 CTreeItemT<TBase> GetFirstVisibleItem() const
4865 {
4866 ATLASSERT(::IsWindow(m_hWnd));
4867 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0L);
4868 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4869 }
4870
4871 CTreeItemT<TBase> GetNextVisibleItem(HTREEITEM hItem) const
4872 {
4873 ATLASSERT(::IsWindow(m_hWnd));
4874 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)hItem);
4875 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4876 }
4877
4878 CTreeItemT<TBase> GetPrevVisibleItem(HTREEITEM hItem) const
4879 {
4880 ATLASSERT(::IsWindow(m_hWnd));
4881 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItem);
4882 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4883 }
4884
4885 CTreeItemT<TBase> GetSelectedItem() const
4886 {
4887 ATLASSERT(::IsWindow(m_hWnd));
4888 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0L);
4889 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4890 }
4891
4892 CTreeItemT<TBase> GetDropHilightItem() const
4893 {
4894 ATLASSERT(::IsWindow(m_hWnd));
4895 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0L);
4896 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4897 }
4898
4899 CTreeItemT<TBase> GetRootItem() const
4900 {
4901 ATLASSERT(::IsWindow(m_hWnd));
4902 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0L);
4903 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4904 }
4905
4906 #if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
4907 CTreeItemT<TBase> GetLastVisibleItem() const
4908 {
4909 ATLASSERT(::IsWindow(m_hWnd));
4910 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
4911 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4912 }
4913 #endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
4914
4915 #if (_WIN32_IE >= 0x0600)
4916 CTreeItemT<TBase> GetNextSelectedItem() const
4917 {
4918 #ifndef TVGN_NEXTSELECTED
4919 const WORD TVGN_NEXTSELECTED = 0x000B;
4920 #endif
4921 ATLASSERT(::IsWindow(m_hWnd));
4922 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_NEXTSELECTED, 0L);
4923 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4924 }
4925 #endif // (_WIN32_IE >= 0x0600)
4926
4927 CTreeItemT<TBase> HitTest(TVHITTESTINFO* pHitTestInfo) const
4928 {
4929 ATLASSERT(::IsWindow(m_hWnd));
4930 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)pHitTestInfo);
4931 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4932 }
4933
4934 CTreeItemT<TBase> InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
4935 int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
4936 HTREEITEM hParent, HTREEITEM hInsertAfter)
4937 {
4938 ATLASSERT(::IsWindow(m_hWnd));
4939 TVINSERTSTRUCT tvis = { 0 };
4940 tvis.hParent = hParent;
4941 tvis.hInsertAfter = hInsertAfter;
4942 tvis.item.mask = nMask;
4943 tvis.item.pszText = (LPTSTR) lpszItem;
4944 tvis.item.iImage = nImage;
4945 tvis.item.iSelectedImage = nSelectedImage;
4946 tvis.item.state = nState;
4947 tvis.item.stateMask = nStateMask;
4948 tvis.item.lParam = lParam;
4949 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
4950 return CTreeItemT<TBase>(hTreeItem, this);
4951 }
4952
4953 CTreeItemT<TBase> HitTest(POINT pt, UINT* pFlags) const
4954 {
4955 ATLASSERT(::IsWindow(m_hWnd));
4956 TVHITTESTINFO hti = { 0 };
4957 hti.pt = pt;
4958 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_HITTEST, 0, (LPARAM)&hti);
4959 if (pFlags != NULL)
4960 *pFlags = hti.flags;
4961 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4962 }
4963
4964 #if (_WIN32_WINNT >= 0x0501)
4965 CTreeItemT<TBase> MapAccIDToHTREEITEM(UINT uID) const
4966 {
4967 ATLASSERT(::IsWindow(m_hWnd));
4968 HTREEITEM hTreeItem = (HTREEITEM)::SendMessage(m_hWnd, TVM_MAPACCIDTOHTREEITEM, uID, 0L);
4969 return CTreeItemT<TBase>(hTreeItem, (CTreeViewCtrlExT<TBase>*)this);
4970 }
4971 #endif // (_WIN32_WINNT >= 0x0501)
4972 };
4973
4974 typedef CTreeViewCtrlExT<ATL::CWindow> CTreeViewCtrlEx;
4975
4976
4977 // CTreeItem inline methods
4978 template <class TBase>
4979 inline BOOL CTreeItemT<TBase>::GetRect(LPRECT lpRect, BOOL bTextOnly) const
4980 {
4981 ATLASSERT(m_pTreeView != NULL);
4982 return m_pTreeView->GetItemRect(m_hTreeItem,lpRect,bTextOnly);
4983 }
4984
4985 template <class TBase>
4986 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNext(UINT nCode) const
4987 {
4988 ATLASSERT(m_pTreeView != NULL);
4989 return m_pTreeView->GetNextItem(m_hTreeItem,nCode);
4990 }
4991
4992 template <class TBase>
4993 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetChild() const
4994 {
4995 ATLASSERT(m_pTreeView != NULL);
4996 return m_pTreeView->GetChildItem(m_hTreeItem);
4997 }
4998
4999 template <class TBase>
5000 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextSibling() const
5001 {
5002 ATLASSERT(m_pTreeView != NULL);
5003 return m_pTreeView->GetNextSiblingItem(m_hTreeItem);
5004 }
5005
5006 template <class TBase>
5007 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetPrevSibling() const
5008 {
5009 ATLASSERT(m_pTreeView != NULL);
5010 return m_pTreeView->GetPrevSiblingItem(m_hTreeItem);
5011 }
5012
5013 template <class TBase>
5014 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetParent() const
5015 {
5016 ATLASSERT(m_pTreeView != NULL);
5017 return m_pTreeView->GetParentItem(m_hTreeItem);
5018 }
5019
5020 template <class TBase>
5021 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetFirstVisible() const
5022 {
5023 ATLASSERT(m_pTreeView != NULL);
5024 return m_pTreeView->GetFirstVisibleItem();
5025 }
5026
5027 template <class TBase>
5028 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextVisible() const
5029 {
5030 ATLASSERT(m_pTreeView != NULL);
5031 return m_pTreeView->GetNextVisibleItem(m_hTreeItem);
5032 }
5033
5034 template <class TBase>
5035 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetPrevVisible() const
5036 {
5037 ATLASSERT(m_pTreeView != NULL);
5038 return m_pTreeView->GetPrevVisibleItem(m_hTreeItem);
5039 }
5040
5041 template <class TBase>
5042 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetSelected() const
5043 {
5044 ATLASSERT(m_pTreeView != NULL);
5045 return m_pTreeView->GetSelectedItem();
5046 }
5047
5048 template <class TBase>
5049 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetDropHilight() const
5050 {
5051 ATLASSERT(m_pTreeView != NULL);
5052 return m_pTreeView->GetDropHilightItem();
5053 }
5054
5055 template <class TBase>
5056 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetRoot() const
5057 {
5058 ATLASSERT(m_pTreeView != NULL);
5059 return m_pTreeView->GetRootItem();
5060 }
5061
5062 #if !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
5063 template <class TBase>
5064 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetLastVisible() const
5065 {
5066 ATLASSERT(m_pTreeView != NULL);
5067 return m_pTreeView->GetLastVisibleItem();
5068 }
5069 #endif // !defined(_WIN32_WCE) && (_WIN32_IE >= 0x0400)
5070
5071 #if (_WIN32_IE >= 0x0600)
5072 template <class TBase>
5073 inline CTreeItemT<TBase> CTreeItemT<TBase>::GetNextSelected() const
5074 {
5075 ATLASSERT(m_pTreeView != NULL);
5076 return m_pTreeView->GetNextSelectedItem();
5077 }
5078 #endif // (_WIN32_IE >= 0x0600)
5079
5080 template <class TBase>
5081 inline BOOL CTreeItemT<TBase>::GetText(LPTSTR lpstrText, int nLen) const
5082 {
5083 ATLASSERT(m_pTreeView != NULL);
5084 return m_pTreeView->GetItemText(m_hTreeItem, lpstrText, nLen);
5085 }
5086
5087 #ifndef _ATL_NO_COM
5088 #ifdef _OLEAUTO_H_
5089 template <class TBase>
5090 inline BOOL CTreeItemT<TBase>::GetText(BSTR& bstrText) const
5091 {
5092 ATLASSERT(m_pTreeView != NULL);
5093 return m_pTreeView->GetItemText(m_hTreeItem, bstrText);
5094 }
5095 #endif // _OLEAUTO_H_
5096 #endif // !_ATL_NO_COM
5097
5098 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
5099 template <class TBase>
5100 inline BOOL CTreeItemT<TBase>::GetText(_CSTRING_NS::CString& strText) const
5101 {
5102 ATLASSERT(m_pTreeView != NULL);
5103 return m_pTreeView->GetItemText(m_hTreeItem, strText);
5104 }
5105 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
5106
5107 template <class TBase>
5108 inline BOOL CTreeItemT<TBase>::GetImage(int& nImage, int& nSelectedImage) const
5109 {
5110 ATLASSERT(m_pTreeView != NULL);
5111 return m_pTreeView->GetItemImage(m_hTreeItem,nImage,nSelectedImage);
5112 }
5113
5114 template <class TBase>
5115 inline UINT CTreeItemT<TBase>::GetState(UINT nStateMask) const
5116 {
5117 ATLASSERT(m_pTreeView != NULL);
5118 return m_pTreeView->GetItemState(m_hTreeItem,nStateMask);
5119 }
5120
5121 template <class TBase>
5122 inline DWORD_PTR CTreeItemT<TBase>::GetData() const
5123 {
5124 ATLASSERT(m_pTreeView != NULL);
5125 return m_pTreeView->GetItemData(m_hTreeItem);
5126 }
5127
5128 template <class TBase>
5129 inline BOOL CTreeItemT<TBase>::SetItem(UINT nMask, LPCTSTR lpszItem, int nImage,
5130 int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam)
5131 {
5132 ATLASSERT(m_pTreeView != NULL);
5133 return m_pTreeView->SetItem(m_hTreeItem, nMask, lpszItem, nImage, nSelectedImage, nState, nStateMask, lParam);
5134 }
5135
5136 template <class TBase>
5137 inline BOOL CTreeItemT<TBase>::SetText(LPCTSTR lpszItem)
5138 {
5139 ATLASSERT(m_pTreeView != NULL);
5140 return m_pTreeView->SetItemText(m_hTreeItem,lpszItem);
5141 }
5142
5143 template <class TBase>
5144 inline BOOL CTreeItemT<TBase>::SetImage(int nImage, int nSelectedImage)
5145 {
5146 ATLASSERT(m_pTreeView != NULL);
5147 return m_pTreeView->SetItemImage(m_hTreeItem,nImage,nSelectedImage);
5148 }
5149
5150 template <class TBase>
5151 inline BOOL CTreeItemT<TBase>::SetState(UINT nState, UINT nStateMask)
5152 {
5153 ATLASSERT(m_pTreeView != NULL);
5154 return m_pTreeView->SetItemState(m_hTreeItem,nState,nStateMask);
5155 }
5156
5157 template <class TBase>
5158 inline BOOL CTreeItemT<TBase>::SetData(DWORD_PTR dwData)
5159 {
5160 ATLASSERT(m_pTreeView != NULL);
5161 return m_pTreeView->SetItemData(m_hTreeItem,dwData);
5162 }
5163
5164 template <class TBase>
5165 inline BOOL CTreeItemT<TBase>::HasChildren() const
5166 {
5167 ATLASSERT(m_pTreeView != NULL);
5168 return m_pTreeView->ItemHasChildren(m_hTreeItem);
5169 }
5170
5171 template <class TBase>
5172 inline BOOL CTreeItemT<TBase>::Delete()
5173 {
5174 ATLASSERT(m_pTreeView != NULL);
5175 return m_pTreeView->DeleteItem(m_hTreeItem);
5176 }
5177
5178 template <class TBase>
5179 inline BOOL CTreeItemT<TBase>::Expand(UINT nCode /*= TVE_EXPAND*/)
5180 {
5181 ATLASSERT(m_pTreeView != NULL);
5182 return m_pTreeView->Expand(m_hTreeItem,nCode);
5183 }
5184
5185 template <class TBase>
5186 inline BOOL CTreeItemT<TBase>::Select(UINT nCode)
5187 {
5188 ATLASSERT(m_pTreeView != NULL);
5189 return m_pTreeView->Select(m_hTreeItem,nCode);
5190 }
5191
5192 template <class TBase>
5193 inline BOOL CTreeItemT<TBase>::Select()
5194 {
5195 ATLASSERT(m_pTreeView != NULL);
5196 return m_pTreeView->SelectItem(m_hTreeItem);
5197 }
5198
5199 template <class TBase>
5200 inline BOOL CTreeItemT<TBase>::SelectDropTarget()
5201 {
5202 ATLASSERT(m_pTreeView != NULL);
5203 return m_pTreeView->SelectDropTarget(m_hTreeItem);
5204 }
5205
5206 template <class TBase>
5207 inline BOOL CTreeItemT<TBase>::SelectSetFirstVisible()
5208 {
5209 ATLASSERT(m_pTreeView != NULL);
5210 return m_pTreeView->SelectSetFirstVisible(m_hTreeItem);
5211 }
5212
5213 template <class TBase>
5214 inline HWND CTreeItemT<TBase>::EditLabel()
5215 {
5216 ATLASSERT(m_pTreeView != NULL);
5217 return m_pTreeView->EditLabel(m_hTreeItem);
5218 }
5219
5220 template <class TBase>
5221 inline HIMAGELIST CTreeItemT<TBase>::CreateDragImage()
5222 {
5223 ATLASSERT(m_pTreeView != NULL);
5224 return m_pTreeView->CreateDragImage(m_hTreeItem);
5225 }
5226
5227 template <class TBase>
5228 inline BOOL CTreeItemT<TBase>::SortChildren(BOOL bRecurse /*= FALSE*/)
5229 {
5230 ATLASSERT(m_pTreeView != NULL);
5231 return m_pTreeView->SortChildren(m_hTreeItem, bRecurse);
5232 }
5233
5234 template <class TBase>
5235 inline BOOL CTreeItemT<TBase>::EnsureVisible()
5236 {
5237 ATLASSERT(m_pTreeView != NULL);
5238 return m_pTreeView->EnsureVisible(m_hTreeItem);
5239 }
5240
5241 template <class TBase>
5242 inline CTreeItemT<TBase> CTreeItemT<TBase>::_Insert(LPCTSTR lpstrItem, int nImageIndex, HTREEITEM hItemAfter)
5243 {
5244 ATLASSERT(m_pTreeView != NULL);
5245 TVINSERTSTRUCT ins = { 0 };
5246 ins.hParent = m_hTreeItem;
5247 ins.hInsertAfter = hItemAfter;
5248 ins.item.mask = TVIF_TEXT;
5249 ins.item.pszText = (LPTSTR)lpstrItem;
5250 if(nImageIndex != -1)
5251 {
5252 ins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
5253 ins.item.iImage = nImageIndex;
5254 ins.item.iSelectedImage = nImageIndex;
5255 }
5256 return CTreeItemT<TBase>(m_pTreeView->InsertItem(&ins), m_pTreeView);
5257 }
5258
5259 template <class TBase>
5260 inline int CTreeItemT<TBase>::GetImageIndex() const
5261 {
5262 ATLASSERT(m_pTreeView != NULL);
5263 TVITEM item = { 0 };
5264 item.mask = TVIF_HANDLE | TVIF_IMAGE;
5265 item.hItem = m_hTreeItem;
5266 m_pTreeView->GetItem(&item);
5267 return item.iImage;
5268 }
5269
5270 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
5271 template <class TBase>
5272 inline BOOL CTreeItemT<TBase>::SetInsertMark(BOOL bAfter)
5273 {
5274 ATLASSERT(m_pTreeView != NULL);
5275 return m_pTreeView->SetInsertMark(m_hTreeItem, bAfter);
5276 }
5277 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
5278
5279 #if (_WIN32_WINNT >= 0x0501)
5280 template <class TBase>
5281 inline UINT CTreeItemT<TBase>::MapHTREEITEMToAccID() const
5282 {
5283 ATLASSERT(m_pTreeView != NULL);
5284 return m_pTreeView->MapHTREEITEMToAccID(m_hTreeItem);
5285 }
5286 #endif // (_WIN32_WINNT >= 0x0501)
5287
5288 #if (_WIN32_WINNT >= 0x0600)
5289 template <class TBase>
5290 inline void CTreeItemT<TBase>::ShowInfoTip()
5291 {
5292 ATLASSERT(m_pTreeView != NULL);
5293 m_pTreeView->ShowInfoTip(m_hTreeItem);
5294 }
5295
5296 template <class TBase>
5297 inline BOOL CTreeItemT<TBase>::GetPartRect(TVITEMPART partID, LPRECT lpRect) const
5298 {
5299 ATLASSERT(m_pTreeView != NULL);
5300 return m_pTreeView->GetItemPartRect(m_hTreeItem, partID, lpRect);
5301 }
5302 #endif // (_WIN32_WINNT >= 0x0600)
5303
5304
5305 ///////////////////////////////////////////////////////////////////////////////
5306 // CToolBarCtrl
5307
5308 template <class TBase>
5309 class CToolBarCtrlT : public TBase
5310 {
5311 public:
5312 // Construction
5313 CToolBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
5314 { }
5315
5316 CToolBarCtrlT< TBase >& operator =(HWND hWnd)
5317 {
5318 m_hWnd = hWnd;
5319 return *this;
5320 }
5321
5322 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
5323 DWORD dwStyle = 0, DWORD dwExStyle = 0,
5324 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
5325 {
5326 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
5327 }
5328
5329 // Attributes
5330 static LPCTSTR GetWndClassName()
5331 {
5332 return TOOLBARCLASSNAME;
5333 }
5334
5335 BOOL IsButtonEnabled(int nID) const
5336 {
5337 ATLASSERT(::IsWindow(m_hWnd));
5338 return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONENABLED, nID, 0L);
5339 }
5340
5341 BOOL IsButtonChecked(int nID) const
5342 {
5343 ATLASSERT(::IsWindow(m_hWnd));
5344 return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONCHECKED, nID, 0L);
5345 }
5346
5347 BOOL IsButtonPressed(int nID) const
5348 {
5349 ATLASSERT(::IsWindow(m_hWnd));
5350 return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONPRESSED, nID, 0L);
5351 }
5352
5353 BOOL IsButtonHidden(int nID) const
5354 {
5355 ATLASSERT(::IsWindow(m_hWnd));
5356 return(BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONHIDDEN, nID, 0L);
5357 }
5358
5359 BOOL IsButtonIndeterminate(int nID) const
5360 {
5361 ATLASSERT(::IsWindow(m_hWnd));
5362 return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONINDETERMINATE, nID, 0L);
5363 }
5364
5365 int GetState(int nID) const
5366 {
5367 ATLASSERT(::IsWindow(m_hWnd));
5368 return (int)::SendMessage(m_hWnd, TB_GETSTATE, nID, 0L);
5369 }
5370
5371 BOOL SetState(int nID, UINT nState)
5372 {
5373 ATLASSERT(::IsWindow(m_hWnd));
5374 return (BOOL)::SendMessage(m_hWnd, TB_SETSTATE, nID, MAKELPARAM(nState, 0));
5375 }
5376
5377 BOOL GetButton(int nIndex, LPTBBUTTON lpButton) const
5378 {
5379 ATLASSERT(::IsWindow(m_hWnd));
5380 return (BOOL)::SendMessage(m_hWnd, TB_GETBUTTON, nIndex, (LPARAM)lpButton);
5381 }
5382
5383 int GetButtonCount() const
5384 {
5385 ATLASSERT(::IsWindow(m_hWnd));
5386 return (int)::SendMessage(m_hWnd, TB_BUTTONCOUNT, 0, 0L);
5387 }
5388
5389 BOOL GetItemRect(int nIndex, LPRECT lpRect) const
5390 {
5391 ATLASSERT(::IsWindow(m_hWnd));
5392 return (BOOL)::SendMessage(m_hWnd, TB_GETITEMRECT, nIndex, (LPARAM)lpRect);
5393 }
5394
5395 void SetButtonStructSize(int nSize = sizeof(TBBUTTON))
5396 {
5397 ATLASSERT(::IsWindow(m_hWnd));
5398 ::SendMessage(m_hWnd, TB_BUTTONSTRUCTSIZE, nSize, 0L);
5399 }
5400
5401 BOOL SetButtonSize(SIZE size)
5402 {
5403 ATLASSERT(::IsWindow(m_hWnd));
5404 return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(size.cx, size.cy));
5405 }
5406
5407 BOOL SetButtonSize(int cx, int cy)
5408 {
5409 ATLASSERT(::IsWindow(m_hWnd));
5410 return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, cy));
5411 }
5412
5413 BOOL SetBitmapSize(SIZE size)
5414 {
5415 ATLASSERT(::IsWindow(m_hWnd));
5416 return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(size.cx, size.cy));
5417 }
5418
5419 BOOL SetBitmapSize(int cx, int cy)
5420 {
5421 ATLASSERT(::IsWindow(m_hWnd));
5422 return (BOOL)::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(cx, cy));
5423 }
5424
5425 #ifndef _WIN32_WCE
5426 CToolTipCtrl GetToolTips() const
5427 {
5428 ATLASSERT(::IsWindow(m_hWnd));
5429 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TB_GETTOOLTIPS, 0, 0L));
5430 }
5431
5432 void SetToolTips(HWND hWndToolTip)
5433 {
5434 ATLASSERT(::IsWindow(m_hWnd));
5435 ::SendMessage(m_hWnd, TB_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
5436 }
5437 #endif // !_WIN32_WCE
5438
5439 void SetNotifyWnd(HWND hWnd)
5440 {
5441 ATLASSERT(::IsWindow(m_hWnd));
5442 ::SendMessage(m_hWnd, TB_SETPARENT, (WPARAM)hWnd, 0L);
5443 }
5444
5445 int GetRows() const
5446 {
5447 ATLASSERT(::IsWindow(m_hWnd));
5448 return (int)::SendMessage(m_hWnd, TB_GETROWS, 0, 0L);
5449 }
5450
5451 void SetRows(int nRows, BOOL bLarger, LPRECT lpRect)
5452 {
5453 ATLASSERT(::IsWindow(m_hWnd));
5454 ::SendMessage(m_hWnd, TB_SETROWS, MAKELPARAM(nRows, bLarger), (LPARAM)lpRect);
5455 }
5456
5457 BOOL SetCmdID(int nIndex, UINT nID)
5458 {
5459 ATLASSERT(::IsWindow(m_hWnd));
5460 return (BOOL)::SendMessage(m_hWnd, TB_SETCMDID, nIndex, nID);
5461 }
5462
5463 DWORD GetBitmapFlags() const
5464 {
5465 ATLASSERT(::IsWindow(m_hWnd));
5466 return (DWORD)::SendMessage(m_hWnd, TB_GETBITMAPFLAGS, 0, 0L);
5467 }
5468
5469 int GetBitmap(int nID) const
5470 {
5471 ATLASSERT(::IsWindow(m_hWnd));
5472 return (int)::SendMessage(m_hWnd, TB_GETBITMAP, nID, 0L);
5473 }
5474
5475 int GetButtonText(int nID, LPTSTR lpstrText) const
5476 {
5477 ATLASSERT(::IsWindow(m_hWnd));
5478 return (int)::SendMessage(m_hWnd, TB_GETBUTTONTEXT, nID, (LPARAM)lpstrText);
5479 }
5480
5481 // nIndex - IE5 or higher only
5482 CImageList GetImageList(int nIndex = 0) const
5483 {
5484 ATLASSERT(::IsWindow(m_hWnd));
5485 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETIMAGELIST, nIndex, 0L));
5486 }
5487
5488 // nIndex - IE5 or higher only
5489 CImageList SetImageList(HIMAGELIST hImageList, int nIndex = 0)
5490 {
5491 ATLASSERT(::IsWindow(m_hWnd));
5492 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETIMAGELIST, nIndex, (LPARAM)hImageList));
5493 }
5494
5495 // nIndex - IE5 or higher only
5496 CImageList GetDisabledImageList(int nIndex = 0) const
5497 {
5498 ATLASSERT(::IsWindow(m_hWnd));
5499 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETDISABLEDIMAGELIST, nIndex, 0L));
5500 }
5501
5502 // nIndex - IE5 or higher only
5503 CImageList SetDisabledImageList(HIMAGELIST hImageList, int nIndex = 0)
5504 {
5505 ATLASSERT(::IsWindow(m_hWnd));
5506 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETDISABLEDIMAGELIST, nIndex, (LPARAM)hImageList));
5507 }
5508
5509 #ifndef _WIN32_WCE
5510 // nIndex - IE5 or higher only
5511 CImageList GetHotImageList(int nIndex = 0) const
5512 {
5513 ATLASSERT(::IsWindow(m_hWnd));
5514 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETHOTIMAGELIST, nIndex, 0L));
5515 }
5516
5517 // nIndex - IE5 or higher only
5518 CImageList SetHotImageList(HIMAGELIST hImageList, int nIndex = 0)
5519 {
5520 ATLASSERT(::IsWindow(m_hWnd));
5521 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETHOTIMAGELIST, nIndex, (LPARAM)hImageList));
5522 }
5523 #endif // !_WIN32_WCE
5524
5525 DWORD GetStyle() const
5526 {
5527 ATLASSERT(::IsWindow(m_hWnd));
5528 return (DWORD)::SendMessage(m_hWnd, TB_GETSTYLE, 0, 0L);
5529 }
5530
5531 void SetStyle(DWORD dwStyle)
5532 {
5533 ATLASSERT(::IsWindow(m_hWnd));
5534 ::SendMessage(m_hWnd, TB_SETSTYLE, 0, dwStyle);
5535 }
5536
5537 DWORD GetButtonSize() const
5538 {
5539 ATLASSERT(::IsWindow(m_hWnd));
5540 return (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L);
5541 }
5542
5543 void GetButtonSize(SIZE& size) const
5544 {
5545 ATLASSERT(::IsWindow(m_hWnd));
5546 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETBUTTONSIZE, 0, 0L);
5547 size.cx = LOWORD(dwRet);
5548 size.cy = HIWORD(dwRet);
5549 }
5550
5551 BOOL GetRect(int nID, LPRECT lpRect) const
5552 {
5553 ATLASSERT(::IsWindow(m_hWnd));
5554 return (BOOL)::SendMessage(m_hWnd, TB_GETRECT, nID, (LPARAM)lpRect);
5555 }
5556
5557 int GetTextRows() const
5558 {
5559 ATLASSERT(::IsWindow(m_hWnd));
5560 return (int)::SendMessage(m_hWnd, TB_GETTEXTROWS, 0, 0L);
5561 }
5562
5563 BOOL SetButtonWidth(int cxMin, int cxMax)
5564 {
5565 ATLASSERT(::IsWindow(m_hWnd));
5566 return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONWIDTH, 0, MAKELPARAM(cxMin, cxMax));
5567 }
5568
5569 BOOL SetIndent(int nIndent)
5570 {
5571 ATLASSERT(::IsWindow(m_hWnd));
5572 return (BOOL)::SendMessage(m_hWnd, TB_SETINDENT, nIndent, 0L);
5573 }
5574
5575 BOOL SetMaxTextRows(int nMaxTextRows)
5576 {
5577 ATLASSERT(::IsWindow(m_hWnd));
5578 return (BOOL)::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, nMaxTextRows, 0L);
5579 }
5580
5581 #if (_WIN32_IE >= 0x0400)
5582 #ifndef _WIN32_WCE
5583 BOOL GetAnchorHighlight() const
5584 {
5585 ATLASSERT(::IsWindow(m_hWnd));
5586 return (BOOL)::SendMessage(m_hWnd, TB_GETANCHORHIGHLIGHT, 0, 0L);
5587 }
5588
5589 BOOL SetAnchorHighlight(BOOL bEnable = TRUE)
5590 {
5591 ATLASSERT(::IsWindow(m_hWnd));
5592 return (BOOL)::SendMessage(m_hWnd, TB_SETANCHORHIGHLIGHT, bEnable, 0L);
5593 }
5594 #endif // !_WIN32_WCE
5595
5596 int GetButtonInfo(int nID, LPTBBUTTONINFO lptbbi) const
5597 {
5598 ATLASSERT(::IsWindow(m_hWnd));
5599 return (int)::SendMessage(m_hWnd, TB_GETBUTTONINFO, nID, (LPARAM)lptbbi);
5600 }
5601
5602 BOOL SetButtonInfo(int nID, LPTBBUTTONINFO lptbbi)
5603 {
5604 ATLASSERT(::IsWindow(m_hWnd));
5605 return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)lptbbi);
5606 }
5607
5608 BOOL SetButtonInfo(int nID, DWORD dwMask, BYTE Style, BYTE State, LPCTSTR lpszItem,
5609 int iImage, WORD cx, int iCommand, DWORD_PTR lParam)
5610 {
5611 ATLASSERT(::IsWindow(m_hWnd));
5612 TBBUTTONINFO tbbi = { 0 };
5613 tbbi.cbSize = sizeof(TBBUTTONINFO);
5614 tbbi.dwMask = dwMask;
5615 tbbi.idCommand = iCommand;
5616 tbbi.iImage = iImage;
5617 tbbi.fsState = State;
5618 tbbi.fsStyle = Style;
5619 tbbi.cx = cx;
5620 tbbi.pszText = (LPTSTR) lpszItem;
5621 tbbi.lParam = lParam;
5622 return (BOOL)::SendMessage(m_hWnd, TB_SETBUTTONINFO, nID, (LPARAM)&tbbi);
5623 }
5624
5625 #ifndef _WIN32_WCE
5626 int GetHotItem() const
5627 {
5628 ATLASSERT(::IsWindow(m_hWnd));
5629 return (int)::SendMessage(m_hWnd, TB_GETHOTITEM, 0, 0L);
5630 }
5631
5632 int SetHotItem(int nItem)
5633 {
5634 ATLASSERT(::IsWindow(m_hWnd));
5635 return (int)::SendMessage(m_hWnd, TB_SETHOTITEM, nItem, 0L);
5636 }
5637 #endif // !_WIN32_WCE
5638
5639 BOOL IsButtonHighlighted(int nButtonID) const
5640 {
5641 ATLASSERT(::IsWindow(m_hWnd));
5642 return (BOOL)::SendMessage(m_hWnd, TB_ISBUTTONHIGHLIGHTED, nButtonID, 0L);
5643 }
5644
5645 DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwFlags)
5646 {
5647 ATLASSERT(::IsWindow(m_hWnd));
5648 return (DWORD)::SendMessage(m_hWnd, TB_SETDRAWTEXTFLAGS, dwMask, dwFlags);
5649 }
5650
5651 #ifndef _WIN32_WCE
5652 BOOL GetColorScheme(LPCOLORSCHEME lpcs) const
5653 {
5654 ATLASSERT(::IsWindow(m_hWnd));
5655 return (BOOL)::SendMessage(m_hWnd, TB_GETCOLORSCHEME, 0, (LPARAM)lpcs);
5656 }
5657
5658 void SetColorScheme(LPCOLORSCHEME lpcs)
5659 {
5660 ATLASSERT(::IsWindow(m_hWnd));
5661 ::SendMessage(m_hWnd, TB_SETCOLORSCHEME, 0, (LPARAM)lpcs);
5662 }
5663
5664 DWORD GetExtendedStyle() const
5665 {
5666 ATLASSERT(::IsWindow(m_hWnd));
5667 return (DWORD)::SendMessage(m_hWnd, TB_GETEXTENDEDSTYLE, 0, 0L);
5668 }
5669
5670 DWORD SetExtendedStyle(DWORD dwStyle)
5671 {
5672 ATLASSERT(::IsWindow(m_hWnd));
5673 return (DWORD)::SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, dwStyle);
5674 }
5675
5676 void GetInsertMark(LPTBINSERTMARK lptbim) const
5677 {
5678 ATLASSERT(::IsWindow(m_hWnd));
5679 ::SendMessage(m_hWnd, TB_GETINSERTMARK, 0, (LPARAM)lptbim);
5680 }
5681
5682 void SetInsertMark(LPTBINSERTMARK lptbim)
5683 {
5684 ATLASSERT(::IsWindow(m_hWnd));
5685 ::SendMessage(m_hWnd, TB_SETINSERTMARK, 0, (LPARAM)lptbim);
5686 }
5687
5688 COLORREF GetInsertMarkColor() const
5689 {
5690 ATLASSERT(::IsWindow(m_hWnd));
5691 return (COLORREF)::SendMessage(m_hWnd, TB_GETINSERTMARKCOLOR, 0, 0L);
5692 }
5693
5694 COLORREF SetInsertMarkColor(COLORREF clr)
5695 {
5696 ATLASSERT(::IsWindow(m_hWnd));
5697 return (COLORREF)::SendMessage(m_hWnd, TB_SETINSERTMARKCOLOR, 0, (LPARAM)clr);
5698 }
5699
5700 BOOL GetMaxSize(LPSIZE lpSize) const
5701 {
5702 ATLASSERT(::IsWindow(m_hWnd));
5703 return (BOOL)::SendMessage(m_hWnd, TB_GETMAXSIZE, 0, (LPARAM)lpSize);
5704 }
5705
5706 void GetPadding(LPSIZE lpSizePadding) const
5707 {
5708 ATLASSERT(::IsWindow(m_hWnd));
5709 ATLASSERT(lpSizePadding != NULL);
5710 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_GETPADDING, 0, 0L);
5711 lpSizePadding->cx = GET_X_LPARAM(dwRet);
5712 lpSizePadding->cy = GET_Y_LPARAM(dwRet);
5713 }
5714
5715 void SetPadding(int cx, int cy, LPSIZE lpSizePadding = NULL)
5716 {
5717 ATLASSERT(::IsWindow(m_hWnd));
5718 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, TB_SETPADDING, 0, MAKELPARAM(cx, cy));
5719 if(lpSizePadding != NULL)
5720 {
5721 lpSizePadding->cx = GET_X_LPARAM(dwRet);
5722 lpSizePadding->cy = GET_Y_LPARAM(dwRet);
5723 }
5724 }
5725
5726 BOOL GetUnicodeFormat() const
5727 {
5728 ATLASSERT(::IsWindow(m_hWnd));
5729 return (BOOL)::SendMessage(m_hWnd, TB_GETUNICODEFORMAT, 0, 0L);
5730 }
5731
5732 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
5733 {
5734 ATLASSERT(::IsWindow(m_hWnd));
5735 return (BOOL)::SendMessage(m_hWnd, TB_SETUNICODEFORMAT, bUnicode, 0L);
5736 }
5737 #endif // !_WIN32_WCE
5738 #endif // (_WIN32_IE >= 0x0400)
5739
5740 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5741 int GetString(int nString, LPTSTR lpstrString, int cchMaxLen) const
5742 {
5743 ATLASSERT(::IsWindow(m_hWnd));
5744 return (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(cchMaxLen, nString), (LPARAM)lpstrString);
5745 }
5746
5747 int GetStringBSTR(int nString, BSTR& bstrString) const
5748 {
5749 USES_CONVERSION;
5750 ATLASSERT(::IsWindow(m_hWnd));
5751 ATLASSERT(bstrString == NULL);
5752 int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL));
5753 if(nLength != -1)
5754 {
5755 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
5756 LPTSTR lpstrText = buff.Allocate(nLength + 1);
5757 if(lpstrText != NULL)
5758 {
5759 nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstrText);
5760 if(nLength != -1)
5761 bstrString = ::SysAllocString(T2OLE(lpstrText));
5762 }
5763 else
5764 {
5765 nLength = -1;
5766 }
5767 }
5768
5769 return nLength;
5770 }
5771
5772 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
5773 int GetString(int nString, _CSTRING_NS::CString& str) const
5774 {
5775 ATLASSERT(::IsWindow(m_hWnd));
5776 int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(0, nString), NULL));
5777 if(nLength != -1)
5778 {
5779 LPTSTR lpstr = str.GetBufferSetLength(nLength + 1);
5780 if(lpstr != NULL)
5781 nLength = (int)::SendMessage(m_hWnd, TB_GETSTRING, MAKEWPARAM(nLength + 1, nString), (LPARAM)lpstr);
5782 else
5783 nLength = -1;
5784 str.ReleaseBuffer();
5785 }
5786 return nLength;
5787 }
5788 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
5789 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5790
5791 #if (_WIN32_WINNT >= 0x0501)
5792 void GetMetrics(LPTBMETRICS lptbm) const
5793 {
5794 ATLASSERT(::IsWindow(m_hWnd));
5795 ::SendMessage(m_hWnd, TB_GETMETRICS, 0, (LPARAM)lptbm);
5796 }
5797
5798 void SetMetrics(LPTBMETRICS lptbm)
5799 {
5800 ATLASSERT(::IsWindow(m_hWnd));
5801 ::SendMessage(m_hWnd, TB_SETMETRICS, 0, (LPARAM)lptbm);
5802 }
5803
5804 void SetWindowTheme(LPCWSTR lpstrTheme)
5805 {
5806 ATLASSERT(::IsWindow(m_hWnd));
5807 ::SendMessage(m_hWnd, TB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
5808 }
5809 #endif // (_WIN32_WINNT >= 0x0501)
5810
5811 #if (_WIN32_WINNT >= 0x0600)
5812 CImageList GetPressedImageList(int nIndex = 0) const
5813 {
5814 ATLASSERT(::IsWindow(m_hWnd));
5815 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_GETPRESSEDIMAGELIST, nIndex, 0L));
5816 }
5817
5818 CImageList SetPressedImageList(HIMAGELIST hImageList, int nIndex = 0)
5819 {
5820 ATLASSERT(::IsWindow(m_hWnd));
5821 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TB_SETPRESSEDIMAGELIST, nIndex, (LPARAM)hImageList));
5822 }
5823
5824 void GetItemDropDownRect(int nIndex, LPRECT lpRect) const
5825 {
5826 #ifndef TB_GETITEMDROPDOWNRECT
5827 const int TB_GETITEMDROPDOWNRECT = WM_USER + 103;
5828 #endif
5829 ATLASSERT(::IsWindow(m_hWnd));
5830 BOOL bRet = (BOOL)::SendMessage(m_hWnd, TB_GETITEMDROPDOWNRECT, nIndex, (LPARAM)lpRect);
5831 bRet; // avoid level 4 warning
5832 ATLASSERT(bRet != FALSE);
5833 }
5834 #endif // (_WIN32_WINNT >= 0x0600)
5835
5836 // Operations
5837 BOOL EnableButton(int nID, BOOL bEnable = TRUE)
5838 {
5839 ATLASSERT(::IsWindow(m_hWnd));
5840 return (BOOL)::SendMessage(m_hWnd, TB_ENABLEBUTTON, nID, MAKELPARAM(bEnable, 0));
5841 }
5842
5843 BOOL CheckButton(int nID, BOOL bCheck = TRUE)
5844 {
5845 ATLASSERT(::IsWindow(m_hWnd));
5846 return (BOOL)::SendMessage(m_hWnd, TB_CHECKBUTTON, nID, MAKELPARAM(bCheck, 0));
5847 }
5848
5849 BOOL PressButton(int nID, BOOL bPress = TRUE)
5850 {
5851 ATLASSERT(::IsWindow(m_hWnd));
5852 return (BOOL)::SendMessage(m_hWnd, TB_PRESSBUTTON, nID, MAKELPARAM(bPress, 0));
5853 }
5854
5855 BOOL HideButton(int nID, BOOL bHide = TRUE)
5856 {
5857 ATLASSERT(::IsWindow(m_hWnd));
5858 return (BOOL)::SendMessage(m_hWnd, TB_HIDEBUTTON, nID, MAKELPARAM(bHide, 0));
5859 }
5860
5861 BOOL Indeterminate(int nID, BOOL bIndeterminate = TRUE)
5862 {
5863 ATLASSERT(::IsWindow(m_hWnd));
5864 return (BOOL)::SendMessage(m_hWnd, TB_INDETERMINATE, nID, MAKELPARAM(bIndeterminate, 0));
5865 }
5866
5867 int AddBitmap(int nNumButtons, UINT nBitmapID)
5868 {
5869 ATLASSERT(::IsWindow(m_hWnd));
5870 TBADDBITMAP tbab = { 0 };
5871 tbab.hInst = ModuleHelper::GetResourceInstance();
5872 ATLASSERT(tbab.hInst != NULL);
5873 tbab.nID = nBitmapID;
5874 return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
5875 }
5876
5877 int AddBitmap(int nNumButtons, HBITMAP hBitmap)
5878 {
5879 ATLASSERT(::IsWindow(m_hWnd));
5880 TBADDBITMAP tbab = { 0 };
5881 tbab.hInst = NULL;
5882 tbab.nID = (UINT_PTR)hBitmap;
5883 return (int)::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
5884 }
5885
5886 BOOL AddButtons(int nNumButtons, LPTBBUTTON lpButtons)
5887 {
5888 ATLASSERT(::IsWindow(m_hWnd));
5889 return (BOOL)::SendMessage(m_hWnd, TB_ADDBUTTONS, nNumButtons, (LPARAM)lpButtons);
5890 }
5891
5892 BOOL InsertButton(int nIndex, LPTBBUTTON lpButton)
5893 {
5894 ATLASSERT(::IsWindow(m_hWnd));
5895 return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)lpButton);
5896 }
5897
5898 BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap,
5899 INT_PTR iString, DWORD_PTR lParam)
5900 {
5901 ATLASSERT(::IsWindow(m_hWnd));
5902 TBBUTTON tbb = { 0 };
5903 tbb.fsStyle = Style;
5904 tbb.fsState = State;
5905 tbb.idCommand = iCommand;
5906 tbb.iBitmap = iBitmap;
5907 tbb.iString = iString;
5908 tbb.dwData = lParam;
5909 return (BOOL)::SendMessage(m_hWnd, TB_INSERTBUTTON, nIndex, (LPARAM)&tbb);
5910 }
5911
5912 BOOL InsertButton(int nIndex, int iCommand, BYTE Style, BYTE State, int iBitmap,
5913 LPCTSTR lpszItem, DWORD_PTR lParam)
5914 {
5915 return InsertButton(nIndex, iCommand, Style, State, iBitmap, (INT_PTR)lpszItem, lParam);
5916 }
5917
5918 BOOL AddButton(LPTBBUTTON lpButton)
5919 {
5920 return InsertButton(-1, lpButton);
5921 }
5922
5923 BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, INT_PTR iString, DWORD_PTR lParam)
5924 {
5925 return InsertButton(-1, iCommand, Style, State, iBitmap, iString, lParam);
5926 }
5927
5928 BOOL AddButton(int iCommand, BYTE Style, BYTE State, int iBitmap, LPCTSTR lpszItem, DWORD_PTR lParam)
5929 {
5930 return InsertButton(-1, iCommand, Style, State, iBitmap, lpszItem, lParam);
5931 }
5932
5933 BOOL DeleteButton(int nIndex)
5934 {
5935 ATLASSERT(::IsWindow(m_hWnd));
5936 return (BOOL)::SendMessage(m_hWnd, TB_DELETEBUTTON, nIndex, 0L);
5937 }
5938
5939 BOOL InsertSeparator(int nIndex, int cxWidth = 8)
5940 {
5941 return InsertButton(nIndex, 0, BTNS_SEP, 0, cxWidth, (INT_PTR)0, 0);
5942 }
5943
5944 BOOL AddSeparator(int cxWidth = 8)
5945 {
5946 return AddButton(0, BTNS_SEP, 0, cxWidth, (INT_PTR)0, 0);
5947 }
5948
5949 int CommandToIndex(UINT nID) const
5950 {
5951 ATLASSERT(::IsWindow(m_hWnd));
5952 return (int)::SendMessage(m_hWnd, TB_COMMANDTOINDEX, nID, 0L);
5953 }
5954
5955 #ifndef _WIN32_WCE
5956 void SaveState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName)
5957 {
5958 ATLASSERT(::IsWindow(m_hWnd));
5959 TBSAVEPARAMS tbs = { 0 };
5960 tbs.hkr = hKeyRoot;
5961 tbs.pszSubKey = lpszSubKey;
5962 tbs.pszValueName = lpszValueName;
5963 ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)TRUE, (LPARAM)&tbs);
5964 }
5965
5966 void RestoreState(HKEY hKeyRoot, LPCTSTR lpszSubKey, LPCTSTR lpszValueName)
5967 {
5968 ATLASSERT(::IsWindow(m_hWnd));
5969 TBSAVEPARAMS tbs = { 0 };
5970 tbs.hkr = hKeyRoot;
5971 tbs.pszSubKey = lpszSubKey;
5972 tbs.pszValueName = lpszValueName;
5973 ::SendMessage(m_hWnd, TB_SAVERESTORE, (WPARAM)FALSE, (LPARAM)&tbs);
5974 }
5975
5976 void Customize()
5977 {
5978 ATLASSERT(::IsWindow(m_hWnd));
5979 ::SendMessage(m_hWnd, TB_CUSTOMIZE, 0, 0L);
5980 }
5981 #endif // !_WIN32_WCE
5982
5983 int AddString(UINT nStringID)
5984 {
5985 ATLASSERT(::IsWindow(m_hWnd));
5986 return (int)::SendMessage(m_hWnd, TB_ADDSTRING, (WPARAM)ModuleHelper::GetResourceInstance(), (LPARAM)nStringID);
5987 }
5988
5989 int AddStrings(LPCTSTR lpszStrings)
5990 {
5991 ATLASSERT(::IsWindow(m_hWnd));
5992 return (int)::SendMessage(m_hWnd, TB_ADDSTRING, 0, (LPARAM)lpszStrings);
5993 }
5994
5995 void AutoSize()
5996 {
5997 ATLASSERT(::IsWindow(m_hWnd));
5998 ::SendMessage(m_hWnd, TB_AUTOSIZE, 0, 0L);
5999 }
6000
6001 BOOL ChangeBitmap(int nID, int nBitmap)
6002 {
6003 ATLASSERT(::IsWindow(m_hWnd));
6004 return (BOOL)::SendMessage(m_hWnd, TB_CHANGEBITMAP, nID, MAKELPARAM(nBitmap, 0));
6005 }
6006
6007 int LoadImages(int nBitmapID)
6008 {
6009 ATLASSERT(::IsWindow(m_hWnd));
6010 return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)ModuleHelper::GetResourceInstance());
6011 }
6012
6013 int LoadStdImages(int nBitmapID)
6014 {
6015 ATLASSERT(::IsWindow(m_hWnd));
6016 return (int)::SendMessage(m_hWnd, TB_LOADIMAGES, nBitmapID, (LPARAM)HINST_COMMCTRL);
6017 }
6018
6019 BOOL ReplaceBitmap(LPTBREPLACEBITMAP ptbrb)
6020 {
6021 ATLASSERT(::IsWindow(m_hWnd));
6022 return (BOOL)::SendMessage(m_hWnd, TB_REPLACEBITMAP, 0, (LPARAM)ptbrb);
6023 }
6024
6025 #if (_WIN32_IE >= 0x0400)
6026 int HitTest(LPPOINT lpPoint) const
6027 {
6028 ATLASSERT(::IsWindow(m_hWnd));
6029 return (int)::SendMessage(m_hWnd, TB_HITTEST, 0, (LPARAM)lpPoint);
6030 }
6031
6032 #ifndef _WIN32_WCE
6033 BOOL InsertMarkHitTest(LPPOINT lpPoint, LPTBINSERTMARK lptbim) const
6034 {
6035 ATLASSERT(::IsWindow(m_hWnd));
6036 return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)lptbim);
6037 }
6038
6039 BOOL InsertMarkHitTest(int x, int y, LPTBINSERTMARK lptbim) const
6040 {
6041 ATLASSERT(::IsWindow(m_hWnd));
6042 POINT pt = { x, y };
6043 return (BOOL)::SendMessage(m_hWnd, TB_INSERTMARKHITTEST, (WPARAM)&pt, (LPARAM)lptbim);
6044 }
6045
6046 BOOL MapAccelerator(TCHAR chAccel, int& nID) const
6047 {
6048 ATLASSERT(::IsWindow(m_hWnd));
6049 return (BOOL)::SendMessage(m_hWnd, TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&nID);
6050 }
6051
6052 BOOL MarkButton(int nID, BOOL bHighlight = TRUE)
6053 {
6054 ATLASSERT(::IsWindow(m_hWnd));
6055 return (BOOL)::SendMessage(m_hWnd, TB_MARKBUTTON, nID, MAKELPARAM(bHighlight, 0));
6056 }
6057
6058 BOOL MoveButton(int nOldPos, int nNewPos)
6059 {
6060 ATLASSERT(::IsWindow(m_hWnd));
6061 return (BOOL)::SendMessage(m_hWnd, TB_MOVEBUTTON, nOldPos, nNewPos);
6062 }
6063
6064 HRESULT GetObject(REFIID iid, LPVOID* ppvObject)
6065 {
6066 ATLASSERT(::IsWindow(m_hWnd));
6067 return (HRESULT)::SendMessage(m_hWnd, TB_GETOBJECT, (WPARAM)&iid, (LPARAM)ppvObject);
6068 }
6069 #endif // !_WIN32_WCE
6070 #endif // (_WIN32_IE >= 0x0400)
6071 };
6072
6073 typedef CToolBarCtrlT<ATL::CWindow> CToolBarCtrl;
6074
6075
6076 ///////////////////////////////////////////////////////////////////////////////
6077 // CStatusBarCtrl
6078
6079 template <class TBase>
6080 class CStatusBarCtrlT : public TBase
6081 {
6082 public:
6083 // Constructors
6084 CStatusBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6085 { }
6086
6087 CStatusBarCtrlT< TBase >& operator =(HWND hWnd)
6088 {
6089 m_hWnd = hWnd;
6090 return *this;
6091 }
6092
6093 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6094 DWORD dwStyle = 0, DWORD dwExStyle = 0,
6095 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6096 {
6097 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6098 }
6099
6100 // Methods
6101 static LPCTSTR GetWndClassName()
6102 {
6103 return STATUSCLASSNAME;
6104 }
6105
6106 int GetParts(int nParts, int* pParts) const
6107 {
6108 ATLASSERT(::IsWindow(m_hWnd));
6109 return (int)::SendMessage(m_hWnd, SB_GETPARTS, nParts, (LPARAM)pParts);
6110 }
6111
6112 BOOL SetParts(int nParts, int* pWidths)
6113 {
6114 ATLASSERT(::IsWindow(m_hWnd));
6115 return (BOOL)::SendMessage(m_hWnd, SB_SETPARTS, nParts, (LPARAM)pWidths);
6116 }
6117
6118 int GetTextLength(int nPane, int* pType = NULL) const
6119 {
6120 ATLASSERT(::IsWindow(m_hWnd));
6121 ATLASSERT(nPane < 256);
6122 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L);
6123 if (pType != NULL)
6124 *pType = (int)(short)HIWORD(dwRet);
6125 return (int)(short)LOWORD(dwRet);
6126 }
6127
6128 int GetText(int nPane, LPTSTR lpszText, int* pType = NULL) const
6129 {
6130 ATLASSERT(::IsWindow(m_hWnd));
6131 ATLASSERT(nPane < 256);
6132 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, SB_GETTEXT, (WPARAM)nPane, (LPARAM)lpszText);
6133 if(pType != NULL)
6134 *pType = (int)(short)HIWORD(dwRet);
6135 return (int)(short)LOWORD(dwRet);
6136 }
6137
6138 #ifndef _ATL_NO_COM
6139 BOOL GetTextBSTR(int nPane, BSTR& bstrText, int* pType = NULL) const
6140 {
6141 USES_CONVERSION;
6142 ATLASSERT(::IsWindow(m_hWnd));
6143 ATLASSERT(nPane < 256);
6144 ATLASSERT(bstrText == NULL);
6145 int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L));
6146 if(nLength == 0)
6147 return FALSE;
6148
6149 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
6150 LPTSTR lpstrText = buff.Allocate(nLength + 1);
6151 if(lpstrText == NULL)
6152 return FALSE;
6153
6154 if(!GetText(nPane, lpstrText, pType))
6155 return FALSE;
6156
6157 bstrText = ::SysAllocString(T2OLE(lpstrText));
6158 return (bstrText != NULL) ? TRUE : FALSE;
6159 }
6160 #endif // !_ATL_NO_COM
6161
6162 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
6163 int GetText(int nPane, _CSTRING_NS::CString& strText, int* pType = NULL) const
6164 {
6165 ATLASSERT(::IsWindow(m_hWnd));
6166 ATLASSERT(nPane < 256);
6167 int nLength = (int)(short)LOWORD(::SendMessage(m_hWnd, SB_GETTEXTLENGTH, (WPARAM)nPane, 0L));
6168 if(nLength == 0)
6169 return 0;
6170
6171 LPTSTR lpstr = strText.GetBufferSetLength(nLength);
6172 if(lpstr == NULL)
6173 return 0;
6174 return GetText(nPane, lpstr, pType);
6175 }
6176 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
6177
6178 BOOL SetText(int nPane, LPCTSTR lpszText, int nType = 0)
6179 {
6180 ATLASSERT(::IsWindow(m_hWnd));
6181 ATLASSERT(nPane < 256);
6182 return (BOOL)::SendMessage(m_hWnd, SB_SETTEXT, (nPane | nType), (LPARAM)lpszText);
6183 }
6184
6185 BOOL GetRect(int nPane, LPRECT lpRect) const
6186 {
6187 ATLASSERT(::IsWindow(m_hWnd));
6188 ATLASSERT(nPane < 256);
6189 return (BOOL)::SendMessage(m_hWnd, SB_GETRECT, nPane, (LPARAM)lpRect);
6190 }
6191
6192 BOOL GetBorders(int* pBorders) const
6193 {
6194 ATLASSERT(::IsWindow(m_hWnd));
6195 return (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)pBorders);
6196 }
6197
6198 BOOL GetBorders(int& nHorz, int& nVert, int& nSpacing) const
6199 {
6200 ATLASSERT(::IsWindow(m_hWnd));
6201 int borders[3] = { 0, 0, 0 };
6202 BOOL bResult = (BOOL)::SendMessage(m_hWnd, SB_GETBORDERS, 0, (LPARAM)&borders);
6203 if(bResult)
6204 {
6205 nHorz = borders[0];
6206 nVert = borders[1];
6207 nSpacing = borders[2];
6208 }
6209 return bResult;
6210 }
6211
6212 void SetMinHeight(int nMin)
6213 {
6214 ATLASSERT(::IsWindow(m_hWnd));
6215 ::SendMessage(m_hWnd, SB_SETMINHEIGHT, nMin, 0L);
6216 }
6217
6218 BOOL SetSimple(BOOL bSimple = TRUE)
6219 {
6220 ATLASSERT(::IsWindow(m_hWnd));
6221 return (BOOL)::SendMessage(m_hWnd, SB_SIMPLE, bSimple, 0L);
6222 }
6223
6224 BOOL IsSimple() const
6225 {
6226 ATLASSERT(::IsWindow(m_hWnd));
6227 return (BOOL)::SendMessage(m_hWnd, SB_ISSIMPLE, 0, 0L);
6228 }
6229
6230 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
6231 BOOL GetUnicodeFormat() const
6232 {
6233 ATLASSERT(::IsWindow(m_hWnd));
6234 return (BOOL)::SendMessage(m_hWnd, SB_GETUNICODEFORMAT, 0, 0L);
6235 }
6236
6237 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6238 {
6239 ATLASSERT(::IsWindow(m_hWnd));
6240 return (BOOL)::SendMessage(m_hWnd, SB_SETUNICODEFORMAT, bUnicode, 0L);
6241 }
6242
6243 void GetTipText(int nPane, LPTSTR lpstrText, int nSize) const
6244 {
6245 ATLASSERT(::IsWindow(m_hWnd));
6246 ATLASSERT(nPane < 256);
6247 ::SendMessage(m_hWnd, SB_GETTIPTEXT, MAKEWPARAM(nPane, nSize), (LPARAM)lpstrText);
6248 }
6249
6250 void SetTipText(int nPane, LPCTSTR lpstrText)
6251 {
6252 ATLASSERT(::IsWindow(m_hWnd));
6253 ATLASSERT(nPane < 256);
6254 ::SendMessage(m_hWnd, SB_SETTIPTEXT, nPane, (LPARAM)lpstrText);
6255 }
6256 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
6257
6258 #if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
6259 COLORREF SetBkColor(COLORREF clrBk)
6260 {
6261 ATLASSERT(::IsWindow(m_hWnd));
6262 return (COLORREF)::SendMessage(m_hWnd, SB_SETBKCOLOR, 0, (LPARAM)clrBk);
6263 }
6264
6265 HICON GetIcon(int nPane) const
6266 {
6267 ATLASSERT(::IsWindow(m_hWnd));
6268 ATLASSERT(nPane < 256);
6269 return (HICON)::SendMessage(m_hWnd, SB_GETICON, nPane, 0L);
6270 }
6271
6272 BOOL SetIcon(int nPane, HICON hIcon)
6273 {
6274 ATLASSERT(::IsWindow(m_hWnd));
6275 ATLASSERT(nPane < 256);
6276 return (BOOL)::SendMessage(m_hWnd, SB_SETICON, nPane, (LPARAM)hIcon);
6277 }
6278 #endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
6279 };
6280
6281 typedef CStatusBarCtrlT<ATL::CWindow> CStatusBarCtrl;
6282
6283
6284 ///////////////////////////////////////////////////////////////////////////////
6285 // CTabCtrl
6286
6287 template <class TBase>
6288 class CTabCtrlT : public TBase
6289 {
6290 public:
6291 // Constructors
6292 CTabCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6293 { }
6294
6295 CTabCtrlT< TBase >& operator =(HWND hWnd)
6296 {
6297 m_hWnd = hWnd;
6298 return *this;
6299 }
6300
6301 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6302 DWORD dwStyle = 0, DWORD dwExStyle = 0,
6303 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6304 {
6305 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6306 }
6307
6308 // Attributes
6309 static LPCTSTR GetWndClassName()
6310 {
6311 return WC_TABCONTROL;
6312 }
6313
6314 CImageList GetImageList() const
6315 {
6316 ATLASSERT(::IsWindow(m_hWnd));
6317 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_GETIMAGELIST, 0, 0L));
6318 }
6319
6320 CImageList SetImageList(HIMAGELIST hImageList)
6321 {
6322 ATLASSERT(::IsWindow(m_hWnd));
6323 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, TCM_SETIMAGELIST, 0, (LPARAM)hImageList));
6324 }
6325
6326 int GetItemCount() const
6327 {
6328 ATLASSERT(::IsWindow(m_hWnd));
6329 return (int)::SendMessage(m_hWnd, TCM_GETITEMCOUNT, 0, 0L);
6330 }
6331
6332 BOOL GetItem(int nItem, LPTCITEM pTabCtrlItem) const
6333 {
6334 ATLASSERT(::IsWindow(m_hWnd));
6335 return (BOOL)::SendMessage(m_hWnd, TCM_GETITEM, nItem, (LPARAM)pTabCtrlItem);
6336 }
6337
6338 BOOL SetItem(int nItem, LPTCITEM pTabCtrlItem)
6339 {
6340 ATLASSERT(::IsWindow(m_hWnd));
6341 return (BOOL)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)pTabCtrlItem);
6342 }
6343
6344 int SetItem(int nItem, UINT mask, LPCTSTR lpszItem, DWORD dwState, DWORD dwStateMask, int iImage, LPARAM lParam)
6345 {
6346 ATLASSERT(::IsWindow(m_hWnd));
6347 TCITEM tci = { 0 };
6348 tci.mask = mask;
6349 tci.pszText = (LPTSTR) lpszItem;
6350 tci.dwState = dwState;
6351 tci.dwStateMask = dwStateMask;
6352 tci.iImage = iImage;
6353 tci.lParam = lParam;
6354 return (int)::SendMessage(m_hWnd, TCM_SETITEM, nItem, (LPARAM)&tci);
6355 }
6356
6357 BOOL GetItemRect(int nItem, LPRECT lpRect) const
6358 {
6359 ATLASSERT(::IsWindow(m_hWnd));
6360 return (BOOL)::SendMessage(m_hWnd, TCM_GETITEMRECT, nItem, (LPARAM)lpRect);
6361 }
6362
6363 int GetCurSel() const
6364 {
6365 ATLASSERT(::IsWindow(m_hWnd));
6366 return (int)::SendMessage(m_hWnd, TCM_GETCURSEL, 0, 0L);
6367 }
6368
6369 int SetCurSel(int nItem)
6370 {
6371 ATLASSERT(::IsWindow(m_hWnd));
6372 return (int)::SendMessage(m_hWnd, TCM_SETCURSEL, nItem, 0L);
6373 }
6374
6375 SIZE SetItemSize(SIZE size)
6376 {
6377 ATLASSERT(::IsWindow(m_hWnd));
6378 DWORD dwSize = (DWORD)::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(size.cx, size.cy));
6379 SIZE sizeRet = { GET_X_LPARAM(dwSize), GET_Y_LPARAM(dwSize) };
6380 return sizeRet;
6381 }
6382
6383 void SetItemSize(int cx, int cy)
6384 {
6385 ATLASSERT(::IsWindow(m_hWnd));
6386 ::SendMessage(m_hWnd, TCM_SETITEMSIZE, 0, MAKELPARAM(cx, cy));
6387 }
6388
6389 void SetPadding(SIZE size)
6390 {
6391 ATLASSERT(::IsWindow(m_hWnd));
6392 ::SendMessage(m_hWnd, TCM_SETPADDING, 0, MAKELPARAM(size.cx, size.cy));
6393 }
6394
6395 int GetRowCount() const
6396 {
6397 ATLASSERT(::IsWindow(m_hWnd));
6398 return (int)::SendMessage(m_hWnd, TCM_GETROWCOUNT, 0, 0L);
6399 }
6400
6401 #ifndef _WIN32_WCE
6402 CToolTipCtrl GetToolTips() const
6403 {
6404 ATLASSERT(::IsWindow(m_hWnd));
6405 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TCM_GETTOOLTIPS, 0, 0L));
6406 }
6407
6408 // this method is deprecated, please use GetToolTips
6409 CToolTipCtrl GetTooltips() const { return GetToolTips(); }
6410
6411 void SetToolTips(HWND hWndToolTip)
6412 {
6413 ATLASSERT(::IsWindow(m_hWnd));
6414 ::SendMessage(m_hWnd, TCM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
6415 }
6416
6417 // this method is deprecated, please use SetToolTips
6418 void SetTooltips(HWND hWndToolTip) { SetToolTips(hWndToolTip); }
6419
6420 #endif // !_WIN32_WCE
6421
6422 int GetCurFocus() const
6423 {
6424 ATLASSERT(::IsWindow(m_hWnd));
6425 return (int)::SendMessage(m_hWnd, TCM_GETCURFOCUS, 0, 0L);
6426 }
6427
6428 void SetCurFocus(int nItem)
6429 {
6430 ATLASSERT(::IsWindow(m_hWnd));
6431 ::SendMessage(m_hWnd, TCM_SETCURFOCUS, nItem, 0L);
6432 }
6433
6434 BOOL SetItemExtra(int cbExtra)
6435 {
6436 ATLASSERT(::IsWindow(m_hWnd));
6437 ATLASSERT(GetItemCount() == 0); // must be empty
6438 return (BOOL)::SendMessage(m_hWnd, TCM_SETITEMEXTRA, cbExtra, 0L);
6439 }
6440
6441 int SetMinTabWidth(int nWidth = -1)
6442 {
6443 ATLASSERT(::IsWindow(m_hWnd));
6444 return (int)::SendMessage(m_hWnd, TCM_SETMINTABWIDTH, 0, nWidth);
6445 }
6446
6447 #if (_WIN32_IE >= 0x0400)
6448 DWORD GetExtendedStyle() const
6449 {
6450 ATLASSERT(::IsWindow(m_hWnd));
6451 return (DWORD)::SendMessage(m_hWnd, TCM_GETEXTENDEDSTYLE, 0, 0L);
6452 }
6453
6454 DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
6455 {
6456 ATLASSERT(::IsWindow(m_hWnd));
6457 return (DWORD)::SendMessage(m_hWnd, TCM_SETEXTENDEDSTYLE, dwExMask, dwExStyle);
6458 }
6459
6460 #ifndef _WIN32_WCE
6461 BOOL GetUnicodeFormat() const
6462 {
6463 ATLASSERT(::IsWindow(m_hWnd));
6464 return (BOOL)::SendMessage(m_hWnd, TCM_GETUNICODEFORMAT, 0, 0L);
6465 }
6466
6467 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6468 {
6469 ATLASSERT(::IsWindow(m_hWnd));
6470 return (BOOL)::SendMessage(m_hWnd, TCM_SETUNICODEFORMAT, bUnicode, 0L);
6471 }
6472 #endif // !_WIN32_WCE
6473 #endif // (_WIN32_IE >= 0x0400)
6474
6475 // Operations
6476 int InsertItem(int nItem, LPTCITEM pTabCtrlItem)
6477 {
6478 ATLASSERT(::IsWindow(m_hWnd));
6479 return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)pTabCtrlItem);
6480 }
6481
6482 int InsertItem(int nItem, UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam)
6483 {
6484 ATLASSERT(::IsWindow(m_hWnd));
6485 TCITEM tci = { 0 };
6486 tci.mask = mask;
6487 tci.pszText = (LPTSTR) lpszItem;
6488 tci.iImage = iImage;
6489 tci.lParam = lParam;
6490 return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci);
6491 }
6492
6493 int InsertItem(int nItem, LPCTSTR lpszItem)
6494 {
6495 ATLASSERT(::IsWindow(m_hWnd));
6496 TCITEM tci = { 0 };
6497 tci.mask = TCIF_TEXT;
6498 tci.pszText = (LPTSTR) lpszItem;
6499 return (int)::SendMessage(m_hWnd, TCM_INSERTITEM, nItem, (LPARAM)&tci);
6500 }
6501
6502 int AddItem(LPTCITEM pTabCtrlItem)
6503 {
6504 return InsertItem(GetItemCount(), pTabCtrlItem);
6505 }
6506
6507 int AddItem(UINT mask, LPCTSTR lpszItem, int iImage, LPARAM lParam)
6508 {
6509 return InsertItem(GetItemCount(), mask, lpszItem, iImage, lParam);
6510 }
6511
6512 int AddItem(LPCTSTR lpszItem)
6513 {
6514 return InsertItem(GetItemCount(), lpszItem);
6515 }
6516
6517 BOOL DeleteItem(int nItem)
6518 {
6519 ATLASSERT(::IsWindow(m_hWnd));
6520 return (BOOL)::SendMessage(m_hWnd, TCM_DELETEITEM, nItem, 0L);
6521 }
6522
6523 BOOL DeleteAllItems()
6524 {
6525 ATLASSERT(::IsWindow(m_hWnd));
6526 return (BOOL)::SendMessage(m_hWnd, TCM_DELETEALLITEMS, 0, 0L);
6527 }
6528
6529 void AdjustRect(BOOL bLarger, LPRECT lpRect)
6530 {
6531 ATLASSERT(::IsWindow(m_hWnd));
6532 ::SendMessage(m_hWnd, TCM_ADJUSTRECT, bLarger, (LPARAM)lpRect);
6533 }
6534
6535 void RemoveImage(int nImage)
6536 {
6537 ATLASSERT(::IsWindow(m_hWnd));
6538 ::SendMessage(m_hWnd, TCM_REMOVEIMAGE, nImage, 0L);
6539 }
6540
6541 int HitTest(TC_HITTESTINFO* pHitTestInfo) const
6542 {
6543 ATLASSERT(::IsWindow(m_hWnd));
6544 return (int)::SendMessage(m_hWnd, TCM_HITTEST, 0, (LPARAM)pHitTestInfo);
6545 }
6546
6547 void DeselectAll(BOOL bExcludeFocus = TRUE)
6548 {
6549 ATLASSERT(::IsWindow(m_hWnd));
6550 ::SendMessage(m_hWnd, TCM_DESELECTALL, bExcludeFocus, 0L);
6551 }
6552
6553 #if (_WIN32_IE >= 0x0400)
6554 BOOL HighlightItem(int nIndex, BOOL bHighlight = TRUE)
6555 {
6556 ATLASSERT(::IsWindow(m_hWnd));
6557 return (BOOL)::SendMessage(m_hWnd, TCM_HIGHLIGHTITEM, nIndex, MAKELPARAM(bHighlight, 0));
6558 }
6559 #endif // (_WIN32_IE >= 0x0400)
6560 };
6561
6562 typedef CTabCtrlT<ATL::CWindow> CTabCtrl;
6563
6564
6565 ///////////////////////////////////////////////////////////////////////////////
6566 // CTrackBarCtrl
6567
6568 template <class TBase>
6569 class CTrackBarCtrlT : public TBase
6570 {
6571 public:
6572 // Constructors
6573 CTrackBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6574 { }
6575
6576 CTrackBarCtrlT< TBase >& operator =(HWND hWnd)
6577 {
6578 m_hWnd = hWnd;
6579 return *this;
6580 }
6581
6582 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6583 DWORD dwStyle = 0, DWORD dwExStyle = 0,
6584 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6585 {
6586 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6587 }
6588
6589 // Attributes
6590 static LPCTSTR GetWndClassName()
6591 {
6592 return TRACKBAR_CLASS;
6593 }
6594
6595 int GetLineSize() const
6596 {
6597 ATLASSERT(::IsWindow(m_hWnd));
6598 return (int)::SendMessage(m_hWnd, TBM_GETLINESIZE, 0, 0L);
6599 }
6600
6601 int SetLineSize(int nSize)
6602 {
6603 ATLASSERT(::IsWindow(m_hWnd));
6604 return (int)::SendMessage(m_hWnd, TBM_SETLINESIZE, 0, nSize);
6605 }
6606
6607 int GetPageSize() const
6608 {
6609 ATLASSERT(::IsWindow(m_hWnd));
6610 return (int)::SendMessage(m_hWnd, TBM_GETPAGESIZE, 0, 0L);
6611 }
6612
6613 int SetPageSize(int nSize)
6614 {
6615 ATLASSERT(::IsWindow(m_hWnd));
6616 return (int)::SendMessage(m_hWnd, TBM_SETPAGESIZE, 0, nSize);
6617 }
6618
6619 int GetRangeMin() const
6620 {
6621 ATLASSERT(::IsWindow(m_hWnd));
6622 return (int)::SendMessage(m_hWnd, TBM_GETRANGEMIN, 0, 0L);
6623 }
6624
6625 void SetRangeMin(int nMin, BOOL bRedraw = FALSE)
6626 {
6627 ATLASSERT(::IsWindow(m_hWnd));
6628 ::SendMessage(m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin);
6629 }
6630
6631 int GetRangeMax() const
6632 {
6633 ATLASSERT(::IsWindow(m_hWnd));
6634 return (int)::SendMessage(m_hWnd, TBM_GETRANGEMAX, 0, 0L);
6635 }
6636
6637 void SetRangeMax(int nMax, BOOL bRedraw = FALSE)
6638 {
6639 ATLASSERT(::IsWindow(m_hWnd));
6640 ::SendMessage(m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax);
6641 }
6642
6643 void GetRange(int& nMin, int& nMax) const
6644 {
6645 nMin = GetRangeMin();
6646 nMax = GetRangeMax();
6647 }
6648
6649 void SetRange(int nMin, int nMax, BOOL bRedraw = TRUE)
6650 {
6651 ATLASSERT(::IsWindow(m_hWnd));
6652 ::SendMessage(m_hWnd, TBM_SETRANGE, bRedraw, MAKELPARAM(nMin, nMax));
6653 }
6654
6655 int GetSelStart() const
6656 {
6657 ATLASSERT(::IsWindow(m_hWnd));
6658 return (int)::SendMessage(m_hWnd, TBM_GETSELSTART, 0, 0L);
6659 }
6660
6661 void SetSelStart(int nMin, BOOL bRedraw = FALSE)
6662 {
6663 ATLASSERT(::IsWindow(m_hWnd));
6664 ::SendMessage(m_hWnd, TBM_SETSELSTART, bRedraw, (LPARAM)nMin);
6665 }
6666
6667 int GetSelEnd() const
6668 {
6669 ATLASSERT(::IsWindow(m_hWnd));
6670 return (int)::SendMessage(m_hWnd, TBM_GETSELEND, 0, 0L);
6671 }
6672
6673 void SetSelEnd(int nMax, BOOL bRedraw = FALSE)
6674 {
6675 ATLASSERT(::IsWindow(m_hWnd));
6676 ::SendMessage(m_hWnd, TBM_SETSELEND, bRedraw, (LPARAM)nMax);
6677 }
6678
6679 void GetSelection(int& nMin, int& nMax) const
6680 {
6681 nMin = GetSelStart();
6682 nMax = GetSelEnd();
6683 }
6684
6685 void SetSelection(int nMin, int nMax, BOOL bRedraw = TRUE)
6686 {
6687 SetSelStart(nMin, FALSE);
6688 SetSelEnd(nMax, bRedraw);
6689 }
6690
6691 void GetChannelRect(LPRECT lprc) const
6692 {
6693 ATLASSERT(::IsWindow(m_hWnd));
6694 ::SendMessage(m_hWnd, TBM_GETCHANNELRECT, 0, (LPARAM)lprc);
6695 }
6696
6697 void GetThumbRect(LPRECT lprc) const
6698 {
6699 ATLASSERT(::IsWindow(m_hWnd));
6700 ::SendMessage(m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)lprc);
6701 }
6702
6703 int GetPos() const
6704 {
6705 ATLASSERT(::IsWindow(m_hWnd));
6706 return (int)::SendMessage(m_hWnd, TBM_GETPOS, 0, 0L);
6707 }
6708
6709 void SetPos(int nPos)
6710 {
6711 ATLASSERT(::IsWindow(m_hWnd));
6712 ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos);
6713 }
6714
6715 UINT GetNumTics() const
6716 {
6717 ATLASSERT(::IsWindow(m_hWnd));
6718 return (UINT)::SendMessage(m_hWnd, TBM_GETNUMTICS, 0, 0L);
6719 }
6720
6721 DWORD* GetTicArray() const
6722 {
6723 ATLASSERT(::IsWindow(m_hWnd));
6724 return (DWORD*)::SendMessage(m_hWnd, TBM_GETPTICS, 0, 0L);
6725 }
6726
6727 int GetTic(int nTic) const
6728 {
6729 ATLASSERT(::IsWindow(m_hWnd));
6730 return (int)::SendMessage(m_hWnd, TBM_GETTIC, nTic, 0L);
6731 }
6732
6733 BOOL SetTic(int nTic)
6734 {
6735 ATLASSERT(::IsWindow(m_hWnd));
6736 return (BOOL)::SendMessage(m_hWnd, TBM_SETTIC, 0, nTic);
6737 }
6738
6739 int GetTicPos(int nTic) const
6740 {
6741 ATLASSERT(::IsWindow(m_hWnd));
6742 return (int)::SendMessage(m_hWnd, TBM_GETTICPOS, nTic, 0L);
6743 }
6744
6745 void SetTicFreq(int nFreq)
6746 {
6747 ATLASSERT(::IsWindow(m_hWnd));
6748 ::SendMessage(m_hWnd, TBM_SETTICFREQ, nFreq, 0L);
6749 }
6750
6751 int GetThumbLength() const
6752 {
6753 ATLASSERT(::IsWindow(m_hWnd));
6754 return (int)::SendMessage(m_hWnd, TBM_GETTHUMBLENGTH, 0, 0L);
6755 }
6756
6757 void SetThumbLength(int nLength)
6758 {
6759 ATLASSERT(::IsWindow(m_hWnd));
6760 ::SendMessage(m_hWnd, TBM_SETTHUMBLENGTH, nLength, 0L);
6761 }
6762
6763 void SetSel(int nStart, int nEnd, BOOL bRedraw = TRUE)
6764 {
6765 ATLASSERT(::IsWindow(m_hWnd));
6766 ATLASSERT((GetStyle() & TBS_ENABLESELRANGE) != 0);
6767 ::SendMessage(m_hWnd, TBM_SETSEL, bRedraw, MAKELPARAM(nStart, nEnd));
6768 }
6769
6770 ATL::CWindow GetBuddy(BOOL bLeft = TRUE) const
6771 {
6772 ATLASSERT(::IsWindow(m_hWnd));
6773 return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_GETBUDDY, bLeft, 0L));
6774 }
6775
6776 ATL::CWindow SetBuddy(HWND hWndBuddy, BOOL bLeft = TRUE)
6777 {
6778 ATLASSERT(::IsWindow(m_hWnd));
6779 return ATL::CWindow((HWND)::SendMessage(m_hWnd, TBM_SETBUDDY, bLeft, (LPARAM)hWndBuddy));
6780 }
6781
6782 #ifndef _WIN32_WCE
6783 CToolTipCtrl GetToolTips() const
6784 {
6785 ATLASSERT(::IsWindow(m_hWnd));
6786 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, TBM_GETTOOLTIPS, 0, 0L));
6787 }
6788
6789 void SetToolTips(HWND hWndTT)
6790 {
6791 ATLASSERT(::IsWindow(m_hWnd));
6792 ::SendMessage(m_hWnd, TBM_SETTOOLTIPS, (WPARAM)hWndTT, 0L);
6793 }
6794
6795 int SetTipSide(int nSide)
6796 {
6797 ATLASSERT(::IsWindow(m_hWnd));
6798 return (int)::SendMessage(m_hWnd, TBM_SETTIPSIDE, nSide, 0L);
6799 }
6800 #endif // !_WIN32_WCE
6801
6802 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
6803 BOOL GetUnicodeFormat() const
6804 {
6805 ATLASSERT(::IsWindow(m_hWnd));
6806 return (BOOL)::SendMessage(m_hWnd, TBM_GETUNICODEFORMAT, 0, 0L);
6807 }
6808
6809 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6810 {
6811 ATLASSERT(::IsWindow(m_hWnd));
6812 return (BOOL)::SendMessage(m_hWnd, TBM_SETUNICODEFORMAT, bUnicode, 0L);
6813 }
6814 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
6815
6816 // Operations
6817 void ClearSel(BOOL bRedraw = FALSE)
6818 {
6819 ATLASSERT(::IsWindow(m_hWnd));
6820 ::SendMessage(m_hWnd, TBM_CLEARSEL, bRedraw, 0L);
6821 }
6822
6823 void VerifyPos()
6824 {
6825 ATLASSERT(::IsWindow(m_hWnd));
6826 ::SendMessage(m_hWnd, TBM_SETPOS, FALSE, 0L);
6827 }
6828
6829 void ClearTics(BOOL bRedraw = FALSE)
6830 {
6831 ATLASSERT(::IsWindow(m_hWnd));
6832 ::SendMessage(m_hWnd, TBM_CLEARTICS, bRedraw, 0L);
6833 }
6834 };
6835
6836 typedef CTrackBarCtrlT<ATL::CWindow> CTrackBarCtrl;
6837
6838
6839 ///////////////////////////////////////////////////////////////////////////////
6840 // CUpDownCtrl
6841
6842 template <class TBase>
6843 class CUpDownCtrlT : public TBase
6844 {
6845 public:
6846 // Constructors
6847 CUpDownCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6848 { }
6849
6850 CUpDownCtrlT< TBase >& operator =(HWND hWnd)
6851 {
6852 m_hWnd = hWnd;
6853 return *this;
6854 }
6855
6856 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
6857 DWORD dwStyle = 0, DWORD dwExStyle = 0,
6858 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
6859 {
6860 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
6861 }
6862
6863 // Attributes
6864 static LPCTSTR GetWndClassName()
6865 {
6866 return UPDOWN_CLASS;
6867 }
6868
6869 UINT GetAccel(int nAccel, UDACCEL* pAccel) const
6870 {
6871 ATLASSERT(::IsWindow(m_hWnd));
6872 return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETACCEL, nAccel, (LPARAM)pAccel));
6873 }
6874
6875 BOOL SetAccel(int nAccel, UDACCEL* pAccel)
6876 {
6877 ATLASSERT(::IsWindow(m_hWnd));
6878 return (BOOL)LOWORD(::SendMessage(m_hWnd, UDM_SETACCEL, nAccel, (LPARAM)pAccel));
6879 }
6880
6881 UINT GetBase() const
6882 {
6883 ATLASSERT(::IsWindow(m_hWnd));
6884 return (UINT)LOWORD(::SendMessage(m_hWnd, UDM_GETBASE, 0, 0L));
6885 }
6886
6887 int SetBase(int nBase)
6888 {
6889 ATLASSERT(::IsWindow(m_hWnd));
6890 return (int)::SendMessage(m_hWnd, UDM_SETBASE, nBase, 0L);
6891 }
6892
6893 ATL::CWindow GetBuddy() const
6894 {
6895 ATLASSERT(::IsWindow(m_hWnd));
6896 return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_GETBUDDY, 0, 0L));
6897 }
6898
6899 ATL::CWindow SetBuddy(HWND hWndBuddy)
6900 {
6901 ATLASSERT(::IsWindow(m_hWnd));
6902 return ATL::CWindow((HWND)::SendMessage(m_hWnd, UDM_SETBUDDY, (WPARAM)hWndBuddy, 0L));
6903 }
6904
6905 int GetPos(LPBOOL lpbError = NULL) const
6906 {
6907 ATLASSERT(::IsWindow(m_hWnd));
6908 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETPOS, 0, 0L);
6909 // Note: Seems that Windows always sets error to TRUE if
6910 // UDS_SETBUDDYINT style is not used
6911 if(lpbError != NULL)
6912 *lpbError = (HIWORD(dwRet) != 0) ? TRUE : FALSE;
6913 return (int)(short)LOWORD(dwRet);
6914 }
6915
6916 int SetPos(int nPos)
6917 {
6918 ATLASSERT(::IsWindow(m_hWnd));
6919 return (int)(short)LOWORD(::SendMessage(m_hWnd, UDM_SETPOS, 0, MAKELPARAM(nPos, 0)));
6920 }
6921
6922 DWORD GetRange() const
6923 {
6924 ATLASSERT(::IsWindow(m_hWnd));
6925 return (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L);
6926 }
6927
6928 void GetRange(int& nLower, int& nUpper) const
6929 {
6930 ATLASSERT(::IsWindow(m_hWnd));
6931 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, UDM_GETRANGE, 0, 0L);
6932 nLower = (int)(short)HIWORD(dwRet);
6933 nUpper = (int)(short)LOWORD(dwRet);
6934 }
6935
6936 void SetRange(int nLower, int nUpper)
6937 {
6938 ATLASSERT(::IsWindow(m_hWnd));
6939 ::SendMessage(m_hWnd, UDM_SETRANGE, 0, MAKELPARAM(nUpper, nLower));
6940 }
6941
6942 #if (_WIN32_IE >= 0x0400)
6943 void SetRange32(int nLower, int nUpper)
6944 {
6945 ATLASSERT(::IsWindow(m_hWnd));
6946 ::SendMessage(m_hWnd, UDM_SETRANGE32, nLower, nUpper);
6947 }
6948
6949 void GetRange32(int& nLower, int& nUpper) const
6950 {
6951 ATLASSERT(::IsWindow(m_hWnd));
6952 ::SendMessage(m_hWnd, UDM_GETRANGE32, (WPARAM)&nLower, (LPARAM)&nUpper);
6953 }
6954
6955 #ifndef _WIN32_WCE
6956 BOOL GetUnicodeFormat() const
6957 {
6958 ATLASSERT(::IsWindow(m_hWnd));
6959 return (BOOL)::SendMessage(m_hWnd, UDM_GETUNICODEFORMAT, 0, 0L);
6960 }
6961
6962 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
6963 {
6964 ATLASSERT(::IsWindow(m_hWnd));
6965 return (BOOL)::SendMessage(m_hWnd, UDM_SETUNICODEFORMAT, bUnicode, 0L);
6966 }
6967 #endif // !_WIN32_WCE
6968 #endif // (_WIN32_IE >= 0x0400)
6969
6970 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
6971 int GetPos32(LPBOOL lpbError = NULL) const
6972 {
6973 ATLASSERT(::IsWindow(m_hWnd));
6974 // Note: Seems that Windows always sets error to TRUE if
6975 // UDS_SETBUDDYINT style is not used
6976 return (int)::SendMessage(m_hWnd, UDM_GETPOS32, 0, (LPARAM)lpbError);
6977 }
6978
6979 int SetPos32(int nPos)
6980 {
6981 ATLASSERT(::IsWindow(m_hWnd));
6982 return (int)::SendMessage(m_hWnd, UDM_SETPOS32, 0, (LPARAM)nPos);
6983 }
6984 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
6985 };
6986
6987 typedef CUpDownCtrlT<ATL::CWindow> CUpDownCtrl;
6988
6989
6990 ///////////////////////////////////////////////////////////////////////////////
6991 // CProgressBarCtrl
6992
6993 template <class TBase>
6994 class CProgressBarCtrlT : public TBase
6995 {
6996 public:
6997 // Constructors
6998 CProgressBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
6999 { }
7000
7001 CProgressBarCtrlT< TBase >& operator =(HWND hWnd)
7002 {
7003 m_hWnd = hWnd;
7004 return *this;
7005 }
7006
7007 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7008 DWORD dwStyle = 0, DWORD dwExStyle = 0,
7009 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7010 {
7011 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7012 }
7013
7014 // Attributes
7015 static LPCTSTR GetWndClassName()
7016 {
7017 return PROGRESS_CLASS;
7018 }
7019
7020 DWORD SetRange(int nLower, int nUpper)
7021 {
7022 ATLASSERT(::IsWindow(m_hWnd));
7023 return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE, 0, MAKELPARAM(nLower, nUpper));
7024 }
7025
7026 int SetPos(int nPos)
7027 {
7028 ATLASSERT(::IsWindow(m_hWnd));
7029 return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETPOS, nPos, 0L));
7030 }
7031
7032 int OffsetPos(int nPos)
7033 {
7034 ATLASSERT(::IsWindow(m_hWnd));
7035 return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_DELTAPOS, nPos, 0L));
7036 }
7037
7038 int SetStep(int nStep)
7039 {
7040 ATLASSERT(::IsWindow(m_hWnd));
7041 return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_SETSTEP, nStep, 0L));
7042 }
7043
7044 UINT GetPos() const
7045 {
7046 ATLASSERT(::IsWindow(m_hWnd));
7047 return (UINT)::SendMessage(m_hWnd, PBM_GETPOS, 0, 0L);
7048 }
7049
7050 void GetRange(PPBRANGE pPBRange) const
7051 {
7052 ATLASSERT(::IsWindow(m_hWnd));
7053 ATLASSERT(pPBRange != NULL);
7054 ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)pPBRange);
7055 }
7056
7057 void GetRange(int& nLower, int& nUpper) const
7058 {
7059 ATLASSERT(::IsWindow(m_hWnd));
7060 PBRANGE range = { 0 };
7061 ::SendMessage(m_hWnd, PBM_GETRANGE, TRUE, (LPARAM)&range);
7062 nLower = range.iLow;
7063 nUpper = range.iHigh;
7064 }
7065
7066 int GetRangeLimit(BOOL bLowLimit) const
7067 {
7068 ATLASSERT(::IsWindow(m_hWnd));
7069 return (int)::SendMessage(m_hWnd, PBM_GETRANGE, bLowLimit, (LPARAM)NULL);
7070 }
7071
7072 DWORD SetRange32(int nMin, int nMax)
7073 {
7074 ATLASSERT(::IsWindow(m_hWnd));
7075 return (DWORD)::SendMessage(m_hWnd, PBM_SETRANGE32, nMin, nMax);
7076 }
7077
7078 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
7079 COLORREF SetBarColor(COLORREF clr)
7080 {
7081 ATLASSERT(::IsWindow(m_hWnd));
7082 return (COLORREF)::SendMessage(m_hWnd, PBM_SETBARCOLOR, 0, (LPARAM)clr);
7083 }
7084
7085 COLORREF SetBkColor(COLORREF clr)
7086 {
7087 ATLASSERT(::IsWindow(m_hWnd));
7088 return (COLORREF)::SendMessage(m_hWnd, PBM_SETBKCOLOR, 0, (LPARAM)clr);
7089 }
7090 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
7091
7092 #if (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE)
7093 BOOL SetMarquee(BOOL bMarquee, UINT uUpdateTime = 0U)
7094 {
7095 ATLASSERT(::IsWindow(m_hWnd));
7096 return (BOOL)::SendMessage(m_hWnd, PBM_SETMARQUEE, (WPARAM)bMarquee, (LPARAM)uUpdateTime);
7097 }
7098 #endif // (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE)
7099
7100 #if (_WIN32_WINNT >= 0x0600)
7101 int GetStep() const
7102 {
7103 ATLASSERT(::IsWindow(m_hWnd));
7104 return (int)::SendMessage(m_hWnd, PBM_GETSTEP, 0, 0L);
7105 }
7106
7107 COLORREF GetBkColor() const
7108 {
7109 ATLASSERT(::IsWindow(m_hWnd));
7110 return (COLORREF)::SendMessage(m_hWnd, PBM_GETBKCOLOR, 0, 0L);
7111 }
7112
7113 COLORREF GetBarColor() const
7114 {
7115 ATLASSERT(::IsWindow(m_hWnd));
7116 return (COLORREF)::SendMessage(m_hWnd, PBM_GETBARCOLOR, 0, 0L);
7117 }
7118
7119 int GetState() const
7120 {
7121 ATLASSERT(::IsWindow(m_hWnd));
7122 return (int)::SendMessage(m_hWnd, PBM_GETSTATE, 0, 0L);
7123 }
7124
7125 int SetState(int nState)
7126 {
7127 ATLASSERT(::IsWindow(m_hWnd));
7128 return (int)::SendMessage(m_hWnd, PBM_SETSTATE, nState, 0L);
7129 }
7130 #endif // (_WIN32_WINNT >= 0x0600)
7131
7132 // Operations
7133 int StepIt()
7134 {
7135 ATLASSERT(::IsWindow(m_hWnd));
7136 return (int)(short)LOWORD(::SendMessage(m_hWnd, PBM_STEPIT, 0, 0L));
7137 }
7138 };
7139
7140 typedef CProgressBarCtrlT<ATL::CWindow> CProgressBarCtrl;
7141
7142
7143 ///////////////////////////////////////////////////////////////////////////////
7144 // CHotKeyCtrl
7145
7146 #ifndef _WIN32_WCE
7147
7148 template <class TBase>
7149 class CHotKeyCtrlT : public TBase
7150 {
7151 public:
7152 // Constructors
7153 CHotKeyCtrlT(HWND hWnd = NULL) : TBase(hWnd)
7154 { }
7155
7156 CHotKeyCtrlT< TBase >& operator =(HWND hWnd)
7157 {
7158 m_hWnd = hWnd;
7159 return *this;
7160 }
7161
7162 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7163 DWORD dwStyle = 0, DWORD dwExStyle = 0,
7164 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7165 {
7166 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7167 }
7168
7169 // Attributes
7170 static LPCTSTR GetWndClassName()
7171 {
7172 return HOTKEY_CLASS;
7173 }
7174
7175 DWORD GetHotKey() const
7176 {
7177 ATLASSERT(::IsWindow(m_hWnd));
7178 return (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L);
7179 }
7180
7181 void GetHotKey(WORD &wVirtualKeyCode, WORD &wModifiers) const
7182 {
7183 ATLASSERT(::IsWindow(m_hWnd));
7184 DWORD dw = (DWORD)::SendMessage(m_hWnd, HKM_GETHOTKEY, 0, 0L);
7185 wVirtualKeyCode = LOBYTE(LOWORD(dw));
7186 wModifiers = HIBYTE(LOWORD(dw));
7187 }
7188
7189 void SetHotKey(WORD wVirtualKeyCode, WORD wModifiers)
7190 {
7191 ATLASSERT(::IsWindow(m_hWnd));
7192 ::SendMessage(m_hWnd, HKM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0L);
7193 }
7194
7195 void SetRules(WORD wInvalidComb, WORD wModifiers)
7196 {
7197 ATLASSERT(::IsWindow(m_hWnd));
7198 ::SendMessage(m_hWnd, HKM_SETRULES, wInvalidComb, MAKELPARAM(wModifiers, 0));
7199 }
7200 };
7201
7202 typedef CHotKeyCtrlT<ATL::CWindow> CHotKeyCtrl;
7203
7204 #endif // !_WIN32_WCE
7205
7206
7207 ///////////////////////////////////////////////////////////////////////////////
7208 // CAnimateCtrl
7209
7210 #ifndef _WIN32_WCE
7211
7212 template <class TBase>
7213 class CAnimateCtrlT : public TBase
7214 {
7215 public:
7216 // Constructors
7217 CAnimateCtrlT(HWND hWnd = NULL) : TBase(hWnd)
7218 { }
7219
7220 CAnimateCtrlT< TBase >& operator =(HWND hWnd)
7221 {
7222 m_hWnd = hWnd;
7223 return *this;
7224 }
7225
7226 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7227 DWORD dwStyle = 0, DWORD dwExStyle = 0,
7228 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7229 {
7230 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7231 }
7232
7233 // Attributes
7234 static LPCTSTR GetWndClassName()
7235 {
7236 return ANIMATE_CLASS;
7237 }
7238
7239 // Operations
7240 BOOL Open(ATL::_U_STRINGorID FileName)
7241 {
7242 ATLASSERT(::IsWindow(m_hWnd));
7243 return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, (LPARAM)FileName.m_lpstr);
7244 }
7245
7246 BOOL Play(UINT nFrom, UINT nTo, UINT nRep)
7247 {
7248 ATLASSERT(::IsWindow(m_hWnd));
7249 return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, nRep, MAKELPARAM(nFrom, nTo));
7250 }
7251
7252 BOOL Stop()
7253 {
7254 ATLASSERT(::IsWindow(m_hWnd));
7255 return (BOOL)::SendMessage(m_hWnd, ACM_STOP, 0, 0L);
7256 }
7257
7258 BOOL Close()
7259 {
7260 ATLASSERT(::IsWindow(m_hWnd));
7261 return (BOOL)::SendMessage(m_hWnd, ACM_OPEN, 0, 0L);
7262 }
7263
7264 BOOL Seek(UINT nTo)
7265 {
7266 ATLASSERT(::IsWindow(m_hWnd));
7267 return (BOOL)::SendMessage(m_hWnd, ACM_PLAY, 0, MAKELPARAM(nTo, nTo));
7268 }
7269
7270 // Vista only
7271 BOOL IsPlaying() const
7272 {
7273 #ifndef ACM_ISPLAYING
7274 const UINT ACM_ISPLAYING = (WM_USER+104);
7275 #endif
7276 ATLASSERT(::IsWindow(m_hWnd));
7277 return (BOOL)::SendMessage(m_hWnd, ACM_ISPLAYING, 0, 0L);
7278 }
7279 };
7280
7281 typedef CAnimateCtrlT<ATL::CWindow> CAnimateCtrl;
7282
7283 #endif // !_WIN32_WCE
7284
7285
7286 ///////////////////////////////////////////////////////////////////////////////
7287 // CRichEditCtrl
7288
7289 #ifndef _WIN32_WCE
7290
7291 #if defined(_UNICODE) && (_RICHEDIT_VER == 0x0100)
7292 #undef RICHEDIT_CLASS
7293 #define RICHEDIT_CLASS L"RICHEDIT"
7294 #endif
7295
7296 #if !defined(_UNICODE) && (_RICHEDIT_VER >= 0x0500)
7297 #undef MSFTEDIT_CLASS
7298 #define MSFTEDIT_CLASS "RICHEDIT50W"
7299 #endif
7300
7301 template <class TBase>
7302 class CRichEditCtrlT : public TBase
7303 {
7304 public:
7305 // Constructors
7306 CRichEditCtrlT(HWND hWnd = NULL) : TBase(hWnd)
7307 { }
7308
7309 CRichEditCtrlT< TBase >& operator =(HWND hWnd)
7310 {
7311 m_hWnd = hWnd;
7312 return *this;
7313 }
7314
7315 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
7316 DWORD dwStyle = 0, DWORD dwExStyle = 0,
7317 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
7318 {
7319 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
7320 }
7321
7322 // Attributes
7323 static LPCTSTR GetWndClassName()
7324 {
7325 #if (_RICHEDIT_VER >= 0x0500)
7326 return MSFTEDIT_CLASS;
7327 #else
7328 return RICHEDIT_CLASS;
7329 #endif
7330 }
7331
7332 static LPCTSTR GetLibraryName()
7333 {
7334 #if (_RICHEDIT_VER >= 0x0500)
7335 return _T("MSFTEDIT.DLL");
7336 #elif (_RICHEDIT_VER >= 0x0200)
7337 return _T("RICHED20.DLL");
7338 #else
7339 return _T("RICHED32.DLL");
7340 #endif
7341 }
7342
7343 int GetLineCount() const
7344 {
7345 ATLASSERT(::IsWindow(m_hWnd));
7346 return (int)::SendMessage(m_hWnd, EM_GETLINECOUNT, 0, 0L);
7347 }
7348
7349 BOOL GetModify() const
7350 {
7351 ATLASSERT(::IsWindow(m_hWnd));
7352 return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
7353 }
7354
7355 void SetModify(BOOL bModified = TRUE)
7356 {
7357 ATLASSERT(::IsWindow(m_hWnd));
7358 ::SendMessage(m_hWnd, EM_SETMODIFY, bModified, 0L);
7359 }
7360
7361 void GetRect(LPRECT lpRect) const
7362 {
7363 ATLASSERT(::IsWindow(m_hWnd));
7364 ::SendMessage(m_hWnd, EM_GETRECT, 0, (LPARAM)lpRect);
7365 }
7366
7367 DWORD GetOptions() const
7368 {
7369 ATLASSERT(::IsWindow(m_hWnd));
7370 return (DWORD)::SendMessage(m_hWnd, EM_GETOPTIONS, 0, 0L);
7371 }
7372
7373 DWORD SetOptions(WORD wOperation, DWORD dwOptions)
7374 {
7375 ATLASSERT(::IsWindow(m_hWnd));
7376 return (DWORD)::SendMessage(m_hWnd, EM_SETOPTIONS, wOperation, dwOptions);
7377 }
7378
7379 // NOTE: first word in lpszBuffer must contain the size of the buffer!
7380 int GetLine(int nIndex, LPTSTR lpszBuffer) const
7381 {
7382 ATLASSERT(::IsWindow(m_hWnd));
7383 return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
7384 }
7385
7386 int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
7387 {
7388 ATLASSERT(::IsWindow(m_hWnd));
7389 *(LPWORD)lpszBuffer = (WORD)nMaxLength;
7390 return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
7391 }
7392
7393 BOOL CanUndo() const
7394 {
7395 ATLASSERT(::IsWindow(m_hWnd));
7396 return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
7397 }
7398
7399 BOOL CanPaste(UINT nFormat = 0) const
7400 {
7401 ATLASSERT(::IsWindow(m_hWnd));
7402 return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, nFormat, 0L);
7403 }
7404
7405 void GetSel(LONG& nStartChar, LONG& nEndChar) const
7406 {
7407 ATLASSERT(::IsWindow(m_hWnd));
7408 CHARRANGE cr = { 0, 0 };
7409 ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7410 nStartChar = cr.cpMin;
7411 nEndChar = cr.cpMax;
7412 }
7413
7414 void GetSel(CHARRANGE &cr) const
7415 {
7416 ATLASSERT(::IsWindow(m_hWnd));
7417 ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7418 }
7419
7420 int SetSel(LONG nStartChar, LONG nEndChar)
7421 {
7422 ATLASSERT(::IsWindow(m_hWnd));
7423 CHARRANGE cr = { nStartChar, nEndChar };
7424 return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr);
7425 }
7426
7427 int SetSel(CHARRANGE &cr)
7428 {
7429 ATLASSERT(::IsWindow(m_hWnd));
7430 return (int)::SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&cr);
7431 }
7432
7433 int SetSelAll()
7434 {
7435 return SetSel(0, -1);
7436 }
7437
7438 int SetSelNone()
7439 {
7440 return SetSel(-1, 0);
7441 }
7442
7443 DWORD GetDefaultCharFormat(CHARFORMAT& cf) const
7444 {
7445 ATLASSERT(::IsWindow(m_hWnd));
7446 cf.cbSize = sizeof(CHARFORMAT);
7447 return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf);
7448 }
7449
7450 DWORD GetSelectionCharFormat(CHARFORMAT& cf) const
7451 {
7452 ATLASSERT(::IsWindow(m_hWnd));
7453 cf.cbSize = sizeof(CHARFORMAT);
7454 return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf);
7455 }
7456
7457 DWORD GetEventMask() const
7458 {
7459 ATLASSERT(::IsWindow(m_hWnd));
7460 return (DWORD)::SendMessage(m_hWnd, EM_GETEVENTMASK, 0, 0L);
7461 }
7462
7463 LONG GetLimitText() const
7464 {
7465 ATLASSERT(::IsWindow(m_hWnd));
7466 return (LONG)::SendMessage(m_hWnd, EM_GETLIMITTEXT, 0, 0L);
7467 }
7468
7469 DWORD GetParaFormat(PARAFORMAT& pf) const
7470 {
7471 ATLASSERT(::IsWindow(m_hWnd));
7472 pf.cbSize = sizeof(PARAFORMAT);
7473 return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
7474 }
7475
7476 #if (_RICHEDIT_VER >= 0x0200)
7477 LONG GetSelText(LPTSTR lpstrBuff) const
7478 {
7479 ATLASSERT(::IsWindow(m_hWnd));
7480 return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff);
7481 }
7482 #else // !(_RICHEDIT_VER >= 0x0200)
7483 // RichEdit 1.0 EM_GETSELTEXT is ANSI only
7484 LONG GetSelText(LPSTR lpstrBuff) const
7485 {
7486 ATLASSERT(::IsWindow(m_hWnd));
7487 return (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrBuff);
7488 }
7489 #endif // !(_RICHEDIT_VER >= 0x0200)
7490
7491 #ifndef _ATL_NO_COM
7492 BOOL GetSelTextBSTR(BSTR& bstrText) const
7493 {
7494 USES_CONVERSION;
7495 ATLASSERT(::IsWindow(m_hWnd));
7496 ATLASSERT(bstrText == NULL);
7497
7498 CHARRANGE cr = { 0, 0 };
7499 ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7500
7501 #if (_RICHEDIT_VER >= 0x0200)
7502 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
7503 LPTSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
7504 if(lpstrText == NULL)
7505 return FALSE;
7506 if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0)
7507 return FALSE;
7508
7509 bstrText = ::SysAllocString(T2W(lpstrText));
7510 #else // !(_RICHEDIT_VER >= 0x0200)
7511 CTempBuffer<char, _WTL_STACK_ALLOC_THRESHOLD> buff;
7512 LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
7513 if(lpstrText == NULL)
7514 return FALSE;
7515 if(::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText) == 0)
7516 return FALSE;
7517
7518 bstrText = ::SysAllocString(A2W(lpstrText));
7519 #endif // !(_RICHEDIT_VER >= 0x0200)
7520
7521 return (bstrText != NULL) ? TRUE : FALSE;
7522 }
7523 #endif // !_ATL_NO_COM
7524
7525 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
7526 LONG GetSelText(_CSTRING_NS::CString& strText) const
7527 {
7528 ATLASSERT(::IsWindow(m_hWnd));
7529
7530 CHARRANGE cr = { 0, 0 };
7531 ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
7532
7533 #if (_RICHEDIT_VER >= 0x0200)
7534 LONG lLen = 0;
7535 LPTSTR lpstrText = strText.GetBufferSetLength(cr.cpMax - cr.cpMin);
7536 if(lpstrText != NULL)
7537 {
7538 lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText);
7539 strText.ReleaseBuffer();
7540 }
7541 #else // !(_RICHEDIT_VER >= 0x0200)
7542 CTempBuffer<char, _WTL_STACK_ALLOC_THRESHOLD> buff;
7543 LPSTR lpstrText = buff.Allocate(cr.cpMax - cr.cpMin + 1);
7544 if(lpstrText == NULL)
7545 return 0;
7546 LONG lLen = (LONG)::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpstrText);
7547 if(lLen == 0)
7548 return 0;
7549
7550 USES_CONVERSION;
7551 strText = A2T(lpstrText);
7552 #endif // !(_RICHEDIT_VER >= 0x0200)
7553
7554 return lLen;
7555 }
7556 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
7557
7558 WORD GetSelectionType() const
7559 {
7560 ATLASSERT(::IsWindow(m_hWnd));
7561 return (WORD)::SendMessage(m_hWnd, EM_SELECTIONTYPE, 0, 0L);
7562 }
7563
7564 COLORREF SetBackgroundColor(COLORREF cr)
7565 {
7566 ATLASSERT(::IsWindow(m_hWnd));
7567 return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 0, cr);
7568 }
7569
7570 COLORREF SetBackgroundColor() // sets to system background
7571 {
7572 ATLASSERT(::IsWindow(m_hWnd));
7573 return (COLORREF)::SendMessage(m_hWnd, EM_SETBKGNDCOLOR, 1, 0);
7574 }
7575
7576 BOOL SetCharFormat(CHARFORMAT& cf, WORD wFlags)
7577 {
7578 ATLASSERT(::IsWindow(m_hWnd));
7579 cf.cbSize = sizeof(CHARFORMAT);
7580 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf);
7581 }
7582
7583 BOOL SetDefaultCharFormat(CHARFORMAT& cf)
7584 {
7585 ATLASSERT(::IsWindow(m_hWnd));
7586 cf.cbSize = sizeof(CHARFORMAT);
7587 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
7588 }
7589
7590 BOOL SetSelectionCharFormat(CHARFORMAT& cf)
7591 {
7592 ATLASSERT(::IsWindow(m_hWnd));
7593 cf.cbSize = sizeof(CHARFORMAT);
7594 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
7595 }
7596
7597 BOOL SetWordCharFormat(CHARFORMAT& cf)
7598 {
7599 ATLASSERT(::IsWindow(m_hWnd));
7600 cf.cbSize = sizeof(CHARFORMAT);
7601 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf);
7602 }
7603
7604 DWORD SetEventMask(DWORD dwEventMask)
7605 {
7606 ATLASSERT(::IsWindow(m_hWnd));
7607 return (DWORD)::SendMessage(m_hWnd, EM_SETEVENTMASK, 0, dwEventMask);
7608 }
7609
7610 BOOL SetParaFormat(PARAFORMAT& pf)
7611 {
7612 ATLASSERT(::IsWindow(m_hWnd));
7613 pf.cbSize = sizeof(PARAFORMAT);
7614 return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
7615 }
7616
7617 BOOL SetTargetDevice(HDC hDC, int cxLineWidth)
7618 {
7619 ATLASSERT(::IsWindow(m_hWnd));
7620 return (BOOL)::SendMessage(m_hWnd, EM_SETTARGETDEVICE, (WPARAM)hDC, cxLineWidth);
7621 }
7622
7623 int GetTextLength() const
7624 {
7625 ATLASSERT(::IsWindow(m_hWnd));
7626 return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L);
7627 }
7628
7629 BOOL SetReadOnly(BOOL bReadOnly = TRUE)
7630 {
7631 ATLASSERT(::IsWindow(m_hWnd));
7632 return (BOOL)::SendMessage(m_hWnd, EM_SETREADONLY, bReadOnly, 0L);
7633 }
7634
7635 int GetFirstVisibleLine() const
7636 {
7637 ATLASSERT(::IsWindow(m_hWnd));
7638 return (int)::SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0L);
7639 }
7640
7641 int GetTextRange(TEXTRANGE* pTextRange) const
7642 {
7643 ATLASSERT(::IsWindow(m_hWnd));
7644 return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)pTextRange);
7645 }
7646
7647 #if (_RICHEDIT_VER < 0x0200)
7648 EDITWORDBREAKPROCEX GetWordBreakProcEx() const
7649 {
7650 ATLASSERT(::IsWindow(m_hWnd));
7651 return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_GETWORDBREAKPROCEX, 0, 0L);
7652 }
7653
7654 EDITWORDBREAKPROCEX SetWordBreakProcEx(EDITWORDBREAKPROCEX pfnEditWordBreakProcEx)
7655 {
7656 ATLASSERT(::IsWindow(m_hWnd));
7657 return (EDITWORDBREAKPROCEX)::SendMessage(m_hWnd, EM_SETWORDBREAKPROCEX, 0, (LPARAM)pfnEditWordBreakProcEx);
7658 }
7659 #endif // (_RICHEDIT_VER < 0x0200)
7660
7661 #if (_RICHEDIT_VER >= 0x0200)
7662 int GetTextRange(LONG nStartChar, LONG nEndChar, LPTSTR lpstrText) const
7663 {
7664 ATLASSERT(::IsWindow(m_hWnd));
7665 TEXTRANGE tr = { 0 };
7666 tr.chrg.cpMin = nStartChar;
7667 tr.chrg.cpMax = nEndChar;
7668 tr.lpstrText = lpstrText;
7669 return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
7670 }
7671 #else // !(_RICHEDIT_VER >= 0x0200)
7672 int GetTextRange(LONG nStartChar, LONG nEndChar, LPSTR lpstrText) const
7673 {
7674 ATLASSERT(::IsWindow(m_hWnd));
7675 TEXTRANGE tr = { 0 };
7676 tr.chrg.cpMin = nStartChar;
7677 tr.chrg.cpMax = nEndChar;
7678 tr.lpstrText = lpstrText;
7679 return (int)::SendMessage(m_hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
7680 }
7681 #endif // !(_RICHEDIT_VER >= 0x0200)
7682
7683 #if (_RICHEDIT_VER >= 0x0200)
7684 DWORD GetDefaultCharFormat(CHARFORMAT2& cf) const
7685 {
7686 ATLASSERT(::IsWindow(m_hWnd));
7687 cf.cbSize = sizeof(CHARFORMAT2);
7688 return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 0, (LPARAM)&cf);
7689 }
7690
7691 BOOL SetCharFormat(CHARFORMAT2& cf, WORD wFlags)
7692 {
7693 ATLASSERT(::IsWindow(m_hWnd));
7694 cf.cbSize = sizeof(CHARFORMAT2);
7695 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, (WPARAM)wFlags, (LPARAM)&cf);
7696 }
7697
7698 BOOL SetDefaultCharFormat(CHARFORMAT2& cf)
7699 {
7700 ATLASSERT(::IsWindow(m_hWnd));
7701 cf.cbSize = sizeof(CHARFORMAT2);
7702 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, 0, (LPARAM)&cf);
7703 }
7704
7705 DWORD GetSelectionCharFormat(CHARFORMAT2& cf) const
7706 {
7707 ATLASSERT(::IsWindow(m_hWnd));
7708 cf.cbSize = sizeof(CHARFORMAT2);
7709 return (DWORD)::SendMessage(m_hWnd, EM_GETCHARFORMAT, 1, (LPARAM)&cf);
7710 }
7711
7712 BOOL SetSelectionCharFormat(CHARFORMAT2& cf)
7713 {
7714 ATLASSERT(::IsWindow(m_hWnd));
7715 cf.cbSize = sizeof(CHARFORMAT2);
7716 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
7717 }
7718
7719 BOOL SetWordCharFormat(CHARFORMAT2& cf)
7720 {
7721 ATLASSERT(::IsWindow(m_hWnd));
7722 cf.cbSize = sizeof(CHARFORMAT2);
7723 return (BOOL)::SendMessage(m_hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cf);
7724 }
7725
7726 DWORD GetParaFormat(PARAFORMAT2& pf) const
7727 {
7728 ATLASSERT(::IsWindow(m_hWnd));
7729 pf.cbSize = sizeof(PARAFORMAT2);
7730 return (DWORD)::SendMessage(m_hWnd, EM_GETPARAFORMAT, 0, (LPARAM)&pf);
7731 }
7732
7733 BOOL SetParaFormat(PARAFORMAT2& pf)
7734 {
7735 ATLASSERT(::IsWindow(m_hWnd));
7736 pf.cbSize = sizeof(PARAFORMAT2);
7737 return (BOOL)::SendMessage(m_hWnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
7738 }
7739
7740 TEXTMODE GetTextMode() const
7741 {
7742 ATLASSERT(::IsWindow(m_hWnd));
7743 return (TEXTMODE)::SendMessage(m_hWnd, EM_GETTEXTMODE, 0, 0L);
7744 }
7745
7746 BOOL SetTextMode(TEXTMODE enumTextMode)
7747 {
7748 ATLASSERT(::IsWindow(m_hWnd));
7749 return !(BOOL)::SendMessage(m_hWnd, EM_SETTEXTMODE, enumTextMode, 0L);
7750 }
7751
7752 UNDONAMEID GetUndoName() const
7753 {
7754 ATLASSERT(::IsWindow(m_hWnd));
7755 return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETUNDONAME, 0, 0L);
7756 }
7757
7758 UNDONAMEID GetRedoName() const
7759 {
7760 ATLASSERT(::IsWindow(m_hWnd));
7761 return (UNDONAMEID)::SendMessage(m_hWnd, EM_GETREDONAME, 0, 0L);
7762 }
7763
7764 BOOL CanRedo() const
7765 {
7766 ATLASSERT(::IsWindow(m_hWnd));
7767 return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L);
7768 }
7769
7770 BOOL GetAutoURLDetect() const
7771 {
7772 ATLASSERT(::IsWindow(m_hWnd));
7773 return (BOOL)::SendMessage(m_hWnd, EM_GETAUTOURLDETECT, 0, 0L);
7774 }
7775
7776 BOOL SetAutoURLDetect(BOOL bAutoDetect = TRUE)
7777 {
7778 ATLASSERT(::IsWindow(m_hWnd));
7779 return !(BOOL)::SendMessage(m_hWnd, EM_AUTOURLDETECT, bAutoDetect, 0L);
7780 }
7781
7782 // this method is deprecated, please use SetAutoURLDetect
7783 BOOL EnableAutoURLDetect(BOOL bEnable = TRUE) { return SetAutoURLDetect(bEnable); }
7784
7785 UINT SetUndoLimit(UINT uUndoLimit)
7786 {
7787 ATLASSERT(::IsWindow(m_hWnd));
7788 return (UINT)::SendMessage(m_hWnd, EM_SETUNDOLIMIT, uUndoLimit, 0L);
7789 }
7790
7791 void SetPalette(HPALETTE hPalette)
7792 {
7793 ATLASSERT(::IsWindow(m_hWnd));
7794 ::SendMessage(m_hWnd, EM_SETPALETTE, (WPARAM)hPalette, 0L);
7795 }
7796
7797 int GetTextEx(GETTEXTEX* pGetTextEx, LPTSTR lpstrText) const
7798 {
7799 ATLASSERT(::IsWindow(m_hWnd));
7800 return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)pGetTextEx, (LPARAM)lpstrText);
7801 }
7802
7803 int GetTextEx(LPTSTR lpstrText, int nTextLen, DWORD dwFlags = GT_DEFAULT, UINT uCodePage = CP_ACP, LPCSTR lpDefaultChar = NULL, LPBOOL lpUsedDefChar = NULL) const
7804 {
7805 ATLASSERT(::IsWindow(m_hWnd));
7806 GETTEXTEX gte = { 0 };
7807 gte.cb = nTextLen * sizeof(TCHAR);
7808 gte.codepage = uCodePage;
7809 gte.flags = dwFlags;
7810 gte.lpDefaultChar = lpDefaultChar;
7811 gte.lpUsedDefChar = lpUsedDefChar;
7812 return (int)::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)&gte, (LPARAM)lpstrText);
7813 }
7814
7815 int GetTextLengthEx(GETTEXTLENGTHEX* pGetTextLengthEx) const
7816 {
7817 ATLASSERT(::IsWindow(m_hWnd));
7818 return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)pGetTextLengthEx, 0L);
7819 }
7820
7821 int GetTextLengthEx(DWORD dwFlags = GTL_DEFAULT, UINT uCodePage = CP_ACP) const
7822 {
7823 ATLASSERT(::IsWindow(m_hWnd));
7824 GETTEXTLENGTHEX gtle = { 0 };
7825 gtle.codepage = uCodePage;
7826 gtle.flags = dwFlags;
7827 return (int)::SendMessage(m_hWnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtle, 0L);
7828 }
7829
7830 EDITWORDBREAKPROC GetWordBreakProc() const
7831 {
7832 ATLASSERT(::IsWindow(m_hWnd));
7833 return (EDITWORDBREAKPROC)::SendMessage(m_hWnd, EM_GETWORDBREAKPROC, 0, 0L);
7834 }
7835
7836 void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
7837 {
7838 ATLASSERT(::IsWindow(m_hWnd));
7839 ::SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
7840 }
7841 #endif // (_RICHEDIT_VER >= 0x0200)
7842
7843 #if (_RICHEDIT_VER >= 0x0300)
7844 int SetTextEx(SETTEXTEX* pSetTextEx, LPCTSTR lpstrText)
7845 {
7846 ATLASSERT(::IsWindow(m_hWnd));
7847 return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)pSetTextEx, (LPARAM)lpstrText);
7848 }
7849
7850 int SetTextEx(LPCTSTR lpstrText, DWORD dwFlags = ST_DEFAULT, UINT uCodePage = CP_ACP)
7851 {
7852 ATLASSERT(::IsWindow(m_hWnd));
7853 SETTEXTEX ste = { 0 };
7854 ste.flags = dwFlags;
7855 ste.codepage = uCodePage;
7856 return (int)::SendMessage(m_hWnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpstrText);
7857 }
7858
7859 int GetEditStyle() const
7860 {
7861 ATLASSERT(::IsWindow(m_hWnd));
7862 return (int)::SendMessage(m_hWnd, EM_GETEDITSTYLE, 0, 0L);
7863 }
7864
7865 int SetEditStyle(int nStyle, int nMask = -1)
7866 {
7867 ATLASSERT(::IsWindow(m_hWnd));
7868 if(nMask == -1)
7869 nMask = nStyle; // set everything specified
7870 return (int)::SendMessage(m_hWnd, EM_SETEDITSTYLE, nStyle, nMask);
7871 }
7872
7873 BOOL SetFontSize(int nFontSizeDelta)
7874 {
7875 ATLASSERT(::IsWindow(m_hWnd));
7876 ATLASSERT(nFontSizeDelta >= -1637 && nFontSizeDelta <= 1638);
7877 return (BOOL)::SendMessage(m_hWnd, EM_SETFONTSIZE, nFontSizeDelta, 0L);
7878 }
7879
7880 void GetScrollPos(LPPOINT lpPoint) const
7881 {
7882 ATLASSERT(::IsWindow(m_hWnd));
7883 ATLASSERT(lpPoint != NULL);
7884 ::SendMessage(m_hWnd, EM_GETSCROLLPOS, 0, (LPARAM)lpPoint);
7885 }
7886
7887 void SetScrollPos(LPPOINT lpPoint)
7888 {
7889 ATLASSERT(::IsWindow(m_hWnd));
7890 ATLASSERT(lpPoint != NULL);
7891 ::SendMessage(m_hWnd, EM_SETSCROLLPOS, 0, (LPARAM)lpPoint);
7892 }
7893
7894 BOOL GetZoom(int& nNum, int& nDen) const
7895 {
7896 ATLASSERT(::IsWindow(m_hWnd));
7897 return (BOOL)::SendMessage(m_hWnd, EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen);
7898 }
7899
7900 BOOL SetZoom(int nNum, int nDen)
7901 {
7902 ATLASSERT(::IsWindow(m_hWnd));
7903 ATLASSERT(nNum >= 0 && nNum <= 64);
7904 ATLASSERT(nDen >= 0 && nDen <= 64);
7905 return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, nNum, nDen);
7906 }
7907
7908 BOOL SetZoomOff()
7909 {
7910 ATLASSERT(::IsWindow(m_hWnd));
7911 return (BOOL)::SendMessage(m_hWnd, EM_SETZOOM, 0, 0L);
7912 }
7913
7914 void SetMargins(UINT nLeft, UINT nRight, WORD wFlags = EC_LEFTMARGIN | EC_RIGHTMARGIN)
7915 {
7916 ATLASSERT(::IsWindow(m_hWnd));
7917 ::SendMessage(m_hWnd, EM_SETMARGINS, wFlags, MAKELONG(nLeft, nRight));
7918 }
7919 #endif // (_RICHEDIT_VER >= 0x0300)
7920
7921 // Operations
7922 void LimitText(LONG nChars = 0)
7923 {
7924 ATLASSERT(::IsWindow(m_hWnd));
7925 ::SendMessage(m_hWnd, EM_EXLIMITTEXT, 0, nChars);
7926 }
7927
7928 int LineFromChar(LONG nIndex) const
7929 {
7930 ATLASSERT(::IsWindow(m_hWnd));
7931 return (int)::SendMessage(m_hWnd, EM_EXLINEFROMCHAR, 0, nIndex);
7932 }
7933
7934 POINT PosFromChar(LONG nChar) const
7935 {
7936 ATLASSERT(::IsWindow(m_hWnd));
7937 POINT point = { 0, 0 };
7938 ::SendMessage(m_hWnd, EM_POSFROMCHAR, (WPARAM)&point, nChar);
7939 return point;
7940 }
7941
7942 int CharFromPos(POINT pt) const
7943 {
7944 ATLASSERT(::IsWindow(m_hWnd));
7945 POINTL ptl = { pt.x, pt.y };
7946 return (int)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, (LPARAM)&ptl);
7947 }
7948
7949 void EmptyUndoBuffer()
7950 {
7951 ATLASSERT(::IsWindow(m_hWnd));
7952 ::SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0L);
7953 }
7954
7955 int LineIndex(int nLine = -1) const
7956 {
7957 ATLASSERT(::IsWindow(m_hWnd));
7958 return (int)::SendMessage(m_hWnd, EM_LINEINDEX, nLine, 0L);
7959 }
7960
7961 int LineLength(int nLine = -1) const
7962 {
7963 ATLASSERT(::IsWindow(m_hWnd));
7964 return (int)::SendMessage(m_hWnd, EM_LINELENGTH, nLine, 0L);
7965 }
7966
7967 BOOL LineScroll(int nLines)
7968 {
7969 ATLASSERT(::IsWindow(m_hWnd));
7970 return (BOOL)::SendMessage(m_hWnd, EM_LINESCROLL, 0, nLines);
7971 }
7972
7973 void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
7974 {
7975 ATLASSERT(::IsWindow(m_hWnd));
7976 ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
7977 }
7978
7979 void SetRect(LPCRECT lpRect)
7980 {
7981 ATLASSERT(::IsWindow(m_hWnd));
7982 ::SendMessage(m_hWnd, EM_SETRECT, 0, (LPARAM)lpRect);
7983 }
7984
7985 BOOL DisplayBand(LPRECT pDisplayRect)
7986 {
7987 ATLASSERT(::IsWindow(m_hWnd));
7988 return (BOOL)::SendMessage(m_hWnd, EM_DISPLAYBAND, 0, (LPARAM)pDisplayRect);
7989 }
7990
7991 LONG FindText(DWORD dwFlags, FINDTEXT& ft) const
7992 {
7993 ATLASSERT(::IsWindow(m_hWnd));
7994 #if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE)
7995 return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTW, dwFlags, (LPARAM)&ft);
7996 #else
7997 return (LONG)::SendMessage(m_hWnd, EM_FINDTEXT, dwFlags, (LPARAM)&ft);
7998 #endif
7999 }
8000
8001 LONG FindText(DWORD dwFlags, FINDTEXTEX& ft) const
8002 {
8003 ATLASSERT(::IsWindow(m_hWnd));
8004 #if (_RICHEDIT_VER >= 0x0200) && defined(_UNICODE)
8005 return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEXW, dwFlags, (LPARAM)&ft);
8006 #else
8007 return (LONG)::SendMessage(m_hWnd, EM_FINDTEXTEX, dwFlags, (LPARAM)&ft);
8008 #endif
8009 }
8010
8011 LONG FormatRange(FORMATRANGE& fr, BOOL bDisplay = TRUE)
8012 {
8013 ATLASSERT(::IsWindow(m_hWnd));
8014 return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)&fr);
8015 }
8016
8017 LONG FormatRange(FORMATRANGE* pFormatRange, BOOL bDisplay = TRUE)
8018 {
8019 ATLASSERT(::IsWindow(m_hWnd));
8020 return (LONG)::SendMessage(m_hWnd, EM_FORMATRANGE, bDisplay, (LPARAM)pFormatRange);
8021 }
8022
8023 void HideSelection(BOOL bHide = TRUE, BOOL bChangeStyle = FALSE)
8024 {
8025 ATLASSERT(::IsWindow(m_hWnd));
8026 ::SendMessage(m_hWnd, EM_HIDESELECTION, bHide, bChangeStyle);
8027 }
8028
8029 void PasteSpecial(UINT uClipFormat, DWORD dwAspect = 0, HMETAFILE hMF = 0)
8030 {
8031 ATLASSERT(::IsWindow(m_hWnd));
8032 REPASTESPECIAL reps = { dwAspect, (DWORD_PTR)hMF };
8033 ::SendMessage(m_hWnd, EM_PASTESPECIAL, uClipFormat, (LPARAM)&reps);
8034 }
8035
8036 void RequestResize()
8037 {
8038 ATLASSERT(::IsWindow(m_hWnd));
8039 ::SendMessage(m_hWnd, EM_REQUESTRESIZE, 0, 0L);
8040 }
8041
8042 LONG StreamIn(UINT uFormat, EDITSTREAM& es)
8043 {
8044 ATLASSERT(::IsWindow(m_hWnd));
8045 return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, uFormat, (LPARAM)&es);
8046 }
8047
8048 LONG StreamOut(UINT uFormat, EDITSTREAM& es)
8049 {
8050 ATLASSERT(::IsWindow(m_hWnd));
8051 return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, uFormat, (LPARAM)&es);
8052 }
8053
8054 DWORD FindWordBreak(int nCode, LONG nStartChar)
8055 {
8056 ATLASSERT(::IsWindow(m_hWnd));
8057 return (DWORD)::SendMessage(m_hWnd, EM_FINDWORDBREAK, nCode, nStartChar);
8058 }
8059
8060 // Additional operations
8061 void ScrollCaret()
8062 {
8063 ATLASSERT(::IsWindow(m_hWnd));
8064 ::SendMessage(m_hWnd, EM_SCROLLCARET, 0, 0L);
8065 }
8066
8067 int InsertText(long nInsertAfterChar, LPCTSTR lpstrText, BOOL bCanUndo = FALSE)
8068 {
8069 int nRet = SetSel(nInsertAfterChar, nInsertAfterChar);
8070 ReplaceSel(lpstrText, bCanUndo);
8071 return nRet;
8072 }
8073
8074 int AppendText(LPCTSTR lpstrText, BOOL bCanUndo = FALSE)
8075 {
8076 return InsertText(GetWindowTextLength(), lpstrText, bCanUndo);
8077 }
8078
8079 // Clipboard operations
8080 BOOL Undo()
8081 {
8082 ATLASSERT(::IsWindow(m_hWnd));
8083 return (BOOL)::SendMessage(m_hWnd, EM_UNDO, 0, 0L);
8084 }
8085
8086 void Clear()
8087 {
8088 ATLASSERT(::IsWindow(m_hWnd));
8089 ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
8090 }
8091
8092 void Copy()
8093 {
8094 ATLASSERT(::IsWindow(m_hWnd));
8095 ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
8096 }
8097
8098 void Cut()
8099 {
8100 ATLASSERT(::IsWindow(m_hWnd));
8101 ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
8102 }
8103
8104 void Paste()
8105 {
8106 ATLASSERT(::IsWindow(m_hWnd));
8107 ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
8108 }
8109
8110 // OLE support
8111 IRichEditOle* GetOleInterface() const
8112 {
8113 ATLASSERT(::IsWindow(m_hWnd));
8114 IRichEditOle *pRichEditOle = NULL;
8115 ::SendMessage(m_hWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
8116 return pRichEditOle;
8117 }
8118
8119 BOOL SetOleCallback(IRichEditOleCallback* pCallback)
8120 {
8121 ATLASSERT(::IsWindow(m_hWnd));
8122 return (BOOL)::SendMessage(m_hWnd, EM_SETOLECALLBACK, 0, (LPARAM)pCallback);
8123 }
8124
8125 #if (_RICHEDIT_VER >= 0x0200)
8126 BOOL Redo()
8127 {
8128 ATLASSERT(::IsWindow(m_hWnd));
8129 return (BOOL)::SendMessage(m_hWnd, EM_REDO, 0, 0L);
8130 }
8131
8132 void StopGroupTyping()
8133 {
8134 ATLASSERT(::IsWindow(m_hWnd));
8135 ::SendMessage(m_hWnd, EM_STOPGROUPTYPING, 0, 0L);
8136 }
8137
8138 void ShowScrollBar(int nBarType, BOOL bVisible = TRUE)
8139 {
8140 ATLASSERT(::IsWindow(m_hWnd));
8141 ::SendMessage(m_hWnd, EM_SHOWSCROLLBAR, nBarType, bVisible);
8142 }
8143 #endif // (_RICHEDIT_VER >= 0x0200)
8144
8145 #if (_RICHEDIT_VER >= 0x0300)
8146 BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
8147 {
8148 ATLASSERT(::IsWindow(m_hWnd));
8149 return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
8150 }
8151
8152 BOOL SetTabStops()
8153 {
8154 ATLASSERT(::IsWindow(m_hWnd));
8155 return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 0, 0L);
8156 }
8157
8158 BOOL SetTabStops(const int& cxEachStop) // takes an 'int'
8159 {
8160 ATLASSERT(::IsWindow(m_hWnd));
8161 return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
8162 }
8163 #endif // (_RICHEDIT_VER >= 0x0300)
8164
8165 #if (_RICHEDIT_VER >= 0x0800)
8166 AutoCorrectProc GetAutoCorrectProc() const
8167 {
8168 ATLASSERT(::IsWindow(m_hWnd));
8169 return (AutoCorrectProc)::SendMessage(m_hWnd, EM_GETAUTOCORRECTPROC, 0, 0L);
8170 }
8171
8172 BOOL SetAutoCorrectProc(AutoCorrectProc pfn)
8173 {
8174 ATLASSERT(::IsWindow(m_hWnd));
8175 return (BOOL)::SendMessage(m_hWnd, EM_SETAUTOCORRECTPROC, (WPARAM)pfn, 0L);
8176 }
8177
8178 BOOL CallAutoCorrectProc(WCHAR ch)
8179 {
8180 ATLASSERT(::IsWindow(m_hWnd));
8181 return (BOOL)::SendMessage(m_hWnd, EM_CALLAUTOCORRECTPROC, (WPARAM)ch, 0L);
8182 }
8183
8184 DWORD GetEditStyleEx() const
8185 {
8186 ATLASSERT(::IsWindow(m_hWnd));
8187 return (DWORD)::SendMessage(m_hWnd, EM_GETEDITSTYLEEX, 0, 0L);
8188 }
8189
8190 DWORD SetEditStyleEx(DWORD dwStyleEx, DWORD dwMask)
8191 {
8192 ATLASSERT(::IsWindow(m_hWnd));
8193 return (DWORD)::SendMessage(m_hWnd, EM_SETEDITSTYLEEX, dwStyleEx, dwMask);
8194 }
8195
8196 DWORD GetStoryType(int nStoryIndex) const
8197 {
8198 ATLASSERT(::IsWindow(m_hWnd));
8199 return (DWORD)::SendMessage(m_hWnd, EM_GETSTORYTYPE, nStoryIndex, 0L);
8200 }
8201
8202 DWORD SetStoryType(int nStoryIndex, DWORD dwStoryType)
8203 {
8204 ATLASSERT(::IsWindow(m_hWnd));
8205 return (DWORD)::SendMessage(m_hWnd, EM_SETSTORYTYPE, nStoryIndex, dwStoryType);
8206 }
8207
8208 DWORD GetEllipsisMode() const
8209 {
8210 ATLASSERT(::IsWindow(m_hWnd));
8211
8212 DWORD dwMode = 0;
8213 BOOL bRet = (BOOL)::SendMessage(m_hWnd, EM_GETELLIPSISMODE, 0, (LPARAM)&dwMode);
8214 bRet; // avoid level 4 warning
8215 ATLASSERT(bRet != FALSE);
8216
8217 return dwMode;
8218 }
8219
8220 BOOL SetEllipsisMode(DWORD dwEllipsisMode)
8221 {
8222 ATLASSERT(::IsWindow(m_hWnd));
8223 return (BOOL)::SendMessage(m_hWnd, EM_SETELLIPSISMODE, 0, dwEllipsisMode);
8224 }
8225
8226 BOOL GetEllipsisState() const
8227 {
8228 ATLASSERT(::IsWindow(m_hWnd));
8229 return (BOOL)::SendMessage(m_hWnd, EM_GETELLIPSISSTATE, 0, 0L);
8230 }
8231
8232 BOOL GetTouchOptions(int nTouchOptions) const
8233 {
8234 ATLASSERT(::IsWindow(m_hWnd));
8235 return (BOOL)::SendMessage(m_hWnd, EM_GETTOUCHOPTIONS, nTouchOptions, 0L);
8236 }
8237
8238 void SetTouchOptions(int nTouchOptions, BOOL bEnable)
8239 {
8240 ATLASSERT(::IsWindow(m_hWnd));
8241 ::SendMessage(m_hWnd, EM_SETTOUCHOPTIONS, nTouchOptions, bEnable);
8242 }
8243
8244 HRESULT InsertTable(TABLEROWPARMS* pRowParams, TABLECELLPARMS* pCellParams)
8245 {
8246 ATLASSERT(::IsWindow(m_hWnd));
8247 return (HRESULT)::SendMessage(m_hWnd, EM_INSERTTABLE, (WPARAM)pRowParams, (LPARAM)pCellParams);
8248 }
8249
8250 HRESULT GetTableParams(TABLEROWPARMS* pRowParams, TABLECELLPARMS* pCellParams) const
8251 {
8252 ATLASSERT(::IsWindow(m_hWnd));
8253 return (HRESULT)::SendMessage(m_hWnd, EM_GETTABLEPARMS, (WPARAM)pRowParams, (LPARAM)pCellParams);
8254 }
8255
8256 HRESULT SetTableParams(TABLEROWPARMS* pRowParams, TABLECELLPARMS* pCellParams)
8257 {
8258 ATLASSERT(::IsWindow(m_hWnd));
8259 return (HRESULT)::SendMessage(m_hWnd, EM_SETTABLEPARMS, (WPARAM)pRowParams, (LPARAM)pCellParams);
8260 }
8261
8262 HRESULT InsertImage(RICHEDIT_IMAGE_PARAMETERS* pParams)
8263 {
8264 ATLASSERT(::IsWindow(m_hWnd));
8265 return (HRESULT)::SendMessage(m_hWnd, EM_INSERTIMAGE, 0, (LPARAM)pParams);
8266 }
8267
8268 BOOL SetUiaName(LPCTSTR lpstrName)
8269 {
8270 ATLASSERT(::IsWindow(m_hWnd));
8271 return (BOOL)::SendMessage(m_hWnd, EM_SETUIANAME, 0, (LPARAM)lpstrName);
8272 }
8273 #endif // (_RICHEDIT_VER >= 0x0800)
8274 };
8275
8276 typedef CRichEditCtrlT<ATL::CWindow> CRichEditCtrl;
8277
8278 #endif // !_WIN32_WCE
8279
8280
8281 ///////////////////////////////////////////////////////////////////////////////
8282 // CRichEditCommands - message handlers for standard EDIT commands
8283
8284 #ifndef _WIN32_WCE
8285
8286 // Chain to CRichEditCommands message map. Your class must also derive from CRichEditCtrl.
8287 // Example:
8288 // class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>,
8289 // public CRichEditCommands<CMyRichEdit>
8290 // {
8291 // public:
8292 // BEGIN_MSG_MAP(CMyRichEdit)
8293 // // your handlers...
8294 // CHAIN_MSG_MAP_ALT(CRichEditCommands<CMyRichEdit>, 1)
8295 // END_MSG_MAP()
8296 // // other stuff...
8297 // };
8298
8299 template <class T>
8300 class CRichEditCommands : public CEditCommands< T >
8301 {
8302 public:
8303 BEGIN_MSG_MAP(CRichEditCommands< T >)
8304 ALT_MSG_MAP(1)
8305 COMMAND_ID_HANDLER(ID_EDIT_CLEAR, CEditCommands< T >::OnEditClear)
8306 COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, CEditCommands< T >::OnEditClearAll)
8307 COMMAND_ID_HANDLER(ID_EDIT_COPY, CEditCommands< T >::OnEditCopy)
8308 COMMAND_ID_HANDLER(ID_EDIT_CUT, CEditCommands< T >::OnEditCut)
8309 COMMAND_ID_HANDLER(ID_EDIT_PASTE, CEditCommands< T >::OnEditPaste)
8310 COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, CEditCommands< T >::OnEditSelectAll)
8311 COMMAND_ID_HANDLER(ID_EDIT_UNDO, CEditCommands< T >::OnEditUndo)
8312 #if (_RICHEDIT_VER >= 0x0200)
8313 COMMAND_ID_HANDLER(ID_EDIT_REDO, OnEditRedo)
8314 #endif // (_RICHEDIT_VER >= 0x0200)
8315 END_MSG_MAP()
8316
8317 #if (_RICHEDIT_VER >= 0x0200)
8318 LRESULT OnEditRedo(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
8319 {
8320 T* pT = static_cast<T*>(this);
8321 pT->Redo();
8322 return 0;
8323 }
8324 #endif // (_RICHEDIT_VER >= 0x0200)
8325
8326 // State (update UI) helpers
8327 BOOL CanCut() const
8328 { return HasSelection(); }
8329
8330 BOOL CanCopy() const
8331 { return HasSelection(); }
8332
8333 BOOL CanClear() const
8334 { return HasSelection(); }
8335
8336 // Implementation
8337 BOOL HasSelection() const
8338 {
8339 const T* pT = static_cast<const T*>(this);
8340 return (pT->GetSelectionType() != SEL_EMPTY);
8341 }
8342 };
8343
8344 #endif // _WIN32_WCE
8345
8346
8347 ///////////////////////////////////////////////////////////////////////////////
8348 // CDragListBox
8349
8350 #ifndef _WIN32_WCE
8351
8352 template <class TBase>
8353 class CDragListBoxT : public CListBoxT< TBase >
8354 {
8355 public:
8356 // Constructors
8357 CDragListBoxT(HWND hWnd = NULL) : CListBoxT< TBase >(hWnd)
8358 { }
8359
8360 CDragListBoxT< TBase >& operator =(HWND hWnd)
8361 {
8362 m_hWnd = hWnd;
8363 return *this;
8364 }
8365
8366 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8367 DWORD dwStyle = 0, DWORD dwExStyle = 0,
8368 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8369 {
8370 HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8371 if(hWnd != NULL)
8372 MakeDragList();
8373 return hWnd;
8374 }
8375
8376 // Operations
8377 BOOL MakeDragList()
8378 {
8379 ATLASSERT(::IsWindow(m_hWnd));
8380 ATLASSERT((GetStyle() & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == 0);
8381 return ::MakeDragList(m_hWnd);
8382 }
8383
8384 int LBItemFromPt(POINT pt, BOOL bAutoScroll = TRUE)
8385 {
8386 ATLASSERT(::IsWindow(m_hWnd));
8387 return ::LBItemFromPt(m_hWnd, pt, bAutoScroll);
8388 }
8389
8390 void DrawInsert(int nItem)
8391 {
8392 ATLASSERT(::IsWindow(m_hWnd));
8393 ::DrawInsert(GetParent(), m_hWnd, nItem);
8394 }
8395
8396 static UINT GetDragListMessage()
8397 {
8398 static UINT uDragListMessage = 0;
8399 if(uDragListMessage == 0)
8400 {
8401 CStaticDataInitCriticalSectionLock lock;
8402 if(FAILED(lock.Lock()))
8403 {
8404 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDragListBox::GetDragListMessage.\n"));
8405 ATLASSERT(FALSE);
8406 return 0;
8407 }
8408
8409 if(uDragListMessage == 0)
8410 uDragListMessage = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
8411
8412 lock.Unlock();
8413 }
8414 ATLASSERT(uDragListMessage != 0);
8415 return uDragListMessage;
8416 }
8417 };
8418
8419 typedef CDragListBoxT<ATL::CWindow> CDragListBox;
8420
8421 template <class T>
8422 class CDragListNotifyImpl
8423 {
8424 public:
8425 BEGIN_MSG_MAP(CDragListNotifyImpl< T >)
8426 MESSAGE_HANDLER(CDragListBox::GetDragListMessage(), OnDragListNotify)
8427 END_MSG_MAP()
8428
8429 LRESULT OnDragListNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
8430 {
8431 uMsg; // avoid level 4 warning
8432 ATLASSERT(uMsg == CDragListBox::GetDragListMessage());
8433 T* pT = static_cast<T*>(this);
8434 LPDRAGLISTINFO lpDragListInfo = (LPDRAGLISTINFO)lParam;
8435 LRESULT lRet = 0;
8436 switch(lpDragListInfo->uNotification)
8437 {
8438 case DL_BEGINDRAG:
8439 lRet = (LPARAM)pT->OnBeginDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8440 break;
8441 case DL_CANCELDRAG:
8442 pT->OnCancelDrag((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8443 break;
8444 case DL_DRAGGING:
8445 lRet = (LPARAM)pT->OnDragging((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8446 break;
8447 case DL_DROPPED:
8448 pT->OnDropped((int)wParam, lpDragListInfo->hWnd, lpDragListInfo->ptCursor);
8449 break;
8450 default:
8451 ATLTRACE2(atlTraceUI, 0, _T("Unknown DragListBox notification\n"));
8452 bHandled = FALSE; // don't handle it
8453 break;
8454 }
8455 return lRet;
8456 }
8457
8458 // Overrideables
8459 BOOL OnBeginDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8460 {
8461 return TRUE; // allow dragging
8462 }
8463
8464 void OnCancelDrag(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8465 {
8466 // nothing to do
8467 }
8468
8469 int OnDragging(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8470 {
8471 return 0; // don't change cursor
8472 }
8473
8474 void OnDropped(int /*nCtlID*/, HWND /*hWndDragList*/, POINT /*ptCursor*/)
8475 {
8476 // nothing to do
8477 }
8478 };
8479
8480 #endif // _WIN32_WCE
8481
8482
8483 ///////////////////////////////////////////////////////////////////////////////
8484 // CReBarCtrl
8485
8486 template <class TBase>
8487 class CReBarCtrlT : public TBase
8488 {
8489 public:
8490 // Constructors
8491 CReBarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
8492 { }
8493
8494 CReBarCtrlT< TBase >& operator =(HWND hWnd)
8495 {
8496 m_hWnd = hWnd;
8497 return *this;
8498 }
8499
8500 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8501 DWORD dwStyle = 0, DWORD dwExStyle = 0,
8502 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8503 {
8504 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8505 }
8506
8507 // Attributes
8508 static LPCTSTR GetWndClassName()
8509 {
8510 return REBARCLASSNAME;
8511 }
8512
8513 UINT GetBandCount() const
8514 {
8515 ATLASSERT(::IsWindow(m_hWnd));
8516 return (UINT)::SendMessage(m_hWnd, RB_GETBANDCOUNT, 0, 0L);
8517 }
8518
8519 BOOL GetBandInfo(int nBand, LPREBARBANDINFO lprbbi) const
8520 {
8521 ATLASSERT(::IsWindow(m_hWnd));
8522 return (BOOL)::SendMessage(m_hWnd, RB_GETBANDINFO, nBand, (LPARAM)lprbbi);
8523 }
8524
8525 BOOL SetBandInfo(int nBand, LPREBARBANDINFO lprbbi)
8526 {
8527 ATLASSERT(::IsWindow(m_hWnd));
8528 return (BOOL)::SendMessage(m_hWnd, RB_SETBANDINFO, nBand, (LPARAM)lprbbi);
8529 }
8530
8531 BOOL GetBarInfo(LPREBARINFO lprbi) const
8532 {
8533 ATLASSERT(::IsWindow(m_hWnd));
8534 return (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)lprbi);
8535 }
8536
8537 BOOL SetBarInfo(LPREBARINFO lprbi)
8538 {
8539 ATLASSERT(::IsWindow(m_hWnd));
8540 return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)lprbi);
8541 }
8542
8543 CImageList GetImageList() const
8544 {
8545 ATLASSERT(::IsWindow(m_hWnd));
8546 REBARINFO rbi = { 0 };
8547 rbi.cbSize = sizeof(REBARINFO);
8548 rbi.fMask = RBIM_IMAGELIST;
8549 BOOL bRet = (BOOL)::SendMessage(m_hWnd, RB_GETBARINFO, 0, (LPARAM)&rbi);
8550 return CImageList((bRet != FALSE) ? rbi.himl : NULL);
8551 }
8552
8553 BOOL SetImageList(HIMAGELIST hImageList)
8554 {
8555 ATLASSERT(::IsWindow(m_hWnd));
8556 REBARINFO rbi = { 0 };
8557 rbi.cbSize = sizeof(REBARINFO);
8558 rbi.fMask = RBIM_IMAGELIST;
8559 rbi.himl = hImageList;
8560 return (BOOL)::SendMessage(m_hWnd, RB_SETBARINFO, 0, (LPARAM)&rbi);
8561 }
8562
8563 UINT GetRowCount() const
8564 {
8565 ATLASSERT(::IsWindow(m_hWnd));
8566 return (UINT)::SendMessage(m_hWnd, RB_GETROWCOUNT, 0, 0L);
8567 }
8568
8569 UINT GetRowHeight(int nBand) const
8570 {
8571 ATLASSERT(::IsWindow(m_hWnd));
8572 return (UINT)::SendMessage(m_hWnd, RB_GETROWHEIGHT, nBand, 0L);
8573 }
8574
8575 #if (_WIN32_IE >= 0x0400)
8576 COLORREF GetTextColor() const
8577 {
8578 ATLASSERT(::IsWindow(m_hWnd));
8579 return (COLORREF)::SendMessage(m_hWnd, RB_GETTEXTCOLOR, 0, 0L);
8580 }
8581
8582 COLORREF SetTextColor(COLORREF clr)
8583 {
8584 ATLASSERT(::IsWindow(m_hWnd));
8585 return (COLORREF)::SendMessage(m_hWnd, RB_SETTEXTCOLOR, 0, (LPARAM)clr);
8586 }
8587
8588 COLORREF GetBkColor() const
8589 {
8590 ATLASSERT(::IsWindow(m_hWnd));
8591 return (COLORREF)::SendMessage(m_hWnd, RB_GETBKCOLOR, 0, 0L);
8592 }
8593
8594 COLORREF SetBkColor(COLORREF clr)
8595 {
8596 ATLASSERT(::IsWindow(m_hWnd));
8597 return (COLORREF)::SendMessage(m_hWnd, RB_SETBKCOLOR, 0, (LPARAM)clr);
8598 }
8599
8600 UINT GetBarHeight() const
8601 {
8602 ATLASSERT(::IsWindow(m_hWnd));
8603 return (UINT)::SendMessage(m_hWnd, RB_GETBARHEIGHT, 0, 0L);
8604 }
8605
8606 BOOL GetRect(int nBand, LPRECT lpRect) const
8607 {
8608 ATLASSERT(::IsWindow(m_hWnd));
8609 return (BOOL)::SendMessage(m_hWnd, RB_GETRECT, nBand, (LPARAM)lpRect);
8610 }
8611
8612 #ifndef _WIN32_WCE
8613 CToolTipCtrl GetToolTips() const
8614 {
8615 ATLASSERT(::IsWindow(m_hWnd));
8616 return CToolTipCtrl((HWND)::SendMessage(m_hWnd, RB_GETTOOLTIPS, 0, 0L));
8617 }
8618
8619 void SetToolTips(HWND hwndToolTip)
8620 {
8621 ATLASSERT(::IsWindow(m_hWnd));
8622 ::SendMessage(m_hWnd, RB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L);
8623 }
8624 #endif // !_WIN32_WCE
8625
8626 void GetBandBorders(int nBand, LPRECT lpRect) const
8627 {
8628 ATLASSERT(::IsWindow(m_hWnd));
8629 ATLASSERT(lpRect != NULL);
8630 ::SendMessage(m_hWnd, RB_GETBANDBORDERS, nBand, (LPARAM)lpRect);
8631 }
8632
8633 #ifndef _WIN32_WCE
8634 BOOL GetColorScheme(LPCOLORSCHEME lpColorScheme) const
8635 {
8636 ATLASSERT(::IsWindow(m_hWnd));
8637 ATLASSERT(lpColorScheme != NULL);
8638 return (BOOL)::SendMessage(m_hWnd, RB_GETCOLORSCHEME, 0, (LPARAM)lpColorScheme);
8639 }
8640
8641 void SetColorScheme(LPCOLORSCHEME lpColorScheme)
8642 {
8643 ATLASSERT(::IsWindow(m_hWnd));
8644 ATLASSERT(lpColorScheme != NULL);
8645 ::SendMessage(m_hWnd, RB_SETCOLORSCHEME, 0, (LPARAM)lpColorScheme);
8646 }
8647
8648 HPALETTE GetPalette() const
8649 {
8650 ATLASSERT(::IsWindow(m_hWnd));
8651 return (HPALETTE)::SendMessage(m_hWnd, RB_GETPALETTE, 0, 0L);
8652 }
8653
8654 HPALETTE SetPalette(HPALETTE hPalette)
8655 {
8656 ATLASSERT(::IsWindow(m_hWnd));
8657 return (HPALETTE)::SendMessage(m_hWnd, RB_SETPALETTE, 0, (LPARAM)hPalette);
8658 }
8659
8660 BOOL GetUnicodeFormat() const
8661 {
8662 ATLASSERT(::IsWindow(m_hWnd));
8663 return (BOOL)::SendMessage(m_hWnd, RB_GETUNICODEFORMAT, 0, 0L);
8664 }
8665
8666 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
8667 {
8668 ATLASSERT(::IsWindow(m_hWnd));
8669 return (BOOL)::SendMessage(m_hWnd, RB_SETUNICODEFORMAT, bUnicode, 0L);
8670 }
8671 #endif // !_WIN32_WCE
8672 #endif // (_WIN32_IE >= 0x0400)
8673
8674 #if (_WIN32_WINNT >= 0x0501)
8675 // requires uxtheme.h to be included to use MARGINS struct
8676 #ifndef _UXTHEME_H_
8677 typedef struct _MARGINS* PMARGINS;
8678 #endif // !_UXTHEME_H_
8679 void GetBandMargins(PMARGINS pMargins) const
8680 {
8681 ATLASSERT(::IsWindow(m_hWnd));
8682 ::SendMessage(m_hWnd, RB_GETBANDMARGINS, 0, (LPARAM)pMargins);
8683 }
8684
8685 void SetWindowTheme(LPCWSTR lpstrTheme)
8686 {
8687 ATLASSERT(::IsWindow(m_hWnd));
8688 ::SendMessage(m_hWnd, RB_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
8689 }
8690 #endif // (_WIN32_WINNT >= 0x0501)
8691
8692 #if (_WIN32_IE >= 0x0600)
8693 DWORD GetExtendedStyle() const
8694 {
8695 #ifndef RB_GETEXTENDEDSTYLE
8696 const UINT RB_GETEXTENDEDSTYLE = WM_USER + 42;
8697 #endif
8698 ATLASSERT(::IsWindow(m_hWnd));
8699 return (DWORD)::SendMessage(m_hWnd, RB_GETEXTENDEDSTYLE, 0, 0L);
8700 }
8701
8702 DWORD SetExtendedStyle(DWORD dwStyle, DWORD dwMask)
8703 {
8704 #ifndef RB_SETEXTENDEDSTYLE
8705 const UINT RB_SETEXTENDEDSTYLE = WM_USER + 41;
8706 #endif
8707 ATLASSERT(::IsWindow(m_hWnd));
8708 return (DWORD)::SendMessage(m_hWnd, RB_SETEXTENDEDSTYLE, dwMask, dwStyle);
8709 }
8710 #endif // (_WIN32_IE >= 0x0600)
8711
8712 // Operations
8713 BOOL InsertBand(int nBand, LPREBARBANDINFO lprbbi)
8714 {
8715 ATLASSERT(::IsWindow(m_hWnd));
8716 return (BOOL)::SendMessage(m_hWnd, RB_INSERTBAND, nBand, (LPARAM)lprbbi);
8717 }
8718
8719 BOOL AddBand(LPREBARBANDINFO lprbbi)
8720 {
8721 return InsertBand(-1, lprbbi);
8722 }
8723
8724 BOOL DeleteBand(int nBand)
8725 {
8726 ATLASSERT(::IsWindow(m_hWnd));
8727 return (BOOL)::SendMessage(m_hWnd, RB_DELETEBAND, nBand, 0L);
8728 }
8729
8730 ATL::CWindow SetNotifyWnd(HWND hWnd)
8731 {
8732 ATLASSERT(::IsWindow(m_hWnd));
8733 return ATL::CWindow((HWND)::SendMessage(m_hWnd, RB_SETPARENT, (WPARAM)hWnd, 0L));
8734 }
8735
8736 #if (_WIN32_IE >= 0x0400)
8737 void BeginDrag(int nBand, DWORD dwPos)
8738 {
8739 ATLASSERT(::IsWindow(m_hWnd));
8740 ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, dwPos);
8741 }
8742
8743 void BeginDrag(int nBand, int xPos, int yPos)
8744 {
8745 ATLASSERT(::IsWindow(m_hWnd));
8746 ::SendMessage(m_hWnd, RB_BEGINDRAG, nBand, MAKELPARAM(xPos, yPos));
8747 }
8748
8749 void EndDrag()
8750 {
8751 ATLASSERT(::IsWindow(m_hWnd));
8752 ::SendMessage(m_hWnd, RB_ENDDRAG, 0, 0L);
8753 }
8754
8755 void DragMove(DWORD dwPos)
8756 {
8757 ATLASSERT(::IsWindow(m_hWnd));
8758 ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, dwPos);
8759 }
8760
8761 void DragMove(int xPos, int yPos)
8762 {
8763 ATLASSERT(::IsWindow(m_hWnd));
8764 ::SendMessage(m_hWnd, RB_DRAGMOVE, 0, MAKELPARAM(xPos, yPos));
8765 }
8766
8767 #ifndef _WIN32_WCE
8768 void GetDropTarget(IDropTarget** ppDropTarget) const
8769 {
8770 ATLASSERT(::IsWindow(m_hWnd));
8771 ::SendMessage(m_hWnd, RB_GETDROPTARGET, 0, (LPARAM)ppDropTarget);
8772 }
8773 #endif // !_WIN32_WCE
8774
8775 void MaximizeBand(int nBand, BOOL bIdeal = FALSE)
8776 {
8777 ATLASSERT(::IsWindow(m_hWnd));
8778 ::SendMessage(m_hWnd, RB_MAXIMIZEBAND, nBand, bIdeal);
8779 }
8780
8781 void MinimizeBand(int nBand)
8782 {
8783 ATLASSERT(::IsWindow(m_hWnd));
8784 ::SendMessage(m_hWnd, RB_MINIMIZEBAND, nBand, 0L);
8785 }
8786
8787 BOOL SizeToRect(LPRECT lpRect)
8788 {
8789 ATLASSERT(::IsWindow(m_hWnd));
8790 return (BOOL)::SendMessage(m_hWnd, RB_SIZETORECT, 0, (LPARAM)lpRect);
8791 }
8792
8793 int IdToIndex(UINT uBandID) const
8794 {
8795 ATLASSERT(::IsWindow(m_hWnd));
8796 return (int)::SendMessage(m_hWnd, RB_IDTOINDEX, uBandID, 0L);
8797 }
8798
8799 int HitTest(LPRBHITTESTINFO lprbht) const
8800 {
8801 ATLASSERT(::IsWindow(m_hWnd));
8802 return (int)::SendMessage(m_hWnd, RB_HITTEST, 0, (LPARAM)lprbht);
8803 }
8804
8805 BOOL ShowBand(int nBand, BOOL bShow)
8806 {
8807 ATLASSERT(::IsWindow(m_hWnd));
8808 return (BOOL)::SendMessage(m_hWnd, RB_SHOWBAND, nBand, bShow);
8809 }
8810
8811 #ifndef _WIN32_WCE
8812 BOOL MoveBand(int nBand, int nNewPos)
8813 {
8814 ATLASSERT(::IsWindow(m_hWnd));
8815 ATLASSERT(nNewPos >= 0 && nNewPos <= ((int)GetBandCount() - 1));
8816 return (BOOL)::SendMessage(m_hWnd, RB_MOVEBAND, nBand, nNewPos);
8817 }
8818 #endif // !_WIN32_WCE
8819 #endif // (_WIN32_IE >= 0x0400)
8820
8821 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
8822 void PushChevron(int nBand, LPARAM lAppValue)
8823 {
8824 ATLASSERT(::IsWindow(m_hWnd));
8825 ::SendMessage(m_hWnd, RB_PUSHCHEVRON, nBand, lAppValue);
8826 }
8827 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
8828
8829 // Extra operations
8830 #if (_WIN32_IE >= 0x0400)
8831 void LockBands(bool bLock)
8832 {
8833 int nBandCount = GetBandCount();
8834 for(int i =0; i < nBandCount; i++)
8835 {
8836 REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
8837 rbbi.fMask = RBBIM_STYLE;
8838 BOOL bRet = GetBandInfo(i, &rbbi);
8839 ATLASSERT(bRet);
8840
8841 if((rbbi.fStyle & RBBS_GRIPPERALWAYS) == 0)
8842 {
8843 rbbi.fStyle |= RBBS_GRIPPERALWAYS;
8844 bRet = SetBandInfo(i, &rbbi);
8845 ATLASSERT(bRet);
8846 rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
8847 }
8848
8849 if(bLock)
8850 rbbi.fStyle |= RBBS_NOGRIPPER;
8851 else
8852 rbbi.fStyle &= ~RBBS_NOGRIPPER;
8853
8854 bRet = SetBandInfo(i, &rbbi);
8855 ATLASSERT(bRet);
8856 }
8857 }
8858 #endif // (_WIN32_IE >= 0x0400)
8859
8860 #if (_WIN32_WINNT >= 0x0600)
8861 BOOL SetBandWidth(int nBand, int cxWidth)
8862 {
8863 ATLASSERT(::IsWindow(m_hWnd));
8864 return (BOOL)::SendMessage(m_hWnd, RB_SETBANDWIDTH, nBand, cxWidth);
8865 }
8866 #endif // (_WIN32_WINNT >= 0x0600)
8867 };
8868
8869 typedef CReBarCtrlT<ATL::CWindow> CReBarCtrl;
8870
8871
8872 ///////////////////////////////////////////////////////////////////////////////
8873 // CComboBoxEx
8874
8875 #ifndef _WIN32_WCE
8876
8877 template <class TBase>
8878 class CComboBoxExT : public CComboBoxT< TBase >
8879 {
8880 public:
8881 // Constructors
8882 CComboBoxExT(HWND hWnd = NULL) : CComboBoxT< TBase >(hWnd)
8883 { }
8884
8885 CComboBoxExT< TBase >& operator =(HWND hWnd)
8886 {
8887 m_hWnd = hWnd;
8888 return *this;
8889 }
8890
8891 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
8892 DWORD dwStyle = 0, DWORD dwExStyle = 0,
8893 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
8894 {
8895 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
8896 }
8897
8898 // Attributes
8899 static LPCTSTR GetWndClassName()
8900 {
8901 return WC_COMBOBOXEX;
8902 }
8903
8904 CImageList GetImageList() const
8905 {
8906 ATLASSERT(::IsWindow(m_hWnd));
8907 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_GETIMAGELIST, 0, 0L));
8908 }
8909
8910 CImageList SetImageList(HIMAGELIST hImageList)
8911 {
8912 ATLASSERT(::IsWindow(m_hWnd));
8913 return CImageList((HIMAGELIST)::SendMessage(m_hWnd, CBEM_SETIMAGELIST, 0, (LPARAM)hImageList));
8914 }
8915
8916 #if (_WIN32_IE >= 0x0400)
8917 DWORD GetExtendedStyle() const
8918 {
8919 ATLASSERT(::IsWindow(m_hWnd));
8920 return (DWORD)::SendMessage(m_hWnd, CBEM_GETEXTENDEDSTYLE, 0, 0L);
8921 }
8922
8923 DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
8924 {
8925 ATLASSERT(::IsWindow(m_hWnd));
8926 return (DWORD)::SendMessage(m_hWnd, CBEM_SETEXTENDEDSTYLE, dwExMask, dwExStyle);
8927 }
8928
8929 BOOL GetUnicodeFormat() const
8930 {
8931 ATLASSERT(::IsWindow(m_hWnd));
8932 return (BOOL)::SendMessage(m_hWnd, CBEM_GETUNICODEFORMAT, 0, 0L);
8933 }
8934
8935 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
8936 {
8937 ATLASSERT(::IsWindow(m_hWnd));
8938 return (BOOL)::SendMessage(m_hWnd, CBEM_SETUNICODEFORMAT, bUnicode, 0L);
8939 }
8940 #endif // (_WIN32_IE >= 0x0400)
8941
8942 #if (_WIN32_WINNT >= 0x0501)
8943 void SetWindowTheme(LPCWSTR lpstrTheme)
8944 {
8945 ATLASSERT(::IsWindow(m_hWnd));
8946 ::SendMessage(m_hWnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme);
8947 }
8948 #endif // (_WIN32_WINNT >= 0x0501)
8949
8950 // Operations
8951 int InsertItem(const COMBOBOXEXITEM* lpcCBItem)
8952 {
8953 ATLASSERT(::IsWindow(m_hWnd));
8954 return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem);
8955 }
8956
8957 int InsertItem(UINT nMask, int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage,
8958 int iIndent, int iOverlay, LPARAM lParam)
8959 {
8960 ATLASSERT(::IsWindow(m_hWnd));
8961 COMBOBOXEXITEM cbex = { 0 };
8962 cbex.mask = nMask;
8963 cbex.iItem = nIndex;
8964 cbex.pszText = (LPTSTR) lpszItem;
8965 cbex.iImage = nImage;
8966 cbex.iSelectedImage = nSelImage;
8967 cbex.iIndent = iIndent;
8968 cbex.iOverlay = iOverlay;
8969 cbex.lParam = lParam;
8970 return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex);
8971 }
8972
8973 int InsertItem(int nIndex, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0)
8974 {
8975 ATLASSERT(::IsWindow(m_hWnd));
8976 COMBOBOXEXITEM cbex = { 0 };
8977 cbex.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_INDENT | CBEIF_LPARAM;
8978 cbex.iItem = nIndex;
8979 cbex.pszText = (LPTSTR) lpszItem;
8980 cbex.iImage = nImage;
8981 cbex.iSelectedImage = nSelImage;
8982 cbex.iIndent = iIndent;
8983 cbex.lParam = lParam;
8984 return (int)::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)&cbex);
8985 }
8986
8987 int AddItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, int iOverlay, LPARAM lParam)
8988 {
8989 return InsertItem(nMask, -1, lpszItem, nImage, nSelImage, iIndent, iOverlay, lParam);
8990 }
8991
8992 int AddItem(LPCTSTR lpszItem, int nImage, int nSelImage, int iIndent, LPARAM lParam = 0)
8993 {
8994 return InsertItem(-1, lpszItem, nImage, nSelImage, iIndent, lParam);
8995 }
8996
8997 int DeleteItem(int nIndex)
8998 {
8999 ATLASSERT(::IsWindow(m_hWnd));
9000 return (int)::SendMessage(m_hWnd, CBEM_DELETEITEM, nIndex, 0L);
9001 }
9002
9003 BOOL GetItem(PCOMBOBOXEXITEM pCBItem) const
9004 {
9005 ATLASSERT(::IsWindow(m_hWnd));
9006 return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)pCBItem);
9007 }
9008
9009 BOOL SetItem(const COMBOBOXEXITEM* lpcCBItem)
9010 {
9011 ATLASSERT(::IsWindow(m_hWnd));
9012 return (BOOL)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)lpcCBItem);
9013 }
9014
9015 int SetItem(int nIndex, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelImage,
9016 int iIndent, int iOverlay, LPARAM lParam)
9017 {
9018 ATLASSERT(::IsWindow(m_hWnd));
9019 COMBOBOXEXITEM cbex = { 0 };
9020 cbex.mask = nMask;
9021 cbex.iItem = nIndex;
9022 cbex.pszText = (LPTSTR) lpszItem;
9023 cbex.iImage = nImage;
9024 cbex.iSelectedImage = nSelImage;
9025 cbex.iIndent = iIndent;
9026 cbex.iOverlay = iOverlay;
9027 cbex.lParam = lParam;
9028 return (int)::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)&cbex);
9029 }
9030
9031 BOOL GetItemText(int nIndex, LPTSTR lpszItem, int nLen) const
9032 {
9033 ATLASSERT(::IsWindow(m_hWnd));
9034 ATLASSERT(lpszItem != NULL);
9035
9036 COMBOBOXEXITEM cbex = { 0 };
9037 cbex.mask = CBEIF_TEXT;
9038 cbex.iItem = nIndex;
9039 cbex.pszText = lpszItem;
9040 cbex.cchTextMax = nLen;
9041
9042 return (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
9043 }
9044
9045 #ifndef _ATL_NO_COM
9046 BOOL GetItemText(int nIndex, BSTR& bstrText) const
9047 {
9048 USES_CONVERSION;
9049 ATLASSERT(::IsWindow(m_hWnd));
9050 ATLASSERT(bstrText == NULL);
9051
9052 COMBOBOXEXITEM cbex = { 0 };
9053 cbex.mask = CBEIF_TEXT;
9054 cbex.iItem = nIndex;
9055
9056 LPTSTR lpstrText = NULL;
9057 BOOL bRet = FALSE;
9058 for(int nLen = 256; ; nLen *= 2)
9059 {
9060 ATLTRY(lpstrText = new TCHAR[nLen]);
9061 if(lpstrText == NULL)
9062 break;
9063 lpstrText[0] = NULL;
9064 cbex.pszText = lpstrText;
9065 cbex.cchTextMax = nLen;
9066 bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
9067 if(!bRet || (lstrlen(cbex.pszText) < nLen - 1))
9068 break;
9069 delete [] lpstrText;
9070 lpstrText = NULL;
9071 }
9072
9073 if(lpstrText != NULL)
9074 {
9075 if(bRet)
9076 bstrText = ::SysAllocString(T2OLE(lpstrText));
9077 delete [] lpstrText;
9078 }
9079
9080 return (bstrText != NULL) ? TRUE : FALSE;
9081 }
9082 #endif // !_ATL_NO_COM
9083
9084 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
9085 BOOL GetItemText(int nIndex, _CSTRING_NS::CString& strText) const
9086 {
9087 ATLASSERT(::IsWindow(m_hWnd));
9088
9089 COMBOBOXEXITEM cbex = { 0 };
9090 cbex.mask = CBEIF_TEXT;
9091 cbex.iItem = nIndex;
9092
9093 strText.Empty();
9094 BOOL bRet = FALSE;
9095 for(int nLen = 256; ; nLen *= 2)
9096 {
9097 cbex.pszText = strText.GetBufferSetLength(nLen);
9098 if(cbex.pszText == NULL)
9099 {
9100 bRet = FALSE;
9101 break;
9102 }
9103 cbex.cchTextMax = nLen;
9104 bRet = (BOOL)::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&cbex);
9105 if(!bRet || (lstrlen(cbex.pszText) < nLen - 1))
9106 break;
9107 }
9108 strText.ReleaseBuffer();
9109 return bRet;
9110 }
9111 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
9112
9113 BOOL SetItemText(int nIndex, LPCTSTR lpszItem)
9114 {
9115 ATLASSERT(::IsWindow(m_hWnd));
9116 return SetItem(nIndex, CBEIF_TEXT, lpszItem, 0, 0, 0, 0, 0);
9117 }
9118
9119 CComboBox GetComboCtrl() const
9120 {
9121 ATLASSERT(::IsWindow(m_hWnd));
9122 return CComboBox((HWND)::SendMessage(m_hWnd, CBEM_GETCOMBOCONTROL, 0, 0L));
9123 }
9124
9125 CEdit GetEditCtrl() const
9126 {
9127 ATLASSERT(::IsWindow(m_hWnd));
9128 return CEdit((HWND)::SendMessage(m_hWnd, CBEM_GETEDITCONTROL, 0, 0L));
9129 }
9130
9131 BOOL HasEditChanged() const
9132 {
9133 ATLASSERT(::IsWindow(m_hWnd));
9134 return (BOOL)::SendMessage(m_hWnd, CBEM_HASEDITCHANGED, 0, 0L);
9135 }
9136
9137 // Non-functional
9138 int AddString(LPCTSTR /*lpszItem*/)
9139 {
9140 ATLASSERT(FALSE); // Not available in CComboBoxEx; use InsertItem
9141 return 0;
9142 }
9143
9144 int InsertString(int /*nIndex*/, LPCTSTR /*lpszString*/)
9145 {
9146 ATLASSERT(FALSE); // Not available in CComboBoxEx; use InsertItem
9147 return 0;
9148 }
9149
9150 int Dir(UINT /*attr*/, LPCTSTR /*lpszWildCard*/)
9151 {
9152 ATLASSERT(FALSE); // Not available in CComboBoxEx
9153 return 0;
9154 }
9155
9156 int FindString(int /*nStartAfter*/, LPCTSTR /*lpszString*/) const
9157 {
9158 ATLASSERT(FALSE); // Not available in CComboBoxEx; try FindStringExact
9159 return 0;
9160 }
9161 };
9162
9163 typedef CComboBoxExT<ATL::CWindow> CComboBoxEx;
9164
9165 #endif // !_WIN32_WCE
9166
9167
9168 ///////////////////////////////////////////////////////////////////////////////
9169 // CMonthCalendarCtrl
9170
9171 template <class TBase>
9172 class CMonthCalendarCtrlT : public TBase
9173 {
9174 public:
9175 // Constructors
9176 CMonthCalendarCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9177 { }
9178
9179 CMonthCalendarCtrlT< TBase >& operator =(HWND hWnd)
9180 {
9181 m_hWnd = hWnd;
9182 return *this;
9183 }
9184
9185 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9186 DWORD dwStyle = 0, DWORD dwExStyle = 0,
9187 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9188 {
9189 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9190 }
9191
9192 // Attributes
9193 static LPCTSTR GetWndClassName()
9194 {
9195 return MONTHCAL_CLASS;
9196 }
9197
9198 COLORREF GetColor(int nColorType) const
9199 {
9200 ATLASSERT(::IsWindow(m_hWnd));
9201 return (COLORREF)::SendMessage(m_hWnd, MCM_GETCOLOR, nColorType, 0L);
9202 }
9203
9204 COLORREF SetColor(int nColorType, COLORREF clr)
9205 {
9206 ATLASSERT(::IsWindow(m_hWnd));
9207 return (COLORREF)::SendMessage(m_hWnd, MCM_SETCOLOR, nColorType, clr);
9208 }
9209
9210 BOOL GetCurSel(LPSYSTEMTIME lpSysTime) const
9211 {
9212 ATLASSERT(::IsWindow(m_hWnd));
9213 return (BOOL)::SendMessage(m_hWnd, MCM_GETCURSEL, 0, (LPARAM)lpSysTime);
9214 }
9215
9216 BOOL SetCurSel(LPSYSTEMTIME lpSysTime)
9217 {
9218 ATLASSERT(::IsWindow(m_hWnd));
9219 return (BOOL)::SendMessage(m_hWnd, MCM_SETCURSEL, 0, (LPARAM)lpSysTime);
9220 }
9221
9222 int GetFirstDayOfWeek(BOOL* pbLocaleVal = NULL) const
9223 {
9224 ATLASSERT(::IsWindow(m_hWnd));
9225 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_GETFIRSTDAYOFWEEK, 0, 0L);
9226 if(pbLocaleVal != NULL)
9227 *pbLocaleVal = (BOOL)HIWORD(dwRet);
9228 return (int)(short)LOWORD(dwRet);
9229 }
9230
9231 int SetFirstDayOfWeek(int nDay, BOOL* pbLocaleVal = NULL)
9232 {
9233 ATLASSERT(::IsWindow(m_hWnd));
9234 DWORD dwRet = (DWORD)::SendMessage(m_hWnd, MCM_SETFIRSTDAYOFWEEK, 0, nDay);
9235 if(pbLocaleVal != NULL)
9236 *pbLocaleVal = (BOOL)HIWORD(dwRet);
9237 return (int)(short)LOWORD(dwRet);
9238 }
9239
9240 int GetMaxSelCount() const
9241 {
9242 ATLASSERT(::IsWindow(m_hWnd));
9243 return (int)::SendMessage(m_hWnd, MCM_GETMAXSELCOUNT, 0, 0L);
9244 }
9245
9246 BOOL SetMaxSelCount(int nMax)
9247 {
9248 ATLASSERT(::IsWindow(m_hWnd));
9249 return (BOOL)::SendMessage(m_hWnd, MCM_SETMAXSELCOUNT, nMax, 0L);
9250 }
9251
9252 int GetMonthDelta() const
9253 {
9254 ATLASSERT(::IsWindow(m_hWnd));
9255 return (int)::SendMessage(m_hWnd, MCM_GETMONTHDELTA, 0, 0L);
9256 }
9257
9258 int SetMonthDelta(int nDelta)
9259 {
9260 ATLASSERT(::IsWindow(m_hWnd));
9261 return (int)::SendMessage(m_hWnd, MCM_SETMONTHDELTA, nDelta, 0L);
9262 }
9263
9264 DWORD GetRange(LPSYSTEMTIME lprgSysTimeArray) const
9265 {
9266 ATLASSERT(::IsWindow(m_hWnd));
9267 return (DWORD)::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM)lprgSysTimeArray);
9268 }
9269
9270 BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray)
9271 {
9272 ATLASSERT(::IsWindow(m_hWnd));
9273 return (BOOL)::SendMessage(m_hWnd, MCM_SETRANGE, dwFlags, (LPARAM)lprgSysTimeArray);
9274 }
9275
9276 BOOL GetSelRange(LPSYSTEMTIME lprgSysTimeArray) const
9277 {
9278 ATLASSERT(::IsWindow(m_hWnd));
9279 return (BOOL)::SendMessage(m_hWnd, MCM_GETSELRANGE, 0, (LPARAM)lprgSysTimeArray);
9280 }
9281
9282 BOOL SetSelRange(LPSYSTEMTIME lprgSysTimeArray)
9283 {
9284 ATLASSERT(::IsWindow(m_hWnd));
9285 return (BOOL)::SendMessage(m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)lprgSysTimeArray);
9286 }
9287
9288 BOOL GetToday(LPSYSTEMTIME lpSysTime) const
9289 {
9290 ATLASSERT(::IsWindow(m_hWnd));
9291 return (BOOL)::SendMessage(m_hWnd, MCM_GETTODAY, 0, (LPARAM)lpSysTime);
9292 }
9293
9294 void SetToday(LPSYSTEMTIME lpSysTime)
9295 {
9296 ATLASSERT(::IsWindow(m_hWnd));
9297 ::SendMessage(m_hWnd, MCM_SETTODAY, 0, (LPARAM)lpSysTime);
9298 }
9299
9300 BOOL GetMinReqRect(LPRECT lpRectInfo) const
9301 {
9302 ATLASSERT(::IsWindow(m_hWnd));
9303 return (BOOL)::SendMessage(m_hWnd, MCM_GETMINREQRECT, 0, (LPARAM)lpRectInfo);
9304 }
9305
9306 int GetMaxTodayWidth() const
9307 {
9308 ATLASSERT(::IsWindow(m_hWnd));
9309 return (int)::SendMessage(m_hWnd, MCM_GETMAXTODAYWIDTH, 0, 0L);
9310 }
9311
9312 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
9313 BOOL GetUnicodeFormat() const
9314 {
9315 ATLASSERT(::IsWindow(m_hWnd));
9316 return (BOOL)::SendMessage(m_hWnd, MCM_GETUNICODEFORMAT, 0, 0L);
9317 }
9318
9319 BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
9320 {
9321 ATLASSERT(::IsWindow(m_hWnd));
9322 return (BOOL)::SendMessage(m_hWnd, MCM_SETUNICODEFORMAT, bUnicode, 0L);
9323 }
9324 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
9325
9326 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9327 DWORD GetCurrentView() const
9328 {
9329 ATLASSERT(::IsWindow(m_hWnd));
9330 return (DWORD)::SendMessage(m_hWnd, MCM_GETCURRENTVIEW, 0, 0L);
9331 }
9332
9333 BOOL SetCurrentView(DWORD dwView)
9334 {
9335 ATLASSERT(::IsWindow(m_hWnd));
9336 return (BOOL)::SendMessage(m_hWnd, MCM_SETCURRENTVIEW, 0, dwView);
9337 }
9338
9339 DWORD GetCalendarCount() const
9340 {
9341 ATLASSERT(::IsWindow(m_hWnd));
9342 return (DWORD)::SendMessage(m_hWnd, MCM_GETCALENDARCOUNT, 0, 0L);
9343 }
9344
9345 BOOL GetCalendarGridInfo(PMCGRIDINFO pGridInfo) const
9346 {
9347 ATLASSERT(::IsWindow(m_hWnd));
9348 return (BOOL)::SendMessage(m_hWnd, MCM_GETCALENDARGRIDINFO, 0, (LPARAM)pGridInfo);
9349 }
9350
9351 CALID GetCALID() const
9352 {
9353 ATLASSERT(::IsWindow(m_hWnd));
9354 return (CALID)::SendMessage(m_hWnd, MCM_GETCALID, 0, 0L);
9355 }
9356
9357 void SetCALID(CALID calid)
9358 {
9359 ATLASSERT(::IsWindow(m_hWnd));
9360 ::SendMessage(m_hWnd, MCM_SETCALID, (LPARAM)calid, 0L);
9361 }
9362
9363 int GetCalendarBorder() const
9364 {
9365 ATLASSERT(::IsWindow(m_hWnd));
9366 return (int)::SendMessage(m_hWnd, MCM_GETCALENDARBORDER, 0, 0L);
9367 }
9368
9369 void SetCalendarBorder(int cxyBorder, BOOL bSet = TRUE)
9370 {
9371 ATLASSERT(::IsWindow(m_hWnd));
9372 ::SendMessage(m_hWnd, MCM_SETCALENDARBORDER, (WPARAM)bSet, (LPARAM)cxyBorder);
9373 }
9374 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9375
9376 // Operations
9377 int GetMonthRange(DWORD dwFlags, LPSYSTEMTIME lprgSysTimeArray) const
9378 {
9379 ATLASSERT(::IsWindow(m_hWnd));
9380 return (int)::SendMessage(m_hWnd, MCM_GETMONTHRANGE, dwFlags, (LPARAM)lprgSysTimeArray);
9381 }
9382
9383 BOOL SetDayState(int nMonths, LPMONTHDAYSTATE lpDayStateArray)
9384 {
9385 ATLASSERT(::IsWindow(m_hWnd));
9386 return (BOOL)::SendMessage(m_hWnd, MCM_SETDAYSTATE, nMonths, (LPARAM)lpDayStateArray);
9387 }
9388
9389 DWORD HitTest(PMCHITTESTINFO pMCHitTest) const
9390 {
9391 ATLASSERT(::IsWindow(m_hWnd));
9392 return (DWORD)::SendMessage(m_hWnd, MCM_HITTEST, 0, (LPARAM)pMCHitTest);
9393 }
9394
9395 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9396 void SizeRectToMin(LPRECT lpRect)
9397 {
9398 ATLASSERT(::IsWindow(m_hWnd));
9399 ::SendMessage(m_hWnd, MCM_SIZERECTTOMIN, 0, (LPARAM)lpRect);
9400 }
9401 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9402 };
9403
9404 typedef CMonthCalendarCtrlT<ATL::CWindow> CMonthCalendarCtrl;
9405
9406
9407 ///////////////////////////////////////////////////////////////////////////////
9408 // CDateTimePickerCtrl
9409
9410 template <class TBase>
9411 class CDateTimePickerCtrlT : public TBase
9412 {
9413 public:
9414 // Constructors
9415 CDateTimePickerCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9416 { }
9417
9418 CDateTimePickerCtrlT< TBase >& operator =(HWND hWnd)
9419 {
9420 m_hWnd = hWnd;
9421 return *this;
9422 }
9423
9424 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9425 DWORD dwStyle = 0, DWORD dwExStyle = 0,
9426 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9427 {
9428 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9429 }
9430
9431 // Operations
9432 static LPCTSTR GetWndClassName()
9433 {
9434 return DATETIMEPICK_CLASS;
9435 }
9436
9437 BOOL SetFormat(LPCTSTR lpszFormat)
9438 {
9439 ATLASSERT(::IsWindow(m_hWnd));
9440 return (BOOL)::SendMessage(m_hWnd, DTM_SETFORMAT, 0, (LPARAM)lpszFormat);
9441 }
9442
9443 COLORREF GetMonthCalColor(int nColorType) const
9444 {
9445 ATLASSERT(::IsWindow(m_hWnd));
9446 return (COLORREF)::SendMessage(m_hWnd, DTM_GETMCCOLOR, nColorType, 0L);
9447 }
9448
9449 COLORREF SetMonthCalColor(int nColorType, COLORREF clr)
9450 {
9451 ATLASSERT(::IsWindow(m_hWnd));
9452 return (COLORREF)::SendMessage(m_hWnd, DTM_SETMCCOLOR, nColorType, clr);
9453 }
9454
9455 DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const
9456 {
9457 ATLASSERT(::IsWindow(m_hWnd));
9458 return (DWORD)::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM)lpSysTimeArray);
9459 }
9460
9461 BOOL SetRange(DWORD dwFlags, LPSYSTEMTIME lpSysTimeArray)
9462 {
9463 ATLASSERT(::IsWindow(m_hWnd));
9464 return (BOOL)::SendMessage(m_hWnd, DTM_SETRANGE, dwFlags, (LPARAM)lpSysTimeArray);
9465 }
9466
9467 DWORD GetSystemTime(LPSYSTEMTIME lpSysTime) const
9468 {
9469 ATLASSERT(::IsWindow(m_hWnd));
9470 return (DWORD)::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)lpSysTime);
9471 }
9472
9473 BOOL SetSystemTime(DWORD dwFlags, LPSYSTEMTIME lpSysTime)
9474 {
9475 ATLASSERT(::IsWindow(m_hWnd));
9476 return (BOOL)::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, dwFlags, (LPARAM)lpSysTime);
9477 }
9478
9479 CMonthCalendarCtrl GetMonthCal() const
9480 {
9481 ATLASSERT(::IsWindow(m_hWnd));
9482 return CMonthCalendarCtrl((HWND)::SendMessage(m_hWnd, DTM_GETMONTHCAL, 0, 0L));
9483 }
9484
9485 #if (_WIN32_IE >= 0x0400)
9486 CFontHandle GetMonthCalFont() const
9487 {
9488 ATLASSERT(::IsWindow(m_hWnd));
9489 return CFontHandle((HFONT)::SendMessage(m_hWnd, DTM_GETMCFONT, 0, 0L));
9490 }
9491
9492 void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE)
9493 {
9494 ATLASSERT(::IsWindow(m_hWnd));
9495 ::SendMessage(m_hWnd, DTM_SETMCFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0));
9496 }
9497 #endif // (_WIN32_IE >= 0x0400)
9498
9499 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9500 DWORD GetMonthCalStyle() const
9501 {
9502 ATLASSERT(::IsWindow(m_hWnd));
9503 return (DWORD)::SendMessage(m_hWnd, DTM_GETMCSTYLE, 0, 0L);
9504 }
9505
9506 DWORD SetMonthCalStyle(DWORD dwStyle)
9507 {
9508 ATLASSERT(::IsWindow(m_hWnd));
9509 return (DWORD)::SendMessage(m_hWnd, DTM_SETMCSTYLE, 0, (LPARAM)dwStyle);
9510 }
9511
9512 void GetDateTimePickerInfo(LPDATETIMEPICKERINFO lpPickerInfo) const
9513 {
9514 ATLASSERT(::IsWindow(m_hWnd));
9515 ::SendMessage(m_hWnd, DTM_GETDATETIMEPICKERINFO, 0, (LPARAM)lpPickerInfo);
9516 }
9517
9518 BOOL GetIdealSize(LPSIZE lpSize) const
9519 {
9520 ATLASSERT(::IsWindow(m_hWnd));
9521 return (BOOL)::SendMessage(m_hWnd, DTM_GETIDEALSIZE, 0, (LPARAM)lpSize);
9522 }
9523
9524 void CloseMonthCal()
9525 {
9526 ATLASSERT(::IsWindow(m_hWnd));
9527 ::SendMessage(m_hWnd, DTM_CLOSEMONTHCAL, 0, 0L);
9528 }
9529 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
9530 };
9531
9532 typedef CDateTimePickerCtrlT<ATL::CWindow> CDateTimePickerCtrl;
9533
9534
9535 ///////////////////////////////////////////////////////////////////////////////
9536 // CFlatScrollBarImpl - support for flat scroll bars
9537
9538 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
9539
9540 template <class T>
9541 class CFlatScrollBarImpl
9542 {
9543 public:
9544 // Initialization
9545 BOOL FlatSB_Initialize()
9546 {
9547 T* pT = static_cast<T*>(this);
9548 ATLASSERT(::IsWindow(pT->m_hWnd));
9549 return ::InitializeFlatSB(pT->m_hWnd);
9550 }
9551
9552 HRESULT FlatSB_Uninitialize()
9553 {
9554 T* pT = static_cast<T*>(this);
9555 ATLASSERT(::IsWindow(pT->m_hWnd));
9556 return ::UninitializeFlatSB(pT->m_hWnd);
9557 }
9558
9559 // Flat scroll bar properties
9560 BOOL FlatSB_GetScrollProp(UINT uIndex, LPINT lpnValue) const
9561 {
9562 const T* pT = static_cast<const T*>(this);
9563 ATLASSERT(::IsWindow(pT->m_hWnd));
9564 return ::FlatSB_GetScrollProp(pT->m_hWnd, uIndex, lpnValue);
9565 }
9566
9567 BOOL FlatSB_SetScrollProp(UINT uIndex, int nValue, BOOL bRedraw = TRUE)
9568 {
9569 T* pT = static_cast<T*>(this);
9570 ATLASSERT(::IsWindow(pT->m_hWnd));
9571 return ::FlatSB_SetScrollProp(pT->m_hWnd, uIndex, nValue, bRedraw);
9572 }
9573
9574 // Attributes
9575 int FlatSB_GetScrollPos(int nBar) const
9576 {
9577 const T* pT = static_cast<const T*>(this);
9578 ATLASSERT(::IsWindow(pT->m_hWnd));
9579 return ::FlatSB_GetScrollPos(pT->m_hWnd, nBar);
9580 }
9581
9582 int FlatSB_SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
9583 {
9584 T* pT = static_cast<T*>(this);
9585 ATLASSERT(::IsWindow(pT->m_hWnd));
9586 return ::FlatSB_SetScrollPos(pT->m_hWnd, nBar, nPos, bRedraw);
9587 }
9588
9589 BOOL FlatSB_GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
9590 {
9591 const T* pT = static_cast<const T*>(this);
9592 ATLASSERT(::IsWindow(pT->m_hWnd));
9593 return ::FlatSB_GetScrollRange(pT->m_hWnd, nBar, lpMinPos, lpMaxPos);
9594 }
9595
9596 BOOL FlatSB_SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
9597 {
9598 T* pT = static_cast<T*>(this);
9599 ATLASSERT(::IsWindow(pT->m_hWnd));
9600 return ::FlatSB_SetScrollRange(pT->m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
9601 }
9602
9603 BOOL FlatSB_GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) const
9604 {
9605 const T* pT = static_cast<const T*>(this);
9606 ATLASSERT(::IsWindow(pT->m_hWnd));
9607 return ::FlatSB_GetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo);
9608 }
9609
9610 int FlatSB_SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
9611 {
9612 T* pT = static_cast<T*>(this);
9613 ATLASSERT(::IsWindow(pT->m_hWnd));
9614 return ::FlatSB_SetScrollInfo(pT->m_hWnd, nBar, lpScrollInfo, bRedraw);
9615 }
9616
9617 // Operations
9618 BOOL FlatSB_ShowScrollBar(UINT nBar, BOOL bShow = TRUE)
9619 {
9620 T* pT = static_cast<T*>(this);
9621 ATLASSERT(::IsWindow(pT->m_hWnd));
9622 return ::FlatSB_ShowScrollBar(pT->m_hWnd, nBar, bShow);
9623 }
9624
9625 BOOL FlatSB_EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH)
9626 {
9627 T* pT = static_cast<T*>(this);
9628 ATLASSERT(::IsWindow(pT->m_hWnd));
9629 return ::FlatSB_EnableScrollBar(pT->m_hWnd, uSBFlags, uArrowFlags);
9630 }
9631 };
9632
9633 template <class TBase>
9634 class CFlatScrollBarT : public TBase, public CFlatScrollBarImpl<CFlatScrollBarT< TBase > >
9635 {
9636 public:
9637 CFlatScrollBarT(HWND hWnd = NULL) : TBase(hWnd)
9638 { }
9639
9640 CFlatScrollBarT< TBase >& operator =(HWND hWnd)
9641 {
9642 m_hWnd = hWnd;
9643 return *this;
9644 }
9645 };
9646
9647 typedef CFlatScrollBarT<ATL::CWindow> CFlatScrollBar;
9648
9649 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
9650
9651
9652 ///////////////////////////////////////////////////////////////////////////////
9653 // CIPAddressCtrl
9654
9655 #if (_WIN32_IE >= 0x0400)
9656
9657 template <class TBase>
9658 class CIPAddressCtrlT : public TBase
9659 {
9660 public:
9661 // Constructors
9662 CIPAddressCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9663 { }
9664
9665 CIPAddressCtrlT< TBase >& operator =(HWND hWnd)
9666 {
9667 m_hWnd = hWnd;
9668 return *this;
9669 }
9670
9671 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9672 DWORD dwStyle = 0, DWORD dwExStyle = 0,
9673 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9674 {
9675 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9676 }
9677
9678 // Atteributes
9679 static LPCTSTR GetWndClassName()
9680 {
9681 return WC_IPADDRESS;
9682 }
9683
9684 BOOL IsBlank() const
9685 {
9686 ATLASSERT(::IsWindow(m_hWnd));
9687 return (BOOL)::SendMessage(m_hWnd, IPM_ISBLANK, 0, 0L);
9688 }
9689
9690 int GetAddress(LPDWORD lpdwAddress) const
9691 {
9692 ATLASSERT(::IsWindow(m_hWnd));
9693 return (int)::SendMessage(m_hWnd, IPM_GETADDRESS, 0, (LPARAM)lpdwAddress);
9694 }
9695
9696 void SetAddress(DWORD dwAddress)
9697 {
9698 ATLASSERT(::IsWindow(m_hWnd));
9699 ::SendMessage(m_hWnd, IPM_SETADDRESS, 0, dwAddress);
9700 }
9701
9702 void ClearAddress()
9703 {
9704 ATLASSERT(::IsWindow(m_hWnd));
9705 ::SendMessage(m_hWnd, IPM_CLEARADDRESS, 0, 0L);
9706 }
9707
9708 void SetRange(int nField, WORD wRange)
9709 {
9710 ATLASSERT(::IsWindow(m_hWnd));
9711 ::SendMessage(m_hWnd, IPM_SETRANGE, nField, wRange);
9712 }
9713
9714 void SetRange(int nField, BYTE nMin, BYTE nMax)
9715 {
9716 ATLASSERT(::IsWindow(m_hWnd));
9717 ::SendMessage(m_hWnd, IPM_SETRANGE, nField, MAKEIPRANGE(nMin, nMax));
9718 }
9719
9720 void SetFocus(int nField)
9721 {
9722 ATLASSERT(::IsWindow(m_hWnd));
9723 ::SendMessage(m_hWnd, IPM_SETFOCUS, nField, 0L);
9724 }
9725 };
9726
9727 typedef CIPAddressCtrlT<ATL::CWindow> CIPAddressCtrl;
9728
9729 #endif // (_WIN32_IE >= 0x0400)
9730
9731
9732 ///////////////////////////////////////////////////////////////////////////////
9733 // CPagerCtrl
9734
9735 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
9736
9737 template <class TBase>
9738 class CPagerCtrlT : public TBase
9739 {
9740 public:
9741 // Constructors
9742 CPagerCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9743 { }
9744
9745 CPagerCtrlT< TBase >& operator =(HWND hWnd)
9746 {
9747 m_hWnd = hWnd;
9748 return *this;
9749 }
9750
9751 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9752 DWORD dwStyle = 0, DWORD dwExStyle = 0,
9753 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9754 {
9755 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9756 }
9757
9758 // Attributes
9759 static LPCTSTR GetWndClassName()
9760 {
9761 return WC_PAGESCROLLER;
9762 }
9763
9764 int GetButtonSize() const
9765 {
9766 ATLASSERT(::IsWindow(m_hWnd));
9767 return (int)::SendMessage(m_hWnd, PGM_GETBUTTONSIZE, 0, 0L);
9768 }
9769
9770 int SetButtonSize(int nButtonSize)
9771 {
9772 ATLASSERT(::IsWindow(m_hWnd));
9773 return (int)::SendMessage(m_hWnd, PGM_SETBUTTONSIZE, 0, nButtonSize);
9774 }
9775
9776 DWORD GetButtonState(int nButton) const
9777 {
9778 ATLASSERT(::IsWindow(m_hWnd));
9779 ATLASSERT(nButton == PGB_TOPORLEFT || nButton == PGB_BOTTOMORRIGHT);
9780 return (DWORD)::SendMessage(m_hWnd, PGM_GETBUTTONSTATE, 0, nButton);
9781 }
9782
9783 COLORREF GetBkColor() const
9784 {
9785 ATLASSERT(::IsWindow(m_hWnd));
9786 return (COLORREF)::SendMessage(m_hWnd, PGM_GETBKCOLOR, 0, 0L);
9787 }
9788
9789 COLORREF SetBkColor(COLORREF clrBk)
9790 {
9791 ATLASSERT(::IsWindow(m_hWnd));
9792 return (COLORREF)::SendMessage(m_hWnd, PGM_SETBKCOLOR, 0, (LPARAM)clrBk);
9793 }
9794
9795 int GetBorder() const
9796 {
9797 ATLASSERT(::IsWindow(m_hWnd));
9798 return (int)::SendMessage(m_hWnd, PGM_GETBORDER, 0, 0L);
9799 }
9800
9801 int SetBorder(int nBorderSize)
9802 {
9803 ATLASSERT(::IsWindow(m_hWnd));
9804 return (int)::SendMessage(m_hWnd, PGM_SETBORDER, 0, nBorderSize);
9805 }
9806
9807 int GetPos() const
9808 {
9809 ATLASSERT(::IsWindow(m_hWnd));
9810 return (int)::SendMessage(m_hWnd, PGM_GETPOS, 0, 0L);
9811 }
9812
9813 int SetPos(int nPos)
9814 {
9815 ATLASSERT(::IsWindow(m_hWnd));
9816 return (int)::SendMessage(m_hWnd, PGM_SETPOS, 0, nPos);
9817 }
9818
9819 // Operations
9820 void SetChild(HWND hWndChild)
9821 {
9822 ATLASSERT(::IsWindow(m_hWnd));
9823 ::SendMessage(m_hWnd, PGM_SETCHILD, 0, (LPARAM)hWndChild);
9824 }
9825
9826 void ForwardMouse(BOOL bForward = TRUE)
9827 {
9828 ATLASSERT(::IsWindow(m_hWnd));
9829 ::SendMessage(m_hWnd, PGM_FORWARDMOUSE, bForward, 0L);
9830 }
9831
9832 void RecalcSize()
9833 {
9834 ATLASSERT(::IsWindow(m_hWnd));
9835 ::SendMessage(m_hWnd, PGM_RECALCSIZE, 0, 0L);
9836 }
9837
9838 void GetDropTarget(IDropTarget** ppDropTarget)
9839 {
9840 ATLASSERT(::IsWindow(m_hWnd));
9841 ATLASSERT(ppDropTarget != NULL);
9842 ::SendMessage(m_hWnd, PGM_GETDROPTARGET, 0, (LPARAM)ppDropTarget);
9843 }
9844 };
9845
9846 typedef CPagerCtrlT<ATL::CWindow> CPagerCtrl;
9847
9848 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
9849
9850
9851 ///////////////////////////////////////////////////////////////////////////////
9852 // CLinkCtrl - Windows SYSLINK control
9853
9854 #if (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)
9855
9856 template <class TBase>
9857 class CLinkCtrlT : public TBase
9858 {
9859 public:
9860 // Constructors
9861 CLinkCtrlT(HWND hWnd = NULL) : TBase(hWnd)
9862 { }
9863
9864 CLinkCtrlT< TBase >& operator =(HWND hWnd)
9865 {
9866 m_hWnd = hWnd;
9867 return *this;
9868 }
9869
9870 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
9871 DWORD dwStyle = 0, DWORD dwExStyle = 0,
9872 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
9873 {
9874 return TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
9875 }
9876
9877 // Attributes
9878 static LPCTSTR GetWndClassName()
9879 {
9880 #ifdef _UNICODE
9881 return WC_LINK;
9882 #else // !_UNICODE
9883 return "SysLink";
9884 #endif // !_UNICODE
9885 }
9886
9887 int GetIdealHeight(int cxMaxWidth = 0) const
9888 {
9889 ATLASSERT(::IsWindow(m_hWnd));
9890 return (int)::SendMessage(m_hWnd, LM_GETIDEALHEIGHT, cxMaxWidth, 0L);
9891 }
9892
9893 BOOL GetItem(PLITEM pLItem) const
9894 {
9895 ATLASSERT(::IsWindow(m_hWnd));
9896 return (BOOL)::SendMessage(m_hWnd, LM_GETITEM, 0, (LPARAM)pLItem);
9897 }
9898
9899 BOOL SetItem(PLITEM pLItem)
9900 {
9901 ATLASSERT(::IsWindow(m_hWnd));
9902 return (BOOL)::SendMessage(m_hWnd, LM_SETITEM, 0, (LPARAM)pLItem);
9903 }
9904
9905 // Vista only
9906 int GetIdealSize(SIZE& size, int cxMaxWidth = 0) const
9907 {
9908 #ifndef LM_GETIDEALSIZE
9909 const UINT LM_GETIDEALSIZE = LM_GETIDEALHEIGHT;
9910 #endif
9911 ATLASSERT(::IsWindow(m_hWnd));
9912 return (int)::SendMessage(m_hWnd, LM_GETIDEALSIZE, cxMaxWidth, (LPARAM)&size);
9913 }
9914
9915 // Operations
9916 BOOL HitTest(PLHITTESTINFO pLHitTestInfo) const
9917 {
9918 ATLASSERT(::IsWindow(m_hWnd));
9919 return (BOOL)::SendMessage(m_hWnd, LM_HITTEST, 0, (LPARAM)pLHitTestInfo);
9920 }
9921 };
9922
9923 typedef CLinkCtrlT<ATL::CWindow> CLinkCtrl;
9924
9925 #endif // (_WIN32_WINNT >= 0x0501) && !defined(_WIN32_WCE)
9926
9927
9928 ///////////////////////////////////////////////////////////////////////////////
9929 // CCustomDraw - MI class for custom-draw support
9930
9931 template <class T>
9932 class CCustomDraw
9933 {
9934 public:
9935 #if (_ATL_VER < 0x0700)
9936 BOOL m_bHandledCD;
9937
9938 BOOL IsMsgHandled() const
9939 {
9940 return m_bHandledCD;
9941 }
9942
9943 void SetMsgHandled(BOOL bHandled)
9944 {
9945 m_bHandledCD = bHandled;
9946 }
9947 #endif // !(_ATL_VER < 0x0700)
9948
9949 // Message map and handlers
9950 BEGIN_MSG_MAP(CCustomDraw< T >)
9951 NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
9952 ALT_MSG_MAP(1)
9953 REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
9954 END_MSG_MAP()
9955
9956 // message handler
9957 LRESULT OnCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
9958 {
9959 T* pT = static_cast<T*>(this);
9960 pT->SetMsgHandled(TRUE);
9961 LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)pnmh;
9962 DWORD dwRet = 0;
9963 switch(lpNMCustomDraw->dwDrawStage)
9964 {
9965 case CDDS_PREPAINT:
9966 dwRet = pT->OnPrePaint(idCtrl, lpNMCustomDraw);
9967 break;
9968 case CDDS_POSTPAINT:
9969 dwRet = pT->OnPostPaint(idCtrl, lpNMCustomDraw);
9970 break;
9971 case CDDS_PREERASE:
9972 dwRet = pT->OnPreErase(idCtrl, lpNMCustomDraw);
9973 break;
9974 case CDDS_POSTERASE:
9975 dwRet = pT->OnPostErase(idCtrl, lpNMCustomDraw);
9976 break;
9977 case CDDS_ITEMPREPAINT:
9978 dwRet = pT->OnItemPrePaint(idCtrl, lpNMCustomDraw);
9979 break;
9980 case CDDS_ITEMPOSTPAINT:
9981 dwRet = pT->OnItemPostPaint(idCtrl, lpNMCustomDraw);
9982 break;
9983 case CDDS_ITEMPREERASE:
9984 dwRet = pT->OnItemPreErase(idCtrl, lpNMCustomDraw);
9985 break;
9986 case CDDS_ITEMPOSTERASE:
9987 dwRet = pT->OnItemPostErase(idCtrl, lpNMCustomDraw);
9988 break;
9989 #if (_WIN32_IE >= 0x0400)
9990 case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
9991 dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw);
9992 break;
9993 #endif // (_WIN32_IE >= 0x0400)
9994 default:
9995 pT->SetMsgHandled(FALSE);
9996 break;
9997 }
9998 bHandled = pT->IsMsgHandled();
9999 return dwRet;
10000 }
10001
10002 // Overrideables
10003 DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10004 {
10005 return CDRF_DODEFAULT;
10006 }
10007
10008 DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10009 {
10010 return CDRF_DODEFAULT;
10011 }
10012
10013 DWORD OnPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10014 {
10015 return CDRF_DODEFAULT;
10016 }
10017
10018 DWORD OnPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10019 {
10020 return CDRF_DODEFAULT;
10021 }
10022
10023 DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10024 {
10025 return CDRF_DODEFAULT;
10026 }
10027
10028 DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10029 {
10030 return CDRF_DODEFAULT;
10031 }
10032
10033 DWORD OnItemPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10034 {
10035 return CDRF_DODEFAULT;
10036 }
10037
10038 DWORD OnItemPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10039 {
10040 return CDRF_DODEFAULT;
10041 }
10042
10043 #if (_WIN32_IE >= 0x0400)
10044 DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
10045 {
10046 return CDRF_DODEFAULT;
10047 }
10048 #endif // (_WIN32_IE >= 0x0400)
10049 };
10050
10051
10052 // --- Windows CE common controls ---
10053
10054 #ifdef _WIN32_WCE
10055
10056 ///////////////////////////////////////////////////////////////////////////////
10057 // CCECommandBarCtrl
10058
10059 template <class TBase>
10060 class CCECommandBarCtrlT : public TBase
10061 {
10062 public:
10063 // Constructors
10064 CCECommandBarCtrlT(HWND hWnd = NULL) : TBase(hWnd) { }
10065
10066 CCECommandBarCtrlT< TBase >& operator=(HWND hWnd)
10067 {
10068 m_hWnd = hWnd;
10069 return *this;
10070 }
10071
10072 // Attributes
10073 BOOL IsVisible() const
10074 {
10075 return IsWindowVisible();
10076 }
10077
10078 int GetHeight() const
10079 {
10080 ATLASSERT(::IsWindow(m_hWnd));
10081 return ::CommandBar_Height(m_hWnd);
10082 }
10083
10084 HMENU GetMenu(WORD wButton) const
10085 {
10086 ATLASSERT(::IsWindow(m_hWnd));
10087 return ::CommandBar_GetMenu(m_hWnd, wButton);
10088 }
10089
10090 // Operations
10091 HWND Create(HWND hWndParent, int nCmdBarID)
10092 {
10093 m_hWnd = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), hWndParent, nCmdBarID);
10094 ATLASSERT(::IsWindow(m_hWnd));
10095 return m_hWnd;
10096 }
10097
10098 void Destroy()
10099 {
10100 DestroyWindow();
10101 }
10102
10103 BOOL Show(BOOL bShow = TRUE)
10104 {
10105 ATLASSERT(::IsWindow(m_hWnd));
10106 return ::CommandBar_Show(m_hWnd, bShow);
10107 }
10108
10109 BOOL DrawMenuBar(WORD wButton)
10110 {
10111 ATLASSERT(::IsWindow(m_hWnd));
10112 return ::CommandBar_DrawMenuBar(m_hWnd, wButton);
10113 }
10114
10115 BOOL AddAdornments(DWORD dwFlags = 0)
10116 {
10117 ATLASSERT(::IsWindow(m_hWnd));
10118 return ::CommandBar_AddAdornments(m_hWnd, dwFlags, 0);
10119 }
10120
10121 int AddBitmap(int nBitmapID, int nNumImages)
10122 {
10123 ATLASSERT(::IsWindow(m_hWnd));
10124 return ::CommandBar_AddBitmap(m_hWnd, ModuleHelper::GetResourceInstance(), nBitmapID, nNumImages, 16, 16);
10125 }
10126
10127 BOOL AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons)
10128 {
10129 ATLASSERT(::IsWindow(m_hWnd));
10130 return CommandBar_AddButtons(m_hWnd, uNumButtons, lpButtons);
10131 }
10132
10133 BOOL AddToolTips(UINT uNumToolTips, LPTSTR lpToolTips)
10134 {
10135 ATLASSERT(::IsWindow(m_hWnd));
10136 return CommandBar_AddToolTips(m_hWnd, uNumToolTips, lpToolTips);
10137 }
10138
10139 BOOL InsertButton(int nButton, LPTBBUTTON lpButton)
10140 {
10141 ATLASSERT(::IsWindow(m_hWnd));
10142 return CommandBar_InsertButton(m_hWnd, nButton, lpButton);
10143 }
10144
10145 HWND InsertComboBox(int nWidth, UINT dwStyle, WORD wComboBoxID, WORD wButton)
10146 {
10147 ATLASSERT(::IsWindow(m_hWnd));
10148 return ::CommandBar_InsertComboBox(m_hWnd, ModuleHelper::GetModuleInstance(), nWidth, dwStyle, wComboBoxID, wButton);
10149 }
10150
10151 BOOL InsertMenubar(WORD wMenuID, WORD wButton)
10152 {
10153 ATLASSERT(::IsWindow(m_hWnd));
10154 return ::CommandBar_InsertMenubar(m_hWnd, ModuleHelper::GetResourceInstance(), wMenuID, wButton);
10155 }
10156
10157 BOOL InsertMenubarEx(ATL::_U_STRINGorID menu, WORD wButton)
10158 {
10159 ATLASSERT(::IsWindow(m_hWnd));
10160 return ::CommandBar_InsertMenubarEx(m_hWnd, ModuleHelper::GetResourceInstance(), (LPTSTR)menu.m_lpstr, wButton);
10161 }
10162
10163 BOOL IsCommandBarMessage(LPMSG lpMsg)
10164 {
10165 ATLASSERT(::IsWindow(m_hWnd));
10166 return ::IsCommandBarMessage(m_hWnd, lpMsg);
10167 }
10168 };
10169
10170 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC MenuBar
10171 typedef CCECommandBarCtrlT<CToolBarCtrl> CMenuBarCtrl;
10172 #else
10173 typedef CCECommandBarCtrlT<CToolBarCtrl> CCECommandBarCtrl;
10174 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
10175
10176 ///////////////////////////////////////////////////////////////////////////////
10177 // CCECommandBandsCtrl
10178
10179 template <class TBase>
10180 class CCECommandBandsCtrlT : public TBase
10181 {
10182 public:
10183 // Constructors
10184 CCECommandBandsCtrlT(HWND hWnd = NULL) : TBase(hWnd) { }
10185
10186 CCECommandBandsCtrlT< TBase >& operator=(HWND hWnd)
10187 {
10188 m_hWnd = hWnd;
10189 return *this;
10190 }
10191
10192 // Attributes
10193 BOOL IsVisible() const
10194 {
10195 return IsWindowVisible();
10196 }
10197
10198 #if (_WIN32_IE >= 0x0400)
10199 UINT GetHeight() const
10200 {
10201 ATLASSERT(::IsWindow(m_hWnd));
10202 return CommandBands_Height(m_hWnd);
10203 }
10204 #endif // (_WIN32_IE >= 0x0400)
10205
10206 HWND GetCommandBar(UINT uBand) const
10207 {
10208 ATLASSERT(::IsWindow(m_hWnd));
10209 return ::CommandBands_GetCommandBar(m_hWnd, uBand);
10210 }
10211
10212 BOOL GetRestoreInformation(UINT uBand, LPCOMMANDBANDSRESTOREINFO pcbr) const
10213 {
10214 ATLASSERT(::IsWindow(m_hWnd));
10215 return ::CommandBands_GetRestoreInformation(m_hWnd, uBand, pcbr);
10216 }
10217
10218 // Operations
10219 HWND Create(HWND hWndParent, UINT wID, DWORD dwStyles, HIMAGELIST hImageList = NULL)
10220 {
10221 m_hWnd = ::CommandBands_Create(ModuleHelper::GetModuleInstance(), hWndParent, wID, dwStyles, hImageList);
10222 ATLASSERT(::IsWindow(m_hWnd));
10223 return m_hWnd;
10224 }
10225
10226 BOOL AddAdornments(DWORD dwFlags = 0, LPREBARBANDINFO prbbi = NULL)
10227 {
10228 ATLASSERT(::IsWindow(m_hWnd));
10229 return ::CommandBands_AddAdornments(m_hWnd, ModuleHelper::GetModuleInstance(), dwFlags, prbbi);
10230 }
10231
10232 BOOL AddBands(UINT uBandCount, LPREBARBANDINFO prbbi)
10233 {
10234 ATLASSERT(::IsWindow(m_hWnd));
10235 return ::CommandBands_AddBands(m_hWnd, ModuleHelper::GetModuleInstance(), uBandCount, prbbi);
10236 }
10237
10238 BOOL Show(BOOL bShow = TRUE)
10239 {
10240 ATLASSERT(::IsWindow(m_hWnd));
10241 return ::CommandBands_Show(m_hWnd, bShow);
10242 }
10243 };
10244
10245 typedef CCECommandBandsCtrlT<ATL::CWindow> CCECommandBandsCtrl;
10246
10247 #endif // _WIN32_WCE
10248
10249 }; // namespace WTL
10250
10251 #endif // __ATLCTRLS_H__
+0
-4211
src/third_party/wtl/Include/atlctrlw.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLCTRLW_H__
9 #define __ATLCTRLW_H__
10
11 #pragma once
12
13 #ifdef _WIN32_WCE
14 #error atlctrlw.h is not supported on Windows CE
15 #endif
16
17 #ifndef __ATLAPP_H__
18 #error atlctrlw.h requires atlapp.h to be included first
19 #endif
20
21 #ifndef __ATLCTRLS_H__
22 #error atlctrlw.h requires atlctrls.h to be included first
23 #endif
24
25 #if (_WIN32_IE < 0x0400)
26 #error atlctrlw.h requires _WIN32_IE >= 0x0400
27 #endif
28
29 // Define _WTL_CMDBAR_VISTA_MENUS as 0 to exclude Vista menus support
30 #if !defined(_WTL_CMDBAR_VISTA_MENUS) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
31 #define _WTL_CMDBAR_VISTA_MENUS 1
32 #endif
33
34 #if _WTL_CMDBAR_VISTA_MENUS
35 #if !((_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501))
36 #error _WTL_CMDBAR_VISTA_MENUS requires (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
37 #endif
38 #endif
39
40 // Note: Define _WTL_CMDBAR_VISTA_STD_MENUBAR to use Vista standard menubar look with Vista menus
41
42
43 ///////////////////////////////////////////////////////////////////////////////
44 // Classes in this file:
45 //
46 // CCommandBarCtrlImpl<T, TBase, TWinTraits>
47 // CCommandBarCtrl
48 // CMDICommandBarCtrlImpl<T, TBase, TWinTraits>
49 // CMDICommandBarCtrl
50
51
52 namespace WTL
53 {
54
55 ///////////////////////////////////////////////////////////////////////////////
56 // Command Bars
57
58 // Window Styles:
59 #define CBRWS_TOP CCS_TOP
60 #define CBRWS_BOTTOM CCS_BOTTOM
61 #define CBRWS_NORESIZE CCS_NORESIZE
62 #define CBRWS_NOPARENTALIGN CCS_NOPARENTALIGN
63 #define CBRWS_NODIVIDER CCS_NODIVIDER
64
65 // Extended styles
66 #define CBR_EX_TRANSPARENT 0x00000001L
67 #define CBR_EX_SHAREMENU 0x00000002L
68 #define CBR_EX_ALTFOCUSMODE 0x00000004L
69 #define CBR_EX_TRACKALWAYS 0x00000008L
70 #define CBR_EX_NOVISTAMENUS 0x00000010L
71
72 // standard command bar styles
73 #define ATL_SIMPLE_CMDBAR_PANE_STYLE \
74 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBRWS_NODIVIDER | CBRWS_NORESIZE | CBRWS_NOPARENTALIGN)
75
76 // Messages - support chevrons for frame windows
77 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND
78 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu
79 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu
80
81 typedef struct tagCBRPOPUPMENU
82 {
83 int cbSize;
84 HMENU hMenu; // popup menu do display
85 UINT uFlags; // TPM_* flags for ::TrackPopupMenuEx
86 int x;
87 int y;
88 LPTPMPARAMS lptpm; // ptr to TPMPARAMS for ::TrackPopupMenuEx
89 } CBRPOPUPMENU, *LPCBRPOPUPMENU;
90
91 // helper class
92 template <class T>
93 class CSimpleStack : public ATL::CSimpleArray< T >
94 {
95 public:
96 BOOL Push(T t)
97 {
98 #ifdef _CMDBAR_EXTRA_TRACE
99 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-PUSH (%8.8X) size = %i\n"), t, GetSize());
100 #endif
101 return Add(t);
102 }
103
104 T Pop()
105 {
106 int nLast = GetSize() - 1;
107 if(nLast < 0)
108 return NULL; // must be able to convert to NULL
109 T t = m_aT[nLast];
110 #ifdef _CMDBAR_EXTRA_TRACE
111 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-POP (%8.8X) size = %i\n"), t, GetSize());
112 #endif
113 if(!RemoveAt(nLast))
114 return NULL;
115 return t;
116 }
117
118 T GetCurrent()
119 {
120 int nLast = GetSize() - 1;
121 if(nLast < 0)
122 return NULL; // must be able to convert to NULL
123 return m_aT[nLast];
124 }
125 };
126
127
128 ///////////////////////////////////////////////////////////////////////////////
129 // CCommandBarCtrlBase - base class for the Command Bar implementation
130
131 class CCommandBarCtrlBase : public CToolBarCtrl
132 {
133 public:
134 struct _MsgHookData
135 {
136 HHOOK hMsgHook;
137 DWORD dwUsage;
138
139 _MsgHookData() : hMsgHook(NULL), dwUsage(0)
140 { }
141 };
142
143 typedef ATL::CSimpleMap<DWORD, _MsgHookData*> CMsgHookMap;
144 static CMsgHookMap* s_pmapMsgHook;
145
146 static HHOOK s_hCreateHook;
147 static bool s_bW2K; // For animation flag
148 static CCommandBarCtrlBase* s_pCurrentBar;
149 static bool s_bStaticInit;
150
151 CSimpleStack<HWND> m_stackMenuWnd;
152 CSimpleStack<HMENU> m_stackMenuHandle;
153
154 HWND m_hWndHook;
155 DWORD m_dwMagic;
156
157
158 CCommandBarCtrlBase() : m_hWndHook(NULL), m_dwMagic(1314)
159 {
160 // init static variables
161 if(!s_bStaticInit)
162 {
163 CStaticDataInitCriticalSectionLock lock;
164 if(FAILED(lock.Lock()))
165 {
166 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlBase::CCommandBarCtrlBase.\n"));
167 ATLASSERT(FALSE);
168 return;
169 }
170
171 if(!s_bStaticInit)
172 {
173 // Just in case...
174 AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
175 // Animation on Win2000 only
176 s_bW2K = !AtlIsOldWindows();
177 // done
178 s_bStaticInit = true;
179 }
180
181 lock.Unlock();
182 }
183 }
184
185 bool IsCommandBarBase() const { return m_dwMagic == 1314; }
186 };
187
188 __declspec(selectany) CCommandBarCtrlBase::CMsgHookMap* CCommandBarCtrlBase::s_pmapMsgHook = NULL;
189 __declspec(selectany) HHOOK CCommandBarCtrlBase::s_hCreateHook = NULL;
190 __declspec(selectany) CCommandBarCtrlBase* CCommandBarCtrlBase::s_pCurrentBar = NULL;
191 __declspec(selectany) bool CCommandBarCtrlBase::s_bW2K = false;
192 __declspec(selectany) bool CCommandBarCtrlBase::s_bStaticInit = false;
193
194
195 ///////////////////////////////////////////////////////////////////////////////
196 // CCommandBarCtrl - ATL implementation of Command Bars
197
198 template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = ATL::CControlWinTraits>
199 class ATL_NO_VTABLE CCommandBarCtrlImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
200 {
201 public:
202 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
203
204 // Declarations
205 struct _MenuItemData // menu item data
206 {
207 DWORD dwMagic;
208 LPTSTR lpstrText;
209 UINT fType;
210 UINT fState;
211 int iButton;
212
213 _MenuItemData() { dwMagic = 0x1313; }
214 bool IsCmdBarMenuItem() { return (dwMagic == 0x1313); }
215 };
216
217 struct _ToolBarData // toolbar resource data
218 {
219 WORD wVersion;
220 WORD wWidth;
221 WORD wHeight;
222 WORD wItemCount;
223 //WORD aItems[wItemCount]
224
225 WORD* items()
226 { return (WORD*)(this+1); }
227 };
228
229 // Constants
230 enum _CmdBarDrawConstants
231 {
232 s_kcxGap = 1,
233 s_kcxTextMargin = 2,
234 s_kcxButtonMargin = 3,
235 s_kcyButtonMargin = 3
236 };
237
238 enum
239 {
240 _nMaxMenuItemTextLength = 100,
241 _chChevronShortcut = _T('/')
242 };
243
244 #ifndef DT_HIDEPREFIX
245 enum { DT_HIDEPREFIX = 0x00100000 };
246 #endif // !DT_HIDEPREFIX
247
248 // Data members
249 HMENU m_hMenu;
250 HIMAGELIST m_hImageList;
251 ATL::CSimpleValArray<WORD> m_arrCommand;
252
253 DWORD m_dwExtendedStyle; // Command Bar specific extended styles
254
255 ATL::CContainedWindow m_wndParent;
256
257 bool m_bMenuActive:1;
258 bool m_bAttachedMenu:1;
259 bool m_bImagesVisible:1;
260 bool m_bPopupItem:1;
261 bool m_bContextMenu:1;
262 bool m_bEscapePressed:1;
263 bool m_bSkipMsg:1;
264 bool m_bParentActive:1;
265 bool m_bFlatMenus:1;
266 bool m_bUseKeyboardCues:1;
267 bool m_bShowKeyboardCues:1;
268 bool m_bAllowKeyboardCues:1;
269 bool m_bKeyboardInput:1;
270 bool m_bAlphaImages:1;
271 bool m_bLayoutRTL:1;
272 bool m_bSkipPostDown:1;
273 bool m_bVistaMenus:1;
274
275 int m_nPopBtn;
276 int m_nNextPopBtn;
277
278 SIZE m_szBitmap;
279 SIZE m_szButton;
280
281 COLORREF m_clrMask;
282 CFont m_fontMenu; // used internally, only to measure text
283
284 UINT m_uSysKey;
285
286 HWND m_hWndFocus; // Alternate focus mode
287
288 int m_cxExtraSpacing;
289
290 #if _WTL_CMDBAR_VISTA_MENUS
291 ATL::CSimpleValArray<HBITMAP> m_arrVistaBitmap; // Bitmaps for Vista menus
292 #endif // _WTL_CMDBAR_VISTA_MENUS
293
294 // Constructor/destructor
295 CCommandBarCtrlImpl() :
296 m_hMenu(NULL),
297 m_hImageList(NULL),
298 m_wndParent(this, 1),
299 m_bMenuActive(false),
300 m_bAttachedMenu(false),
301 m_nPopBtn(-1),
302 m_nNextPopBtn(-1),
303 m_bPopupItem(false),
304 m_bImagesVisible(true),
305 m_bSkipMsg(false),
306 m_uSysKey(0),
307 m_hWndFocus(NULL),
308 m_bContextMenu(false),
309 m_bEscapePressed(false),
310 m_clrMask(RGB(192, 192, 192)),
311 m_dwExtendedStyle(CBR_EX_TRANSPARENT | CBR_EX_SHAREMENU | CBR_EX_TRACKALWAYS),
312 m_bParentActive(true),
313 m_bFlatMenus(false),
314 m_bUseKeyboardCues(false),
315 m_bShowKeyboardCues(false),
316 m_bAllowKeyboardCues(true),
317 m_bKeyboardInput(false),
318 m_cxExtraSpacing(0),
319 m_bAlphaImages(false),
320 m_bLayoutRTL(false),
321 m_bSkipPostDown(false),
322 m_bVistaMenus(false)
323 {
324 SetImageSize(16, 15); // default
325 }
326
327 ~CCommandBarCtrlImpl()
328 {
329 if(m_wndParent.IsWindow())
330 /*scary!*/ m_wndParent.UnsubclassWindow();
331
332 if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0)
333 ::DestroyMenu(m_hMenu);
334
335 if(m_hImageList != NULL)
336 ::ImageList_Destroy(m_hImageList);
337 }
338
339 // Attributes
340 DWORD GetCommandBarExtendedStyle() const
341 {
342 return m_dwExtendedStyle;
343 }
344
345 DWORD SetCommandBarExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
346 {
347 DWORD dwPrevStyle = m_dwExtendedStyle;
348 if(dwMask == 0)
349 m_dwExtendedStyle = dwExtendedStyle;
350 else
351 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
352 return dwPrevStyle;
353 }
354
355 CMenuHandle GetMenu() const
356 {
357 ATLASSERT(::IsWindow(m_hWnd));
358 return m_hMenu;
359 }
360
361 COLORREF GetImageMaskColor() const
362 {
363 return m_clrMask;
364 }
365
366 COLORREF SetImageMaskColor(COLORREF clrMask)
367 {
368 COLORREF clrOld = m_clrMask;
369 m_clrMask = clrMask;
370 return clrOld;
371 }
372
373 bool GetImagesVisible() const
374 {
375 return m_bImagesVisible;
376 }
377
378 bool SetImagesVisible(bool bVisible)
379 {
380 bool bOld = m_bImagesVisible;
381 m_bImagesVisible = bVisible;
382 return bOld;
383 }
384
385 void GetImageSize(SIZE& size) const
386 {
387 size = m_szBitmap;
388 }
389
390 bool SetImageSize(SIZE& size)
391 {
392 return SetImageSize(size.cx, size.cy);
393 }
394
395 bool SetImageSize(int cx, int cy)
396 {
397 if(m_hImageList != NULL)
398 {
399 if(::ImageList_GetImageCount(m_hImageList) == 0) // empty
400 {
401 ::ImageList_Destroy(m_hImageList);
402 m_hImageList = NULL;
403 }
404 else
405 {
406 return false; // can't set, image list exists
407 }
408 }
409
410 if(cx == 0 || cy == 0)
411 return false;
412
413 m_szBitmap.cx = cx;
414 m_szBitmap.cy = cy;
415 m_szButton.cx = m_szBitmap.cx + 2 * s_kcxButtonMargin;
416 m_szButton.cy = m_szBitmap.cy + 2 * s_kcyButtonMargin;
417
418 return true;
419 }
420
421 bool GetAlphaImages() const
422 {
423 return m_bAlphaImages;
424 }
425
426 bool SetAlphaImages(bool bAlphaImages)
427 {
428 if(m_hImageList != NULL)
429 {
430 if(::ImageList_GetImageCount(m_hImageList) == 0) // empty
431 {
432 ::ImageList_Destroy(m_hImageList);
433 m_hImageList = NULL;
434 }
435 else
436 {
437 return false; // can't set, image list exists
438 }
439 }
440
441 m_bAlphaImages = bAlphaImages;
442 return true;
443 }
444
445 HWND GetCmdBar() const
446 {
447 ATLASSERT(::IsWindow(m_hWnd));
448 return (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
449 }
450
451 // Methods
452 HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
453 DWORD dwStyle = 0, DWORD dwExStyle = 0,
454 UINT nID = 0, LPVOID lpCreateParam = NULL)
455 {
456 // These styles are required for command bars
457 dwStyle |= TBSTYLE_LIST | TBSTYLE_FLAT;
458 #if (_MSC_VER >= 1300)
459 return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
460 #else // !(_MSC_VER >= 1300)
461 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
462 return _baseClass::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
463 #endif // !(_MSC_VER >= 1300)
464 }
465
466 BOOL AttachToWindow(HWND hWnd)
467 {
468 ATLASSERT(m_hWnd == NULL);
469 ATLASSERT(::IsWindow(hWnd));
470 BOOL bRet = SubclassWindow(hWnd);
471 if(bRet)
472 {
473 m_bAttachedMenu = true;
474 T* pT = static_cast<T*>(this);
475 pT->GetSystemSettings();
476 }
477 return bRet;
478 }
479
480 BOOL LoadMenu(ATL::_U_STRINGorID menu)
481 {
482 ATLASSERT(::IsWindow(m_hWnd));
483
484 if(m_bAttachedMenu) // doesn't work in this mode
485 return FALSE;
486 if(menu.m_lpstr == NULL)
487 return FALSE;
488
489 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr);
490 if(hMenu == NULL)
491 return FALSE;
492
493 return AttachMenu(hMenu);
494 }
495
496 BOOL AttachMenu(HMENU hMenu)
497 {
498 ATLASSERT(::IsWindow(m_hWnd));
499 ATLASSERT(hMenu == NULL || ::IsMenu(hMenu));
500 if(hMenu != NULL && !::IsMenu(hMenu))
501 return FALSE;
502
503 #if _WTL_CMDBAR_VISTA_MENUS
504 // remove Vista bitmaps if used
505 if(m_bVistaMenus && (m_hMenu != NULL))
506 {
507 T* pT = static_cast<T*>(this);
508 pT->_RemoveVistaBitmapsFromMenu();
509 }
510 #endif // _WTL_CMDBAR_VISTA_MENUS
511
512 // destroy old menu, if needed, and set new one
513 if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) == 0)
514 ::DestroyMenu(m_hMenu);
515
516 m_hMenu = hMenu;
517
518 if(m_bAttachedMenu) // Nothing else in this mode
519 return TRUE;
520
521 // Build buttons according to menu
522 SetRedraw(FALSE);
523
524 // Clear all buttons
525 int nCount = GetButtonCount();
526 for(int i = 0; i < nCount; i++)
527 ATLVERIFY(DeleteButton(0) != FALSE);
528
529 // Add buttons for each menu item
530 if(m_hMenu != NULL)
531 {
532 int nItems = ::GetMenuItemCount(m_hMenu);
533
534 T* pT = static_cast<T*>(this);
535 pT; // avoid level 4 warning
536 TCHAR szString[pT->_nMaxMenuItemTextLength] = { 0 };
537 for(int i = 0; i < nItems; i++)
538 {
539 CMenuItemInfo mii;
540 mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU;
541 mii.fType = MFT_STRING;
542 mii.dwTypeData = szString;
543 mii.cch = pT->_nMaxMenuItemTextLength;
544 BOOL bRet = ::GetMenuItemInfo(m_hMenu, i, TRUE, &mii);
545 ATLASSERT(bRet);
546 // If we have more than the buffer, we assume we have bitmaps bits
547 if(lstrlen(szString) > pT->_nMaxMenuItemTextLength - 1)
548 {
549 mii.fType = MFT_BITMAP;
550 ::SetMenuItemInfo(m_hMenu, i, TRUE, &mii);
551 szString[0] = 0;
552 }
553
554 // NOTE: Command Bar currently supports only drop-down menu items
555 ATLASSERT(mii.hSubMenu != NULL);
556
557 TBBUTTON btn = { 0 };
558 btn.iBitmap = 0;
559 btn.idCommand = i;
560 btn.fsState = (BYTE)(((mii.fState & MFS_DISABLED) == 0) ? TBSTATE_ENABLED : 0);
561 btn.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_DROPDOWN;
562 btn.dwData = 0;
563 btn.iString = 0;
564
565 bRet = InsertButton(-1, &btn);
566 ATLASSERT(bRet);
567
568 TBBUTTONINFO bi = { 0 };
569 bi.cbSize = sizeof(TBBUTTONINFO);
570 bi.dwMask = TBIF_TEXT;
571 bi.pszText = szString;
572
573 bRet = SetButtonInfo(i, &bi);
574 ATLASSERT(bRet);
575 }
576 }
577
578 SetRedraw(TRUE);
579 Invalidate();
580 UpdateWindow();
581
582 return TRUE;
583 }
584
585 BOOL LoadImages(ATL::_U_STRINGorID image)
586 {
587 return _LoadImagesHelper(image, false);
588 }
589
590 BOOL LoadMappedImages(UINT nIDImage, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
591 {
592 return _LoadImagesHelper(nIDImage, true, nFlags , lpColorMap, nMapSize);
593 }
594
595 BOOL _LoadImagesHelper(ATL::_U_STRINGorID image, bool bMapped, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
596 {
597 ATLASSERT(::IsWindow(m_hWnd));
598 HINSTANCE hInstance = ModuleHelper::GetResourceInstance();
599
600 HRSRC hRsrc = ::FindResource(hInstance, image.m_lpstr, (LPTSTR)RT_TOOLBAR);
601 if(hRsrc == NULL)
602 return FALSE;
603
604 HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc);
605 if(hGlobal == NULL)
606 return FALSE;
607
608 _ToolBarData* pData = (_ToolBarData*)::LockResource(hGlobal);
609 if(pData == NULL)
610 return FALSE;
611 ATLASSERT(pData->wVersion == 1);
612
613 WORD* pItems = pData->items();
614 int nItems = pData->wItemCount;
615
616 // Set internal data
617 SetImageSize(pData->wWidth, pData->wHeight);
618
619 // Create image list if needed
620 if(m_hImageList == NULL)
621 {
622 // Check if the bitmap is 32-bit (alpha channel) bitmap (valid for Windows XP only)
623 T* pT = static_cast<T*>(this);
624 m_bAlphaImages = AtlIsAlphaBitmapResource(image);
625
626 if(!pT->CreateInternalImageList(pData->wItemCount))
627 return FALSE;
628 }
629
630 #if _WTL_CMDBAR_VISTA_MENUS
631 int nOldImageCount = ::ImageList_GetImageCount(m_hImageList);
632 #endif // _WTL_CMDBAR_VISTA_MENUS
633
634 // Add bitmap to our image list
635 CBitmap bmp;
636 if(bMapped)
637 {
638 ATLASSERT(HIWORD(PtrToUlong(image.m_lpstr)) == 0); // if mapped, must be a numeric ID
639 int nIDImage = (int)(short)LOWORD(PtrToUlong(image.m_lpstr));
640 bmp.LoadMappedBitmap(nIDImage, (WORD)nFlags, lpColorMap, nMapSize);
641 }
642 else
643 {
644 if(m_bAlphaImages)
645 bmp = (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), image.m_lpstr, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
646 else
647 bmp.LoadBitmap(image.m_lpstr);
648 }
649 ATLASSERT(bmp.m_hBitmap != NULL);
650 if(bmp.m_hBitmap == NULL)
651 return FALSE;
652 if(::ImageList_AddMasked(m_hImageList, bmp, m_clrMask) == -1)
653 return FALSE;
654
655 // Fill the array with command IDs
656 for(int i = 0; i < nItems; i++)
657 {
658 if(pItems[i] != 0)
659 m_arrCommand.Add(pItems[i]);
660 }
661
662 int nImageCount = ::ImageList_GetImageCount(m_hImageList);
663 ATLASSERT(nImageCount == m_arrCommand.GetSize());
664 if(nImageCount != m_arrCommand.GetSize())
665 return FALSE;
666
667 #if _WTL_CMDBAR_VISTA_MENUS
668 if(RunTimeHelper::IsVista())
669 {
670 T* pT = static_cast<T*>(this);
671 pT->_AddVistaBitmapsFromImageList(nOldImageCount, nImageCount - nOldImageCount);
672 ATLASSERT(nImageCount == m_arrVistaBitmap.GetSize());
673 }
674 #endif // _WTL_CMDBAR_VISTA_MENUS
675
676 return TRUE;
677 }
678
679 BOOL AddBitmap(ATL::_U_STRINGorID bitmap, int nCommandID)
680 {
681 ATLASSERT(::IsWindow(m_hWnd));
682 CBitmap bmp;
683 bmp.LoadBitmap(bitmap.m_lpstr);
684 if(bmp.m_hBitmap == NULL)
685 return FALSE;
686 return AddBitmap(bmp, nCommandID);
687 }
688
689 BOOL AddBitmap(HBITMAP hBitmap, UINT nCommandID)
690 {
691 ATLASSERT(::IsWindow(m_hWnd));
692 T* pT = static_cast<T*>(this);
693 // Create image list if it doesn't exist
694 if(m_hImageList == NULL)
695 {
696 if(!pT->CreateInternalImageList(1))
697 return FALSE;
698 }
699 // check bitmap size
700 CBitmapHandle bmp = hBitmap;
701 SIZE size = { 0, 0 };
702 bmp.GetSize(size);
703 if(size.cx != m_szBitmap.cx || size.cy != m_szBitmap.cy)
704 {
705 ATLASSERT(FALSE); // must match size!
706 return FALSE;
707 }
708 // add bitmap
709 int nRet = ::ImageList_AddMasked(m_hImageList, hBitmap, m_clrMask);
710 if(nRet == -1)
711 return FALSE;
712 BOOL bRet = m_arrCommand.Add((WORD)nCommandID);
713 ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize());
714 #if _WTL_CMDBAR_VISTA_MENUS
715 if(RunTimeHelper::IsVista())
716 {
717 pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1);
718 ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize());
719 }
720 #endif // _WTL_CMDBAR_VISTA_MENUS
721 return bRet;
722 }
723
724 BOOL AddIcon(ATL::_U_STRINGorID icon, UINT nCommandID)
725 {
726 ATLASSERT(::IsWindow(m_hWnd));
727 HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
728 if(hIcon == NULL)
729 return FALSE;
730 return AddIcon(hIcon, nCommandID);
731 }
732
733 BOOL AddIcon(HICON hIcon, UINT nCommandID)
734 {
735 ATLASSERT(::IsWindow(m_hWnd));
736 T* pT = static_cast<T*>(this);
737 // create image list if it doesn't exist
738 if(m_hImageList == NULL)
739 {
740 if(!pT->CreateInternalImageList(1))
741 return FALSE;
742 }
743
744 int nRet = ::ImageList_AddIcon(m_hImageList, hIcon);
745 if(nRet == -1)
746 return FALSE;
747 BOOL bRet = m_arrCommand.Add((WORD)nCommandID);
748 ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrCommand.GetSize());
749 #if _WTL_CMDBAR_VISTA_MENUS
750 if(RunTimeHelper::IsVista())
751 {
752 pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize() - 1);
753 ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.GetSize());
754 }
755 #endif // _WTL_CMDBAR_VISTA_MENUS
756 return bRet;
757 }
758
759 BOOL ReplaceBitmap(ATL::_U_STRINGorID bitmap, int nCommandID)
760 {
761 ATLASSERT(::IsWindow(m_hWnd));
762 CBitmap bmp;
763 bmp.LoadBitmap(bitmap.m_lpstr);
764 if(bmp.m_hBitmap == NULL)
765 return FALSE;
766 return ReplaceBitmap(bmp, nCommandID);
767 }
768
769 BOOL ReplaceBitmap(HBITMAP hBitmap, UINT nCommandID)
770 {
771 ATLASSERT(::IsWindow(m_hWnd));
772 BOOL bRet = FALSE;
773 for(int i = 0; i < m_arrCommand.GetSize(); i++)
774 {
775 if(m_arrCommand[i] == nCommandID)
776 {
777 bRet = ::ImageList_Remove(m_hImageList, i);
778 if(bRet)
779 {
780 m_arrCommand.RemoveAt(i);
781 #if _WTL_CMDBAR_VISTA_MENUS
782 if(RunTimeHelper::IsVista())
783 {
784 if(m_arrVistaBitmap[i] != NULL)
785 ::DeleteObject(m_arrVistaBitmap[i]);
786 m_arrVistaBitmap.RemoveAt(i);
787 }
788 #endif // _WTL_CMDBAR_VISTA_MENUS
789 }
790 break;
791 }
792 }
793 if(bRet)
794 bRet = AddBitmap(hBitmap, nCommandID);
795 return bRet;
796 }
797
798 BOOL ReplaceIcon(ATL::_U_STRINGorID icon, UINT nCommandID)
799 {
800 ATLASSERT(::IsWindow(m_hWnd));
801 HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
802 if(hIcon == NULL)
803 return FALSE;
804 return ReplaceIcon(hIcon, nCommandID);
805 }
806
807 BOOL ReplaceIcon(HICON hIcon, UINT nCommandID)
808 {
809 ATLASSERT(::IsWindow(m_hWnd));
810 BOOL bRet = FALSE;
811 for(int i = 0; i < m_arrCommand.GetSize(); i++)
812 {
813 if(m_arrCommand[i] == nCommandID)
814 {
815 bRet = (::ImageList_ReplaceIcon(m_hImageList, i, hIcon) != -1);
816 #if _WTL_CMDBAR_VISTA_MENUS
817 if(RunTimeHelper::IsVista() && bRet != FALSE)
818 {
819 T* pT = static_cast<T*>(this);
820 pT->_ReplaceVistaBitmapFromImageList(i);
821 }
822 #endif // _WTL_CMDBAR_VISTA_MENUS
823 break;
824 }
825 }
826 return bRet;
827 }
828
829 BOOL RemoveImage(int nCommandID)
830 {
831 ATLASSERT(::IsWindow(m_hWnd));
832
833 BOOL bRet = FALSE;
834 for(int i = 0; i < m_arrCommand.GetSize(); i++)
835 {
836 if(m_arrCommand[i] == nCommandID)
837 {
838 bRet = ::ImageList_Remove(m_hImageList, i);
839 if(bRet)
840 {
841 m_arrCommand.RemoveAt(i);
842 #if _WTL_CMDBAR_VISTA_MENUS
843 if(RunTimeHelper::IsVista())
844 {
845 if(m_arrVistaBitmap[i] != NULL)
846 ::DeleteObject(m_arrVistaBitmap[i]);
847 m_arrVistaBitmap.RemoveAt(i);
848 }
849 #endif // _WTL_CMDBAR_VISTA_MENUS
850 }
851 break;
852 }
853 }
854 return bRet;
855 }
856
857 BOOL RemoveAllImages()
858 {
859 ATLASSERT(::IsWindow(m_hWnd));
860
861 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Removing all images\n"));
862 BOOL bRet = ::ImageList_RemoveAll(m_hImageList);
863 if(bRet)
864 {
865 m_arrCommand.RemoveAll();
866 #if _WTL_CMDBAR_VISTA_MENUS
867 for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++)
868 {
869 if(m_arrVistaBitmap[i] != NULL)
870 ::DeleteObject(m_arrVistaBitmap[i]);
871 }
872 m_arrVistaBitmap.RemoveAll();
873 #endif // _WTL_CMDBAR_VISTA_MENUS
874 }
875 return bRet;
876 }
877
878 BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL)
879 {
880 ATLASSERT(::IsWindow(m_hWnd));
881 ATLASSERT(::IsMenu(hMenu));
882 if(!::IsMenu(hMenu))
883 return FALSE;
884 m_bContextMenu = true;
885 if(m_bUseKeyboardCues)
886 m_bShowKeyboardCues = m_bKeyboardInput;
887 T* pT = static_cast<T*>(this);
888 return pT->DoTrackPopupMenu(hMenu, uFlags, x, y, lpParams);
889 }
890
891 BOOL SetMDIClient(HWND /*hWndMDIClient*/)
892 {
893 // Use CMDICommandBarCtrl for MDI support
894 ATLASSERT(FALSE);
895 return FALSE;
896 }
897
898 // Message map and handlers
899 BEGIN_MSG_MAP(CCommandBarCtrlImpl)
900 MESSAGE_HANDLER(WM_CREATE, OnCreate)
901 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
902 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
903 MESSAGE_HANDLER(WM_INITMENU, OnInitMenu)
904 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
905 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
906 MESSAGE_HANDLER(GetAutoPopupMessage(), OnInternalAutoPopup)
907 MESSAGE_HANDLER(GetGetBarMessage(), OnInternalGetBar)
908 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
909 MESSAGE_HANDLER(WM_MENUCHAR, OnMenuChar)
910 MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
911
912 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
913 MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
914 MESSAGE_HANDLER(WM_CHAR, OnChar)
915 MESSAGE_HANDLER(WM_SYSKEYDOWN, OnSysKeyDown)
916 MESSAGE_HANDLER(WM_SYSKEYUP, OnSysKeyUp)
917 MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar)
918 // public API handlers - these stay to support chevrons in atlframe.h
919 MESSAGE_HANDLER(CBRM_GETMENU, OnAPIGetMenu)
920 MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnAPITrackPopupMenu)
921 MESSAGE_HANDLER(CBRM_GETCMDBAR, OnAPIGetCmdBar)
922
923 MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
924 MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
925
926 MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg)
927 ALT_MSG_MAP(1) // Parent window messages
928 NOTIFY_CODE_HANDLER(TBN_HOTITEMCHANGE, OnParentHotItemChange)
929 NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnParentDropDown)
930 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnParentInitMenuPopup)
931 MESSAGE_HANDLER(GetGetBarMessage(), OnParentInternalGetBar)
932 MESSAGE_HANDLER(WM_SYSCOMMAND, OnParentSysCommand)
933 MESSAGE_HANDLER(CBRM_GETMENU, OnParentAPIGetMenu)
934 MESSAGE_HANDLER(WM_MENUCHAR, OnParentMenuChar)
935 MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnParentAPITrackPopupMenu)
936 MESSAGE_HANDLER(CBRM_GETCMDBAR, OnParentAPIGetCmdBar)
937 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnParentSettingChange)
938
939 MESSAGE_HANDLER(WM_DRAWITEM, OnParentDrawItem)
940 MESSAGE_HANDLER(WM_MEASUREITEM, OnParentMeasureItem)
941
942 MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate)
943 NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnParentCustomDraw)
944 ALT_MSG_MAP(2) // MDI client window messages
945 // Use CMDICommandBarCtrl for MDI support
946 ALT_MSG_MAP(3) // Message hook messages
947 MESSAGE_HANDLER(WM_MOUSEMOVE, OnHookMouseMove)
948 MESSAGE_HANDLER(WM_SYSKEYDOWN, OnHookSysKeyDown)
949 MESSAGE_HANDLER(WM_SYSKEYUP, OnHookSysKeyUp)
950 MESSAGE_HANDLER(WM_SYSCHAR, OnHookSysChar)
951 MESSAGE_HANDLER(WM_KEYDOWN, OnHookKeyDown)
952 MESSAGE_HANDLER(WM_NEXTMENU, OnHookNextMenu)
953 MESSAGE_HANDLER(WM_CHAR, OnHookChar)
954 END_MSG_MAP()
955
956 LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
957 {
958 LPMSG pMsg = (LPMSG)lParam;
959 if(pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
960 m_bKeyboardInput = false;
961 else if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
962 m_bKeyboardInput = true;
963 LRESULT lRet = 0;
964 ProcessWindowMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam, lRet, 3);
965 return lRet;
966 }
967
968 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
969 {
970 // Let the toolbar initialize itself
971 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
972 // get and use system settings
973 T* pT = static_cast<T*>(this);
974 pT->GetSystemSettings();
975 // Parent init
976 ATL::CWindow wndParent = GetParent();
977 ATL::CWindow wndTopLevelParent = wndParent.GetTopLevelParent();
978 m_wndParent.SubclassWindow(wndTopLevelParent);
979 // Toolbar Init
980 SetButtonStructSize();
981 SetImageList(NULL);
982
983 // Create message hook if needed
984 CWindowCreateCriticalSectionLock lock;
985 if(FAILED(lock.Lock()))
986 {
987 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnCreate.\n"));
988 ATLASSERT(FALSE);
989 return -1;
990 }
991
992 if(s_pmapMsgHook == NULL)
993 {
994 ATLTRY(s_pmapMsgHook = new CMsgHookMap);
995 ATLASSERT(s_pmapMsgHook != NULL);
996 }
997
998 if(s_pmapMsgHook != NULL)
999 {
1000 DWORD dwThreadID = ::GetCurrentThreadId();
1001 _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
1002 if(pData == NULL)
1003 {
1004 ATLTRY(pData = new _MsgHookData);
1005 ATLASSERT(pData != NULL);
1006 HHOOK hMsgHook = ::SetWindowsHookEx(WH_GETMESSAGE, MessageHookProc, ModuleHelper::GetModuleInstance(), dwThreadID);
1007 ATLASSERT(hMsgHook != NULL);
1008 if(pData != NULL && hMsgHook != NULL)
1009 {
1010 pData->hMsgHook = hMsgHook;
1011 pData->dwUsage = 1;
1012 BOOL bRet = s_pmapMsgHook->Add(dwThreadID, pData);
1013 bRet;
1014 ATLASSERT(bRet);
1015 }
1016 }
1017 else
1018 {
1019 (pData->dwUsage)++;
1020 }
1021 }
1022 lock.Unlock();
1023
1024 // Get layout
1025 #if (WINVER >= 0x0500)
1026 m_bLayoutRTL = ((GetExStyle() & WS_EX_LAYOUTRTL) != 0);
1027 #endif // (WINVER >= 0x0500)
1028
1029 return lRet;
1030 }
1031
1032 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1033 {
1034 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
1035
1036 #if _WTL_CMDBAR_VISTA_MENUS
1037 if(m_bVistaMenus && (m_hMenu != NULL))
1038 {
1039 T* pT = static_cast<T*>(this);
1040 pT->_RemoveVistaBitmapsFromMenu();
1041 }
1042
1043 for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++)
1044 {
1045 if(m_arrVistaBitmap[i] != NULL)
1046 ::DeleteObject(m_arrVistaBitmap[i]);
1047 }
1048 #endif // _WTL_CMDBAR_VISTA_MENUS
1049
1050 if(m_bAttachedMenu) // nothing to do in this mode
1051 return lRet;
1052
1053 CWindowCreateCriticalSectionLock lock;
1054 if(FAILED(lock.Lock()))
1055 {
1056 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::OnDestroy.\n"));
1057 ATLASSERT(FALSE);
1058 return lRet;
1059 }
1060
1061 if(s_pmapMsgHook != NULL)
1062 {
1063 DWORD dwThreadID = ::GetCurrentThreadId();
1064 _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
1065 if(pData != NULL)
1066 {
1067 (pData->dwUsage)--;
1068 if(pData->dwUsage == 0)
1069 {
1070 BOOL bRet = ::UnhookWindowsHookEx(pData->hMsgHook);
1071 ATLASSERT(bRet);
1072 bRet = s_pmapMsgHook->Remove(dwThreadID);
1073 ATLASSERT(bRet);
1074 if(bRet)
1075 delete pData;
1076 }
1077
1078 if(s_pmapMsgHook->GetSize() == 0)
1079 {
1080 delete s_pmapMsgHook;
1081 s_pmapMsgHook = NULL;
1082 }
1083 }
1084 }
1085
1086 lock.Unlock();
1087
1088 return lRet;
1089 }
1090
1091 LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1092 {
1093 #ifdef _CMDBAR_EXTRA_TRACE
1094 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyDown\n"));
1095 #endif
1096 if(m_bAttachedMenu) // nothing to do in this mode
1097 {
1098 bHandled = FALSE;
1099 return 1;
1100 }
1101
1102 bHandled = FALSE;
1103 // Simulate Alt+Space for the parent
1104 if(wParam == VK_SPACE)
1105 {
1106 m_wndParent.PostMessage(WM_SYSKEYDOWN, wParam, lParam | (1 << 29));
1107 bHandled = TRUE;
1108 }
1109 #if (_WIN32_IE >= 0x0500)
1110 else if(wParam == VK_LEFT || wParam == VK_RIGHT)
1111 {
1112 WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT;
1113
1114 if(!m_bMenuActive)
1115 {
1116 T* pT = static_cast<T*>(this);
1117 int nBtn = GetHotItem();
1118 int nNextBtn = (wParam == wpNext) ? pT->GetNextMenuItem(nBtn) : pT->GetPreviousMenuItem(nBtn);
1119 if(nNextBtn == -2)
1120 {
1121 SetHotItem(-1);
1122 if(pT->DisplayChevronMenu())
1123 bHandled = TRUE;
1124 }
1125 }
1126 }
1127 #endif // (_WIN32_IE >= 0x0500)
1128 return 0;
1129 }
1130
1131 LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1132 {
1133 #ifdef _CMDBAR_EXTRA_TRACE
1134 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyUp\n"));
1135 #endif
1136 if(m_bAttachedMenu) // nothing to do in this mode
1137 {
1138 bHandled = FALSE;
1139 return 1;
1140 }
1141
1142 if(wParam != VK_SPACE)
1143 bHandled = FALSE;
1144
1145 return 0;
1146 }
1147
1148 LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1149 {
1150 #ifdef _CMDBAR_EXTRA_TRACE
1151 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnChar\n"));
1152 #endif
1153 if(m_bAttachedMenu) // nothing to do in this mode
1154 {
1155 bHandled = FALSE;
1156 return 1;
1157 }
1158
1159 if(wParam != VK_SPACE)
1160 bHandled = FALSE;
1161 else
1162 return 0;
1163 // Security
1164 if(!m_wndParent.IsWindowEnabled() || ::GetFocus() != m_hWnd)
1165 return 0;
1166
1167 // Handle mnemonic press when we have focus
1168 int nBtn = 0;
1169 if(wParam != VK_RETURN && !MapAccelerator((TCHAR)LOWORD(wParam), nBtn))
1170 {
1171 #if (_WIN32_IE >= 0x0500)
1172 if((TCHAR)LOWORD(wParam) != _chChevronShortcut)
1173 #endif // (_WIN32_IE >= 0x0500)
1174 ::MessageBeep(0);
1175 }
1176 else
1177 {
1178 #if (_WIN32_IE >= 0x0500)
1179 RECT rcClient = { 0 };
1180 GetClientRect(&rcClient);
1181 RECT rcBtn = { 0 };
1182 GetItemRect(nBtn, &rcBtn);
1183 TBBUTTON tbb = { 0 };
1184 GetButton(nBtn, &tbb);
1185 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right)
1186 {
1187 #endif // (_WIN32_IE >= 0x0500)
1188 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
1189 if(wParam != VK_RETURN)
1190 SetHotItem(nBtn);
1191 #if (_WIN32_IE >= 0x0500)
1192 }
1193 else
1194 {
1195 ::MessageBeep(0);
1196 bHandled = TRUE;
1197 }
1198 #endif // (_WIN32_IE >= 0x0500)
1199 }
1200 return 0;
1201 }
1202
1203 LRESULT OnSysKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1204 {
1205 #ifdef _CMDBAR_EXTRA_TRACE
1206 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyDown\n"));
1207 #endif
1208 bHandled = FALSE;
1209 return 0;
1210 }
1211
1212 LRESULT OnSysKeyUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1213 {
1214 #ifdef _CMDBAR_EXTRA_TRACE
1215 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyUp\n"));
1216 #endif
1217 bHandled = FALSE;
1218 return 0;
1219 }
1220
1221 LRESULT OnSysChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1222 {
1223 #ifdef _CMDBAR_EXTRA_TRACE
1224 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysChar\n"));
1225 #endif
1226 bHandled = FALSE;
1227 return 0;
1228 }
1229
1230 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1231 {
1232 if(m_bAttachedMenu || (m_dwExtendedStyle & CBR_EX_TRANSPARENT))
1233 {
1234 bHandled = FALSE;
1235 return 0;
1236 }
1237
1238 CDCHandle dc = (HDC)wParam;
1239 RECT rect = { 0 };
1240 GetClientRect(&rect);
1241 dc.FillRect(&rect, COLOR_MENU);
1242
1243 return 1; // don't do the default erase
1244 }
1245
1246 LRESULT OnInitMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1247 {
1248 int nIndex = GetHotItem();
1249 SendMessage(WM_MENUSELECT, MAKEWPARAM(nIndex, MF_POPUP|MF_HILITE), (LPARAM)m_hMenu);
1250 bHandled = FALSE;
1251 return 1;
1252 }
1253
1254 LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1255 {
1256 if((BOOL)HIWORD(lParam)) // System menu, do nothing
1257 {
1258 bHandled = FALSE;
1259 return 1;
1260 }
1261
1262 if(!(m_bAttachedMenu || m_bMenuActive)) // Not attached or ours, do nothing
1263 {
1264 bHandled = FALSE;
1265 return 1;
1266 }
1267
1268 #ifdef _CMDBAR_EXTRA_TRACE
1269 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnInitMenuPopup\n"));
1270 #endif
1271 // forward to the parent or subclassed window, so it can handle update UI
1272 LRESULT lRet = 0;
1273 if(m_bAttachedMenu)
1274 lRet = DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem());
1275 else
1276 lRet = m_wndParent.DefWindowProc(uMsg, wParam, (lParam || m_bContextMenu) ? lParam : GetHotItem());
1277
1278 #if _WTL_CMDBAR_VISTA_MENUS
1279 // If Vista menus are active, just set bitmaps and return
1280 if(m_bVistaMenus)
1281 {
1282 CMenuHandle menu = (HMENU)wParam;
1283 ATLASSERT(menu.m_hMenu != NULL);
1284
1285 for(int i = 0; i < menu.GetMenuItemCount(); i++)
1286 {
1287 WORD nID = (WORD)menu.GetMenuItemID(i);
1288 int nIndex = m_arrCommand.Find(nID);
1289
1290 CMenuItemInfo mii;
1291 mii.fMask = MIIM_BITMAP;
1292 mii.hbmpItem = (m_bImagesVisible && (nIndex != -1)) ? m_arrVistaBitmap[nIndex] : NULL;
1293 menu.SetMenuItemInfo(i, TRUE, &mii);
1294 }
1295
1296 return lRet;
1297 }
1298 #endif // _WTL_CMDBAR_VISTA_MENUS
1299
1300 // Convert menu items to ownerdraw, add our data
1301 if(m_bImagesVisible)
1302 {
1303 CMenuHandle menuPopup = (HMENU)wParam;
1304 ATLASSERT(menuPopup.m_hMenu != NULL);
1305
1306 T* pT = static_cast<T*>(this);
1307 pT; // avoid level 4 warning
1308 TCHAR szString[pT->_nMaxMenuItemTextLength] = { 0 };
1309 BOOL bRet = FALSE;
1310 for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
1311 {
1312 CMenuItemInfo mii;
1313 mii.cch = pT->_nMaxMenuItemTextLength;
1314 mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
1315 mii.dwTypeData = szString;
1316 bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
1317 ATLASSERT(bRet);
1318
1319 if(!(mii.fType & MFT_OWNERDRAW)) // Not already an ownerdraw item
1320 {
1321 mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
1322 _MenuItemData* pMI = NULL;
1323 ATLTRY(pMI = new _MenuItemData);
1324 ATLASSERT(pMI != NULL);
1325 if(pMI != NULL)
1326 {
1327 pMI->fType = mii.fType;
1328 pMI->fState = mii.fState;
1329 mii.fType |= MFT_OWNERDRAW;
1330 pMI->iButton = -1;
1331 for(int j = 0; j < m_arrCommand.GetSize(); j++)
1332 {
1333 if(m_arrCommand[j] == mii.wID)
1334 {
1335 pMI->iButton = j;
1336 break;
1337 }
1338 }
1339 int cchLen = lstrlen(szString) + 1;
1340 pMI->lpstrText = NULL;
1341 ATLTRY(pMI->lpstrText = new TCHAR[cchLen]);
1342 ATLASSERT(pMI->lpstrText != NULL);
1343 if(pMI->lpstrText != NULL)
1344 SecureHelper::strcpy_x(pMI->lpstrText, cchLen, szString);
1345 mii.dwItemData = (ULONG_PTR)pMI;
1346 bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
1347 ATLASSERT(bRet);
1348 }
1349 }
1350 }
1351
1352 // Add it to the list
1353 m_stackMenuHandle.Push(menuPopup.m_hMenu);
1354 }
1355
1356 return lRet;
1357 }
1358
1359 LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1360 {
1361 if(!m_bAttachedMenu) // Not attached, do nothing, forward to parent
1362 {
1363 m_bPopupItem = (lParam != NULL) && ((HMENU)lParam != m_hMenu) && (HIWORD(wParam) & MF_POPUP);
1364 if(m_wndParent.IsWindow())
1365 m_wndParent.SendMessage(uMsg, wParam, lParam);
1366 bHandled = FALSE;
1367 return 1;
1368 }
1369
1370 // Check if a menu is closing, do a cleanup
1371 if(HIWORD(wParam) == 0xFFFF && lParam == NULL) // Menu closing
1372 {
1373 #ifdef _CMDBAR_EXTRA_TRACE
1374 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuSelect - CLOSING!!!!\n"));
1375 #endif
1376 ATLASSERT(m_stackMenuWnd.GetSize() == 0);
1377 // Restore the menu items to the previous state for all menus that were converted
1378 if(m_bImagesVisible)
1379 {
1380 HMENU hMenu = NULL;
1381 while((hMenu = m_stackMenuHandle.Pop()) != NULL)
1382 {
1383 CMenuHandle menuPopup = hMenu;
1384 ATLASSERT(menuPopup.m_hMenu != NULL);
1385 // Restore state and delete menu item data
1386 BOOL bRet = FALSE;
1387 for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
1388 {
1389 CMenuItemInfo mii;
1390 mii.fMask = MIIM_DATA | MIIM_TYPE;
1391 bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
1392 ATLASSERT(bRet);
1393
1394 _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData;
1395 if(pMI != NULL && pMI->IsCmdBarMenuItem())
1396 {
1397 mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
1398 mii.fType = pMI->fType;
1399 mii.dwTypeData = pMI->lpstrText;
1400 mii.cch = lstrlen(pMI->lpstrText);
1401 mii.dwItemData = NULL;
1402
1403 bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
1404 ATLASSERT(bRet);
1405
1406 delete [] pMI->lpstrText;
1407 pMI->dwMagic = 0x6666;
1408 delete pMI;
1409 }
1410 }
1411 }
1412 }
1413 }
1414
1415 bHandled = FALSE;
1416 return 1;
1417 }
1418
1419 LRESULT OnInternalAutoPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1420 {
1421 int nIndex = (int)wParam;
1422 T* pT = static_cast<T*>(this);
1423 pT->DoPopupMenu(nIndex, false);
1424 return 0;
1425 }
1426
1427 LRESULT OnInternalGetBar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1428 {
1429 // Let's make sure we're not embedded in another process
1430 if((LPVOID)wParam != NULL)
1431 *((DWORD*)wParam) = GetCurrentProcessId();
1432 if(IsWindowVisible())
1433 return (LRESULT)static_cast<CCommandBarCtrlBase*>(this);
1434 else
1435 return NULL;
1436 }
1437
1438 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1439 {
1440 #ifndef SPI_SETKEYBOARDCUES
1441 const UINT SPI_SETKEYBOARDCUES = 0x100B;
1442 #endif // !SPI_SETKEYBOARDCUES
1443 #ifndef SPI_GETFLATMENU
1444 const UINT SPI_SETFLATMENU = 0x1023;
1445 #endif // !SPI_GETFLATMENU
1446
1447 if(wParam == SPI_SETNONCLIENTMETRICS || wParam == SPI_SETKEYBOARDCUES || wParam == SPI_SETFLATMENU)
1448 {
1449 T* pT = static_cast<T*>(this);
1450 pT->GetSystemSettings();
1451 }
1452
1453 return 0;
1454 }
1455
1456 LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1457 {
1458 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
1459
1460 LPWINDOWPOS lpWP = (LPWINDOWPOS)lParam;
1461 int cyMin = ::GetSystemMetrics(SM_CYMENU);
1462 if(lpWP->cy < cyMin)
1463 lpWP->cy = cyMin;
1464
1465 return lRet;
1466 }
1467
1468 LRESULT OnMenuChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1469 {
1470 #ifdef _CMDBAR_EXTRA_TRACE
1471 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuChar\n"));
1472 #endif
1473 bHandled = TRUE;
1474 T* pT = static_cast<T*>(this);
1475
1476 LRESULT lRet;
1477 if(m_bMenuActive && LOWORD(wParam) != 0x0D)
1478 lRet = 0;
1479 else
1480 lRet = MAKELRESULT(1, 1);
1481
1482 if(m_bMenuActive && HIWORD(wParam) == MF_POPUP)
1483 {
1484 // Convert character to lower/uppercase and possibly Unicode, using current keyboard layout
1485 TCHAR ch = (TCHAR)LOWORD(wParam);
1486 CMenuHandle menu = (HMENU)lParam;
1487 int nCount = ::GetMenuItemCount(menu);
1488 int nRetCode = MNC_EXECUTE;
1489 BOOL bRet = FALSE;
1490 TCHAR szString[pT->_nMaxMenuItemTextLength] = { 0 };
1491 WORD wMnem = 0;
1492 bool bFound = false;
1493 for(int i = 0; i < nCount; i++)
1494 {
1495 CMenuItemInfo mii;
1496 mii.cch = pT->_nMaxMenuItemTextLength;
1497 mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
1498 mii.dwTypeData = szString;
1499 bRet = menu.GetMenuItemInfo(i, TRUE, &mii);
1500 if(!bRet || (mii.fType & MFT_SEPARATOR))
1501 continue;
1502 _MenuItemData* pmd = (_MenuItemData*)mii.dwItemData;
1503 if(pmd != NULL && pmd->IsCmdBarMenuItem())
1504 {
1505 LPTSTR p = pmd->lpstrText;
1506
1507 if(p != NULL)
1508 {
1509 while(*p && *p != _T('&'))
1510 p = ::CharNext(p);
1511 if(p != NULL && *p)
1512 {
1513 DWORD dwP = MAKELONG(*(++p), 0);
1514 DWORD dwC = MAKELONG(ch, 0);
1515 if(::CharLower((LPTSTR)ULongToPtr(dwP)) == ::CharLower((LPTSTR)ULongToPtr(dwC)))
1516 {
1517 if(!bFound)
1518 {
1519 wMnem = (WORD)i;
1520 bFound = true;
1521 }
1522 else
1523 {
1524 nRetCode = MNC_SELECT;
1525 break;
1526 }
1527 }
1528 }
1529 }
1530 }
1531 }
1532 if(bFound)
1533 {
1534 if(nRetCode == MNC_EXECUTE)
1535 {
1536 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
1537 pT->GiveFocusBack();
1538 }
1539 bHandled = TRUE;
1540 lRet = MAKELRESULT(wMnem, nRetCode);
1541 }
1542 }
1543 else if(!m_bMenuActive)
1544 {
1545 int nBtn = 0;
1546 if(!MapAccelerator((TCHAR)LOWORD(wParam), nBtn))
1547 {
1548 bHandled = FALSE;
1549 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
1550 pT->GiveFocusBack();
1551
1552 #if (_WIN32_IE >= 0x0500)
1553 // check if we should display chevron menu
1554 if((TCHAR)LOWORD(wParam) == pT->_chChevronShortcut)
1555 {
1556 if(pT->DisplayChevronMenu())
1557 bHandled = TRUE;
1558 }
1559 #endif // (_WIN32_IE >= 0x0500)
1560 }
1561 else if(m_wndParent.IsWindowEnabled())
1562 {
1563 #if (_WIN32_IE >= 0x0500)
1564 RECT rcClient = { 0 };
1565 GetClientRect(&rcClient);
1566 RECT rcBtn = { 0 };
1567 GetItemRect(nBtn, &rcBtn);
1568 TBBUTTON tbb = { 0 };
1569 GetButton(nBtn, &tbb);
1570 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right)
1571 {
1572 #endif // (_WIN32_IE >= 0x0500)
1573 if(m_bUseKeyboardCues && !m_bShowKeyboardCues)
1574 {
1575 m_bAllowKeyboardCues = true;
1576 ShowKeyboardCues(true);
1577 }
1578 pT->TakeFocus();
1579 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
1580 SetHotItem(nBtn);
1581 #if (_WIN32_IE >= 0x0500)
1582 }
1583 else
1584 {
1585 ::MessageBeep(0);
1586 }
1587 #endif // (_WIN32_IE >= 0x0500)
1588 }
1589 }
1590
1591 return lRet;
1592 }
1593
1594 LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1595 {
1596 if(m_bUseKeyboardCues && m_bShowKeyboardCues)
1597 ShowKeyboardCues(false);
1598
1599 bHandled = FALSE;
1600 return 1;
1601 }
1602
1603 LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1604 {
1605 LPDRAWITEMSTRUCT lpDrawItemStruct = (LPDRAWITEMSTRUCT)lParam;
1606 _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
1607 if(lpDrawItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem())
1608 {
1609 T* pT = static_cast<T*>(this);
1610 pT->DrawItem(lpDrawItemStruct);
1611 }
1612 else
1613 {
1614 bHandled = FALSE;
1615 }
1616 return (LRESULT)TRUE;
1617 }
1618
1619 LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1620 {
1621 LPMEASUREITEMSTRUCT lpMeasureItemStruct = (LPMEASUREITEMSTRUCT)lParam;
1622 _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;
1623 if(lpMeasureItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->IsCmdBarMenuItem())
1624 {
1625 T* pT = static_cast<T*>(this);
1626 pT->MeasureItem(lpMeasureItemStruct);
1627 }
1628 else
1629 {
1630 bHandled = FALSE;
1631 }
1632 return (LRESULT)TRUE;
1633 }
1634
1635 // API message handlers
1636 LRESULT OnAPIGetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1637 {
1638 return (LRESULT)m_hMenu;
1639 }
1640
1641 LRESULT OnAPITrackPopupMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
1642 {
1643 if(lParam == NULL)
1644 return FALSE;
1645 LPCBRPOPUPMENU lpCBRPopupMenu = (LPCBRPOPUPMENU)lParam;
1646 if(lpCBRPopupMenu->cbSize != sizeof(CBRPOPUPMENU))
1647 return FALSE;
1648
1649 T* pT = static_cast<T*>(this);
1650 return pT->TrackPopupMenu(lpCBRPopupMenu->hMenu, lpCBRPopupMenu->uFlags, lpCBRPopupMenu->x, lpCBRPopupMenu->y, lpCBRPopupMenu->lptpm);
1651 }
1652
1653 LRESULT OnAPIGetCmdBar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1654 {
1655 return (LRESULT)m_hWnd;
1656 }
1657
1658 // Parent window message handlers
1659 LRESULT OnParentHotItemChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1660 {
1661 LPNMTBHOTITEM lpNMHT = (LPNMTBHOTITEM)pnmh;
1662
1663 // Check if this comes from us
1664 if(pnmh->hwndFrom != m_hWnd)
1665 {
1666 bHandled = FALSE;
1667 return 0;
1668 }
1669
1670 bool bBlockTracking = false;
1671 if((m_dwExtendedStyle & CBR_EX_TRACKALWAYS) == 0)
1672 {
1673 DWORD dwProcessID;
1674 ::GetWindowThreadProcessId(::GetActiveWindow(), &dwProcessID);
1675 bBlockTracking = (::GetCurrentProcessId() != dwProcessID);
1676 }
1677
1678 if((!m_wndParent.IsWindowEnabled() || bBlockTracking) && (lpNMHT->dwFlags & HICF_MOUSE))
1679 {
1680 return 1;
1681 }
1682 else
1683 {
1684 #ifndef HICF_LMOUSE
1685 const DWORD HICF_LMOUSE = 0x00000080; // left mouse button selected
1686 #endif
1687 bHandled = FALSE;
1688
1689 // Send WM_MENUSELECT to the app if it needs to display a status text
1690 if(!(lpNMHT->dwFlags & HICF_MOUSE)
1691 && !(lpNMHT->dwFlags & HICF_ACCELERATOR)
1692 && !(lpNMHT->dwFlags & HICF_LMOUSE))
1693 {
1694 if(lpNMHT->dwFlags & HICF_ENTERING)
1695 m_wndParent.SendMessage(WM_MENUSELECT, 0, (LPARAM)m_hMenu);
1696 if(lpNMHT->dwFlags & HICF_LEAVING)
1697 m_wndParent.SendMessage(WM_MENUSELECT, MAKEWPARAM(0, 0xFFFF), NULL);
1698 }
1699
1700 return 0;
1701 }
1702 }
1703
1704 LRESULT OnParentDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1705 {
1706 // Check if this comes from us
1707 if(pnmh->hwndFrom != m_hWnd)
1708 {
1709 bHandled = FALSE;
1710 return 1;
1711 }
1712
1713 T* pT = static_cast<T*>(this);
1714 if(::GetFocus() != m_hWnd)
1715 pT->TakeFocus();
1716 LPNMTOOLBAR pNMToolBar = (LPNMTOOLBAR)pnmh;
1717 int nIndex = CommandToIndex(pNMToolBar->iItem);
1718 m_bContextMenu = false;
1719 m_bEscapePressed = false;
1720 pT->DoPopupMenu(nIndex, true);
1721
1722 return TBDDRET_DEFAULT;
1723 }
1724
1725 LRESULT OnParentInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1726 {
1727 return OnInitMenuPopup(uMsg, wParam, lParam, bHandled);
1728 }
1729
1730 LRESULT OnParentInternalGetBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1731 {
1732 return OnInternalGetBar(uMsg, wParam, lParam, bHandled);
1733 }
1734
1735 LRESULT OnParentSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1736 {
1737 bHandled = FALSE;
1738 if((m_uSysKey == VK_MENU
1739 || (m_uSysKey == VK_F10 && !(::GetKeyState(VK_SHIFT) & 0x80))
1740 || m_uSysKey == VK_SPACE)
1741 && wParam == SC_KEYMENU)
1742 {
1743 T* pT = static_cast<T*>(this);
1744 if(::GetFocus() == m_hWnd)
1745 {
1746 pT->GiveFocusBack(); // exit menu "loop"
1747 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
1748 }
1749 else if(m_uSysKey != VK_SPACE && !m_bSkipMsg)
1750 {
1751 if(m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues)
1752 ShowKeyboardCues(true);
1753
1754 pT->TakeFocus(); // enter menu "loop"
1755 bHandled = TRUE;
1756 }
1757 else if(m_uSysKey != VK_SPACE)
1758 {
1759 bHandled = TRUE;
1760 }
1761 }
1762 m_bSkipMsg = false;
1763 return 0;
1764 }
1765
1766 LRESULT OnParentAPIGetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1767 {
1768 return OnAPIGetMenu(uMsg, wParam, lParam, bHandled);
1769 }
1770
1771 LRESULT OnParentMenuChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1772 {
1773 return OnMenuChar(uMsg, wParam, lParam, bHandled);
1774 }
1775
1776 LRESULT OnParentAPITrackPopupMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1777 {
1778 return OnAPITrackPopupMenu(uMsg, wParam, lParam, bHandled);
1779 }
1780
1781 LRESULT OnParentAPIGetCmdBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1782 {
1783 return OnAPIGetCmdBar(uMsg, wParam, lParam, bHandled);
1784 }
1785
1786 LRESULT OnParentSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1787 {
1788 OnSettingChange(uMsg, wParam, lParam, bHandled);
1789 bHandled = FALSE;
1790 return 1;
1791 }
1792
1793 LRESULT OnParentDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1794 {
1795 return OnDrawItem(uMsg, wParam, lParam, bHandled);
1796 }
1797
1798 LRESULT OnParentMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1799 {
1800 return OnMeasureItem(uMsg, wParam, lParam, bHandled);
1801 }
1802
1803 LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1804 {
1805 m_bParentActive = (LOWORD(wParam) != WA_INACTIVE);
1806 if(!m_bParentActive && m_bUseKeyboardCues && m_bShowKeyboardCues)
1807 {
1808 ShowKeyboardCues(false); // this will repaint our window
1809 }
1810 else
1811 {
1812 Invalidate();
1813 UpdateWindow();
1814 }
1815 bHandled = FALSE;
1816 return 1;
1817 }
1818
1819 LRESULT OnParentCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1820 {
1821 LRESULT lRet = CDRF_DODEFAULT;
1822 bHandled = FALSE;
1823 if(pnmh->hwndFrom == m_hWnd)
1824 {
1825 LPNMTBCUSTOMDRAW lpTBCustomDraw = (LPNMTBCUSTOMDRAW)pnmh;
1826 if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
1827 {
1828 lRet = CDRF_NOTIFYITEMDRAW;
1829 bHandled = TRUE;
1830 }
1831 else if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
1832 {
1833 #if _WTL_CMDBAR_VISTA_MENUS && defined(_WTL_CMDBAR_VISTA_STD_MENUBAR)
1834 if(m_bVistaMenus)
1835 {
1836 ::SetRectEmpty(&lpTBCustomDraw->rcText);
1837 lRet = CDRF_NOTIFYPOSTPAINT;
1838 bHandled = TRUE;
1839 }
1840 else
1841 #endif // _WTL_CMDBAR_VISTA_MENUS && defined(_WTL_CMDBAR_VISTA_STD_MENUBAR)
1842 {
1843 if(m_bFlatMenus)
1844 {
1845 #ifndef COLOR_MENUHILIGHT
1846 const int COLOR_MENUHILIGHT = 29;
1847 #endif // !COLOR_MENUHILIGHT
1848 bool bDisabled = ((lpTBCustomDraw->nmcd.uItemState & CDIS_DISABLED) == CDIS_DISABLED);
1849 if(!bDisabled && ((lpTBCustomDraw->nmcd.uItemState & CDIS_HOT) == CDIS_HOT ||
1850 (lpTBCustomDraw->nmcd.uItemState & CDIS_SELECTED) == CDIS_SELECTED))
1851 {
1852 ::FillRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_MENUHILIGHT));
1853 ::FrameRect(lpTBCustomDraw->nmcd.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_HIGHLIGHT));
1854 lpTBCustomDraw->clrText = ::GetSysColor(m_bParentActive ? COLOR_HIGHLIGHTTEXT : COLOR_GRAYTEXT);
1855 }
1856 else if(bDisabled || !m_bParentActive)
1857 {
1858 lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT);
1859 }
1860
1861 _ParentCustomDrawHelper(lpTBCustomDraw);
1862
1863 lRet = CDRF_SKIPDEFAULT;
1864 bHandled = TRUE;
1865 }
1866 else if(!m_bParentActive)
1867 {
1868 lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT);
1869 bHandled = TRUE;
1870 }
1871 }
1872 }
1873 #if _WTL_CMDBAR_VISTA_MENUS && defined(_WTL_CMDBAR_VISTA_STD_MENUBAR)
1874 else if (lpTBCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT)
1875 {
1876 bool bDisabled = ((lpTBCustomDraw->nmcd.uItemState & CDIS_DISABLED) == CDIS_DISABLED);
1877 if(bDisabled || !m_bParentActive)
1878 lpTBCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT);
1879
1880 _ParentCustomDrawHelper(lpTBCustomDraw);
1881
1882 lRet = CDRF_SKIPDEFAULT;
1883 bHandled = TRUE;
1884 }
1885 #endif // _WTL_CMDBAR_VISTA_MENUS && defined(_WTL_CMDBAR_VISTA_STD_MENUBAR)
1886 }
1887 return lRet;
1888 }
1889
1890 void _ParentCustomDrawHelper(LPNMTBCUSTOMDRAW lpTBCustomDraw)
1891 {
1892 CDCHandle dc = lpTBCustomDraw->nmcd.hdc;
1893 dc.SetTextColor(lpTBCustomDraw->clrText);
1894 dc.SetBkMode(lpTBCustomDraw->nStringBkMode);
1895
1896 HFONT hFont = GetFont();
1897 HFONT hFontOld = NULL;
1898 if(hFont != NULL)
1899 hFontOld = dc.SelectFont(hFont);
1900
1901 const int cchText = 200;
1902 TCHAR szText[cchText] = { 0 };
1903 TBBUTTONINFO tbbi = { 0 };
1904 tbbi.cbSize = sizeof(TBBUTTONINFO);
1905 tbbi.dwMask = TBIF_TEXT;
1906 tbbi.pszText = szText;
1907 tbbi.cchText = cchText;
1908 GetButtonInfo((int)lpTBCustomDraw->nmcd.dwItemSpec, &tbbi);
1909
1910 dc.DrawText(szText, -1, &lpTBCustomDraw->nmcd.rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX));
1911
1912 if(hFont != NULL)
1913 dc.SelectFont(hFontOld);
1914 }
1915
1916 // Message hook handlers
1917 LRESULT OnHookMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1918 {
1919 static POINT s_point = { -1, -1 };
1920 DWORD dwPoint = ::GetMessagePos();
1921 POINT point = { GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint) };
1922
1923 bHandled = FALSE;
1924 if(m_bMenuActive)
1925 {
1926 if(::WindowFromPoint(point) == m_hWnd)
1927 {
1928 ScreenToClient(&point);
1929 int nHit = HitTest(&point);
1930
1931 if((point.x != s_point.x || point.y != s_point.y) && nHit >= 0 && nHit < ::GetMenuItemCount(m_hMenu) && nHit != m_nPopBtn && m_nPopBtn != -1)
1932 {
1933 TBBUTTON tbb = { 0 };
1934 GetButton(nHit, &tbb);
1935 if((tbb.fsState & TBSTATE_ENABLED) != 0)
1936 {
1937 m_nNextPopBtn = nHit | 0xFFFF0000;
1938 HWND hWndMenu = m_stackMenuWnd.GetCurrent();
1939 ATLASSERT(hWndMenu != NULL);
1940
1941 // this one is needed to close a menu if mouse button was down
1942 ::PostMessage(hWndMenu, WM_LBUTTONUP, 0, MAKELPARAM(point.x, point.y));
1943 // this one closes a popup menu
1944 ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L);
1945
1946 bHandled = TRUE;
1947 }
1948 }
1949 }
1950 }
1951 else
1952 {
1953 ScreenToClient(&point);
1954 }
1955
1956 s_point = point;
1957 return 0;
1958 }
1959
1960 LRESULT OnHookSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1961 {
1962 bHandled = FALSE;
1963 #ifdef _CMDBAR_EXTRA_TRACE
1964 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYDOWN (0x%2.2X)\n"), wParam);
1965 #endif
1966
1967 if(wParam == VK_MENU && m_bParentActive && m_bUseKeyboardCues && !m_bShowKeyboardCues && m_bAllowKeyboardCues)
1968 ShowKeyboardCues(true);
1969
1970 if(wParam != VK_SPACE && !m_bMenuActive && ::GetFocus() == m_hWnd)
1971 {
1972 m_bAllowKeyboardCues = false;
1973 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
1974 T* pT = static_cast<T*>(this);
1975 pT->GiveFocusBack();
1976 m_bSkipMsg = true;
1977 }
1978 else
1979 {
1980 if(wParam == VK_SPACE && m_bUseKeyboardCues && m_bShowKeyboardCues)
1981 {
1982 m_bAllowKeyboardCues = true;
1983 ShowKeyboardCues(false);
1984 }
1985 m_uSysKey = (UINT)wParam;
1986 }
1987 return 0;
1988 }
1989
1990 LRESULT OnHookSysKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1991 {
1992 if(!m_bAllowKeyboardCues)
1993 m_bAllowKeyboardCues = true;
1994 bHandled = FALSE;
1995 wParam;
1996 #ifdef _CMDBAR_EXTRA_TRACE
1997 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYUP (0x%2.2X)\n"), wParam);
1998 #endif
1999 return 0;
2000 }
2001
2002 LRESULT OnHookSysChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
2003 {
2004 bHandled = FALSE;
2005 #ifdef _CMDBAR_EXTRA_TRACE
2006 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSCHAR (0x%2.2X)\n"), wParam);
2007 #endif
2008
2009 if(!m_bMenuActive && m_hWndHook != m_hWnd && wParam != VK_SPACE)
2010 bHandled = TRUE;
2011 return 0;
2012 }
2013
2014 LRESULT OnHookKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
2015 {
2016 #ifdef _CMDBAR_EXTRA_TRACE
2017 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_KEYDOWN (0x%2.2X)\n"), wParam);
2018 #endif
2019 bHandled = FALSE;
2020 T* pT = static_cast<T*>(this);
2021
2022 if(wParam == VK_ESCAPE && m_stackMenuWnd.GetSize() <= 1)
2023 {
2024 if(m_bMenuActive && !m_bContextMenu)
2025 {
2026 int nHot = GetHotItem();
2027 if(nHot == -1)
2028 nHot = m_nPopBtn;
2029 if(nHot == -1)
2030 nHot = 0;
2031 SetHotItem(nHot);
2032 bHandled = TRUE;
2033 pT->TakeFocus();
2034 m_bEscapePressed = true; // To keep focus
2035 m_bSkipPostDown = false;
2036 }
2037 else if(::GetFocus() == m_hWnd && m_wndParent.IsWindow())
2038 {
2039 SetHotItem(-1);
2040 pT->GiveFocusBack();
2041 bHandled = TRUE;
2042 }
2043 }
2044 else if(wParam == VK_RETURN || wParam == VK_UP || wParam == VK_DOWN)
2045 {
2046 if(!m_bMenuActive && ::GetFocus() == m_hWnd && m_wndParent.IsWindow())
2047 {
2048 int nHot = GetHotItem();
2049 if(nHot != -1)
2050 {
2051 if(wParam != VK_RETURN)
2052 {
2053 if(!m_bSkipPostDown)
2054 {
2055 // IE4 only: WM_KEYDOWN doesn't generate TBN_DROPDOWN, we need to simulate a mouse click
2056 #if (_WIN32_IE < 0x0500)
2057 DWORD dwMajor = 0, dwMinor = 0;
2058 ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
2059 if(dwMajor <= 4 || (dwMajor == 5 && dwMinor < 80))
2060 {
2061 RECT rect = { 0 };
2062 GetItemRect(nHot, &rect);
2063 PostMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(rect.left, rect.top));
2064 }
2065 #endif // (_WIN32_IE < 0x0500)
2066 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
2067 m_bSkipPostDown = true;
2068 }
2069 else
2070 {
2071 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - skipping posting another VK_DOWN\n"));
2072 m_bSkipPostDown = false;
2073 }
2074 }
2075 }
2076 else
2077 {
2078 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Can't find hot button\n"));
2079 }
2080 }
2081 if(wParam == VK_RETURN && m_bMenuActive)
2082 {
2083 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L);
2084 m_nNextPopBtn = -1;
2085 pT->GiveFocusBack();
2086 }
2087 }
2088 else if(wParam == VK_LEFT || wParam == VK_RIGHT)
2089 {
2090 WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT;
2091 WPARAM wpPrev = m_bLayoutRTL ? VK_RIGHT : VK_LEFT;
2092
2093 if(m_bMenuActive && !m_bContextMenu && !(wParam == wpNext && m_bPopupItem))
2094 {
2095 bool bAction = false;
2096 if(wParam == wpPrev && s_pCurrentBar->m_stackMenuWnd.GetSize() == 1)
2097 {
2098 m_nNextPopBtn = pT->GetPreviousMenuItem(m_nPopBtn);
2099 if(m_nNextPopBtn != -1)
2100 bAction = true;
2101 }
2102 else if(wParam == wpNext)
2103 {
2104 m_nNextPopBtn = pT->GetNextMenuItem(m_nPopBtn);
2105 if(m_nNextPopBtn != -1)
2106 bAction = true;
2107 }
2108 HWND hWndMenu = m_stackMenuWnd.GetCurrent();
2109 ATLASSERT(hWndMenu != NULL);
2110
2111 // Close the popup menu
2112 if(bAction)
2113 {
2114 ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L);
2115 if(wParam == wpNext)
2116 {
2117 int cItem = m_stackMenuWnd.GetSize() - 1;
2118 while(cItem >= 0)
2119 {
2120 hWndMenu = m_stackMenuWnd[cItem];
2121 if(hWndMenu != NULL)
2122 ::PostMessage(hWndMenu, WM_KEYDOWN, VK_ESCAPE, 0L);
2123 cItem--;
2124 }
2125 }
2126 #if (_WIN32_IE >= 0x0500)
2127 if(m_nNextPopBtn == -2)
2128 {
2129 m_nNextPopBtn = -1;
2130 pT->DisplayChevronMenu();
2131 }
2132 #endif // (_WIN32_IE >= 0x0500)
2133 bHandled = TRUE;
2134 }
2135 }
2136 }
2137 return 0;
2138 }
2139
2140 LRESULT OnHookNextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
2141 {
2142 #ifdef _CMDBAR_EXTRA_TRACE
2143 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_NEXTMENU\n"));
2144 #endif
2145 bHandled = FALSE;
2146 return 1;
2147 }
2148
2149 LRESULT OnHookChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
2150 {
2151 #ifdef _CMDBAR_EXTRA_TRACE
2152 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_CHAR (0x%2.2X)\n"), wParam);
2153 #endif
2154 bHandled = (wParam == VK_ESCAPE);
2155 return 0;
2156 }
2157
2158 // Implementation - ownerdraw overrideables and helpers
2159 void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
2160 {
2161 T* pT = static_cast<T*>(this);
2162 if(m_bFlatMenus)
2163 pT->DrawItemFlat(lpDrawItemStruct);
2164 else
2165 pT->DrawItem3D(lpDrawItemStruct);
2166
2167 }
2168
2169 void DrawItem3D(LPDRAWITEMSTRUCT lpDrawItemStruct)
2170 {
2171 _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
2172 CDCHandle dc = lpDrawItemStruct->hDC;
2173 const RECT& rcItem = lpDrawItemStruct->rcItem;
2174 T* pT = static_cast<T*>(this);
2175
2176 if(pmd->fType & MFT_SEPARATOR)
2177 {
2178 // draw separator
2179 RECT rc = rcItem;
2180 rc.top += (rc.bottom - rc.top) / 2; // vertical center
2181 dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line
2182 }
2183 else // not a separator
2184 {
2185 BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED;
2186 BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
2187 BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED;
2188 BOOL bHasImage = FALSE;
2189
2190 if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1)
2191 bSelected = FALSE;
2192 RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect
2193 ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically
2194
2195 int iButton = pmd->iButton;
2196 if(iButton >= 0)
2197 {
2198 bHasImage = TRUE;
2199
2200 // calc drawing point
2201 SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy };
2202 sz.cx /= 2;
2203 sz.cy /= 2;
2204 POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy };
2205
2206 // fill background depending on state
2207 if(!bChecked || (bSelected && !bDisabled))
2208 {
2209 if(!bDisabled)
2210 dc.FillRect(&rcButn, (bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU);
2211 else
2212 dc.FillRect(&rcButn, COLOR_MENU);
2213 }
2214 else
2215 {
2216 COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
2217 COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
2218 CBrush hbr(CDCHandle::GetHalftoneBrush());
2219 dc.SetBrushOrg(rcButn.left, rcButn.top);
2220 dc.FillRect(&rcButn, hbr);
2221 dc.SetTextColor(crTxt);
2222 dc.SetBkColor(crBk);
2223 }
2224
2225 // draw disabled or normal
2226 if(!bDisabled)
2227 {
2228 // draw pushed-in or popped-out edge
2229 if(bSelected || bChecked)
2230 {
2231 RECT rc2 = rcButn;
2232 dc.DrawEdge(&rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER, BF_RECT);
2233 }
2234 // draw the image
2235 ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT);
2236 }
2237 else
2238 {
2239 HBRUSH hBrushBackground = bChecked ? NULL : ::GetSysColorBrush(COLOR_MENU);
2240 pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground);
2241 }
2242 }
2243 else
2244 {
2245 // no image - look for custom checked/unchecked bitmaps
2246 CMenuItemInfo info;
2247 info.fMask = MIIM_CHECKMARKS | MIIM_TYPE;
2248 ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info);
2249 if(bChecked || info.hbmpUnchecked != NULL)
2250 {
2251 BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0);
2252 bHasImage = pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked);
2253 }
2254 }
2255
2256 // draw item text
2257 int cxButn = m_szButton.cx;
2258 COLORREF colorBG = ::GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
2259 if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT)
2260 {
2261 RECT rcBG = rcItem;
2262 if(bHasImage)
2263 rcBG.left += cxButn + s_kcxGap;
2264 dc.FillRect(&rcBG, bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
2265 }
2266
2267 // calc text rectangle and colors
2268 RECT rcText = rcItem;
2269 rcText.left += cxButn + s_kcxGap + s_kcxTextMargin;
2270 rcText.right -= cxButn;
2271 dc.SetBkMode(TRANSPARENT);
2272 COLORREF colorText = ::GetSysColor(bDisabled ? (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));
2273
2274 // font already selected by Windows
2275 if(bDisabled && (!bSelected || colorText == colorBG))
2276 {
2277 // disabled - draw shadow text shifted down and right 1 pixel (unles selected)
2278 RECT rcDisabled = rcText;
2279 ::OffsetRect(&rcDisabled, 1, 1);
2280 pT->DrawMenuText(dc, rcDisabled, pmd->lpstrText, ::GetSysColor(COLOR_3DHILIGHT));
2281 }
2282 pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally!
2283 }
2284 }
2285
2286 void DrawItemFlat(LPDRAWITEMSTRUCT lpDrawItemStruct)
2287 {
2288 _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData;
2289 CDCHandle dc = lpDrawItemStruct->hDC;
2290 const RECT& rcItem = lpDrawItemStruct->rcItem;
2291 T* pT = static_cast<T*>(this);
2292
2293 #ifndef COLOR_MENUHILIGHT
2294 const int COLOR_MENUHILIGHT = 29;
2295 #endif // !COLOR_MENUHILIGHT
2296
2297 BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED;
2298 BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
2299 BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED;
2300
2301 // paint background
2302 if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT)
2303 {
2304 if(bSelected)
2305 {
2306 dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENUHILIGHT));
2307 dc.FrameRect(&rcItem, ::GetSysColorBrush(COLOR_HIGHLIGHT));
2308 }
2309 else
2310 {
2311 dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_MENU));
2312 }
2313 }
2314
2315 if(pmd->fType & MFT_SEPARATOR)
2316 {
2317 // draw separator
2318 RECT rc = rcItem;
2319 rc.top += (rc.bottom - rc.top) / 2; // vertical center
2320 dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line
2321 }
2322 else // not a separator
2323 {
2324 if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1)
2325 bSelected = FALSE;
2326 RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m_szButton.cx, rcItem.top + m_szButton.cy }; // button rect
2327 ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) - (rcButn.bottom - rcButn.top)) / 2); // center vertically
2328
2329 // draw background and border for checked items
2330 if(bChecked)
2331 {
2332 RECT rcCheck = rcButn;
2333 ::InflateRect(&rcCheck, -1, -1);
2334 if(bSelected)
2335 dc.FillRect(&rcCheck, ::GetSysColorBrush(COLOR_MENU));
2336 dc.FrameRect(&rcCheck, ::GetSysColorBrush(COLOR_HIGHLIGHT));
2337 }
2338
2339 int iButton = pmd->iButton;
2340 if(iButton >= 0)
2341 {
2342 // calc drawing point
2343 SIZE sz = { rcButn.right - rcButn.left - m_szBitmap.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy };
2344 sz.cx /= 2;
2345 sz.cy /= 2;
2346 POINT point = { rcButn.left + sz.cx, rcButn.top + sz.cy };
2347
2348 // draw disabled or normal
2349 if(!bDisabled)
2350 {
2351 ::ImageList_Draw(m_hImageList, iButton, dc, point.x, point.y, ILD_TRANSPARENT);
2352 }
2353 else
2354 {
2355 HBRUSH hBrushBackground = ::GetSysColorBrush((bSelected && !(bDisabled && bChecked)) ? COLOR_MENUHILIGHT : COLOR_MENU);
2356 HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW);
2357 pT->DrawBitmapDisabled(dc, iButton, point, hBrushBackground, hBrushBackground, hBrushDisabledImage);
2358 }
2359 }
2360 else
2361 {
2362 // no image - look for custom checked/unchecked bitmaps
2363 CMenuItemInfo info;
2364 info.fMask = MIIM_CHECKMARKS | MIIM_TYPE;
2365 ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndItem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info);
2366 if(bChecked || info.hbmpUnchecked != NULL)
2367 {
2368 BOOL bRadio = ((info.fType & MFT_RADIOCHECK) != 0);
2369 pT->DrawCheckmark(dc, rcButn, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked);
2370 }
2371 }
2372
2373 // draw item text
2374 int cxButn = m_szButton.cx;
2375 // calc text rectangle and colors
2376 RECT rcText = rcItem;
2377 rcText.left += cxButn + s_kcxGap + s_kcxTextMargin;
2378 rcText.right -= cxButn;
2379 dc.SetBkMode(TRANSPARENT);
2380 COLORREF colorText = ::GetSysColor(bDisabled ? (bSelected ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT));
2381
2382 pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText); // finally!
2383 }
2384 }
2385
2386 void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF color)
2387 {
2388 int nTab = -1;
2389 const int nLen = lstrlen(lpstrText);
2390 for(int i = 0; i < nLen; i++)
2391 {
2392 if(lpstrText[i] == _T('\t'))
2393 {
2394 nTab = i;
2395 break;
2396 }
2397 }
2398 dc.SetTextColor(color);
2399 dc.DrawText(lpstrText, nTab, &rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX));
2400 if(nTab != -1)
2401 dc.DrawText(&lpstrText[nTab + 1], -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX));
2402 }
2403
2404 void DrawBitmapDisabled(CDCHandle& dc, int nImage, POINT point,
2405 HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE),
2406 HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT),
2407 HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW))
2408 {
2409 #if (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
2410 if(m_bAlphaImages)
2411 {
2412 IMAGELISTDRAWPARAMS ildp = { 0 };
2413 ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
2414 ildp.himl = m_hImageList;
2415 ildp.i = nImage;
2416 ildp.hdcDst = dc;
2417 ildp.x = point.x;
2418 ildp.y = point.y;
2419 ildp.cx = 0;
2420 ildp.cy = 0;
2421 ildp.xBitmap = 0;
2422 ildp.yBitmap = 0;
2423 ildp.fStyle = ILD_TRANSPARENT;
2424 ildp.fState = ILS_SATURATE;
2425 ildp.Frame = 0;
2426 ::ImageList_DrawIndirect(&ildp);
2427 }
2428 else
2429 #endif // (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
2430 {
2431 // create memory DC
2432 CDC dcMem;
2433 dcMem.CreateCompatibleDC(dc);
2434 // create mono or color bitmap
2435 CBitmap bmp;
2436 bmp.CreateCompatibleBitmap(dc, m_szBitmap.cx, m_szBitmap.cy);
2437 ATLASSERT(bmp.m_hBitmap != NULL);
2438 // draw image into memory DC--fill BG white first
2439 HBITMAP hBmpOld = dcMem.SelectBitmap(bmp);
2440 dcMem.PatBlt(0, 0, m_szBitmap.cx, m_szBitmap.cy, WHITENESS);
2441 // If white is the text color, we can't use the normal painting since
2442 // it would blend with the WHITENESS, but the mask is OK
2443 UINT uDrawStyle = (::GetSysColor(COLOR_BTNTEXT) == RGB(255, 255, 255)) ? ILD_MASK : ILD_NORMAL;
2444 ::ImageList_Draw(m_hImageList, nImage, dcMem, 0, 0, uDrawStyle);
2445 dc.DitherBlt(point.x, point.y, m_szBitmap.cx, m_szBitmap.cy, dcMem, NULL, 0, 0, hBrushBackground, hBrush3DEffect, hBrushDisabledImage);
2446 dcMem.SelectBitmap(hBmpOld); // restore
2447 }
2448 }
2449
2450 // old name
2451 BOOL Draw3DCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck)
2452 {
2453 return DrawCheckmark(dc, rc, bSelected, bDisabled, bRadio, hBmpCheck);
2454 }
2455
2456 BOOL DrawCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL bDisabled, BOOL bRadio, HBITMAP hBmpCheck)
2457 {
2458 // get checkmark bitmap, if none, use Windows standard
2459 SIZE size = { 0, 0 };
2460 CBitmapHandle bmp = hBmpCheck;
2461 if(hBmpCheck != NULL)
2462 {
2463 bmp.GetSize(size);
2464 }
2465 else
2466 {
2467 size.cx = ::GetSystemMetrics(SM_CXMENUCHECK);
2468 size.cy = ::GetSystemMetrics(SM_CYMENUCHECK);
2469 bmp.CreateCompatibleBitmap(dc, size.cx, size.cy);
2470 ATLASSERT(bmp.m_hBitmap != NULL);
2471 }
2472 // center bitmap in caller's rectangle
2473 RECT rcDest = rc;
2474 if((rc.right - rc.left) > size.cx)
2475 {
2476 rcDest.left = rc.left + (rc.right - rc.left - size.cx) / 2;
2477 rcDest.right = rcDest.left + size.cx;
2478 }
2479 if((rc.bottom - rc.top) > size.cy)
2480 {
2481 rcDest.top = rc.top + (rc.bottom - rc.top - size.cy) / 2;
2482 rcDest.bottom = rcDest.top + size.cy;
2483 }
2484 // paint background
2485 if(!m_bFlatMenus)
2486 {
2487 if(bSelected && !bDisabled)
2488 {
2489 dc.FillRect(&rcDest, COLOR_MENU);
2490 }
2491 else
2492 {
2493 COLORREF clrTextOld = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
2494 COLORREF clrBkOld = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
2495 CBrush hbr(CDCHandle::GetHalftoneBrush());
2496 dc.SetBrushOrg(rcDest.left, rcDest.top);
2497 dc.FillRect(&rcDest, hbr);
2498 dc.SetTextColor(clrTextOld);
2499 dc.SetBkColor(clrBkOld);
2500 }
2501 }
2502
2503 // create source image
2504 CDC dcSource;
2505 dcSource.CreateCompatibleDC(dc);
2506 HBITMAP hBmpOld = dcSource.SelectBitmap(bmp);
2507 // set colors
2508 const COLORREF clrBlack = RGB(0, 0, 0);
2509 const COLORREF clrWhite = RGB(255, 255, 255);
2510 COLORREF clrTextOld = dc.SetTextColor(clrBlack);
2511 COLORREF clrBkOld = dc.SetBkColor(clrWhite);
2512 // create mask
2513 CDC dcMask;
2514 dcMask.CreateCompatibleDC(dc);
2515 CBitmap bmpMask;
2516 bmpMask.CreateBitmap(size.cx, size.cy, 1, 1, NULL);
2517 HBITMAP hBmpOld1 = dcMask.SelectBitmap(bmpMask);
2518
2519 // draw the checkmark transparently
2520 int cx = rcDest.right - rcDest.left;
2521 int cy = rcDest.bottom - rcDest.top;
2522 if(hBmpCheck != NULL)
2523 {
2524 // build mask based on transparent color
2525 dcSource.SetBkColor(m_clrMask);
2526 dcMask.SetBkColor(clrBlack);
2527 dcMask.SetTextColor(clrWhite);
2528 dcMask.BitBlt(0, 0, size.cx, size.cy, dcSource, 0, 0, SRCCOPY);
2529 // draw bitmap using the mask
2530 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT);
2531 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, SRCAND);
2532 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, SRCINVERT);
2533 }
2534 else
2535 {
2536 const DWORD ROP_DSno = 0x00BB0226L;
2537 const DWORD ROP_DSa = 0x008800C6L;
2538 const DWORD ROP_DSo = 0x00EE0086L;
2539 const DWORD ROP_DSna = 0x00220326L;
2540
2541 // draw mask
2542 RECT rcSource = { 0, 0, __min(size.cx, rc.right - rc.left), __min(size.cy, rc.bottom - rc.top) };
2543 dcMask.DrawFrameControl(&rcSource, DFC_MENU, bRadio ? DFCS_MENUBULLET : DFCS_MENUCHECK);
2544
2545 // draw shadow if disabled
2546 if(!m_bFlatMenus && bDisabled)
2547 {
2548 // offset by one pixel
2549 int x = rcDest.left + 1;
2550 int y = rcDest.top + 1;
2551 // paint source bitmap
2552 const int nColor = COLOR_3DHILIGHT;
2553 dcSource.FillRect(&rcSource, nColor);
2554 // draw checkmark - special case black and white colors
2555 COLORREF clrCheck = ::GetSysColor(nColor);
2556 if(clrCheck == clrWhite)
2557 {
2558 dc.BitBlt(x, y, cx, cy, dcMask, 0, 0, ROP_DSno);
2559 dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSa);
2560 }
2561 else
2562 {
2563 if(clrCheck != clrBlack)
2564 {
2565 ATLASSERT(dcSource.GetTextColor() == clrBlack);
2566 ATLASSERT(dcSource.GetBkColor() == clrWhite);
2567 dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna);
2568 }
2569 dc.BitBlt(x, y, cx, cy, dcMask, 0, 0, ROP_DSa);
2570 dc.BitBlt(x, y, cx, cy, dcSource, 0, 0, ROP_DSo);
2571 }
2572 }
2573
2574 // paint source bitmap
2575 const int nColor = bDisabled ? COLOR_BTNSHADOW : COLOR_MENUTEXT;
2576 dcSource.FillRect(&rcSource, nColor);
2577 // draw checkmark - special case black and white colors
2578 COLORREF clrCheck = ::GetSysColor(nColor);
2579 if(clrCheck == clrWhite)
2580 {
2581 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, ROP_DSno);
2582 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSa);
2583 }
2584 else
2585 {
2586 if(clrCheck != clrBlack)
2587 {
2588 ATLASSERT(dcSource.GetTextColor() == clrBlack);
2589 ATLASSERT(dcSource.GetBkColor() == clrWhite);
2590 dcSource.BitBlt(0, 0, size.cx, size.cy, dcMask, 0, 0, ROP_DSna);
2591 }
2592 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0, ROP_DSa);
2593 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0, 0, ROP_DSo);
2594 }
2595 }
2596 // restore all
2597 dc.SetTextColor(clrTextOld);
2598 dc.SetBkColor(clrBkOld);
2599 dcSource.SelectBitmap(hBmpOld);
2600 dcMask.SelectBitmap(hBmpOld1);
2601 if(hBmpCheck == NULL)
2602 bmp.DeleteObject();
2603 // draw pushed-in hilight
2604 if(!m_bFlatMenus && !bDisabled)
2605 {
2606 if(rc.right - rc.left > size.cx)
2607 ::InflateRect(&rcDest, 1,1); // inflate checkmark by one pixel all around
2608 dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
2609 }
2610
2611 return TRUE;
2612 }
2613
2614 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
2615 {
2616 _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemData;
2617
2618 if(pmd->fType & MFT_SEPARATOR) // separator - use half system height and zero width
2619 {
2620 lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU) / 2;
2621 lpMeasureItemStruct->itemWidth = 0;
2622 }
2623 else
2624 {
2625 // compute size of text - use DrawText with DT_CALCRECT
2626 CWindowDC dc(NULL);
2627 CFont fontBold;
2628 HFONT hOldFont = NULL;
2629 if(pmd->fState & MFS_DEFAULT)
2630 {
2631 // need bold version of font
2632 LOGFONT lf = { 0 };
2633 m_fontMenu.GetLogFont(lf);
2634 lf.lfWeight += 200;
2635 fontBold.CreateFontIndirect(&lf);
2636 ATLASSERT(fontBold.m_hFont != NULL);
2637 hOldFont = dc.SelectFont(fontBold);
2638 }
2639 else
2640 {
2641 hOldFont = dc.SelectFont(m_fontMenu);
2642 }
2643
2644 RECT rcText = { 0 };
2645 dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
2646 int cx = rcText.right - rcText.left;
2647 dc.SelectFont(hOldFont);
2648
2649 LOGFONT lf = { 0 };
2650 m_fontMenu.GetLogFont(lf);
2651 int cy = lf.lfHeight;
2652 if(cy < 0)
2653 cy = -cy;
2654 const int cyMargin = 8;
2655 cy += cyMargin;
2656
2657 // height of item is the bigger of these two
2658 lpMeasureItemStruct->itemHeight = __max(cy, (int)m_szButton.cy);
2659
2660 // width is width of text plus a bunch of stuff
2661 cx += 2 * s_kcxTextMargin; // L/R margin for readability
2662 cx += s_kcxGap; // space between button and menu text
2663 cx += 2 * m_szButton.cx; // button width (L=button; R=empty margin)
2664 cx += m_cxExtraSpacing; // extra between item text and accelerator keys
2665
2666 // Windows adds 1 to returned value
2667 cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1;
2668 lpMeasureItemStruct->itemWidth = cx; // done deal
2669 }
2670 }
2671
2672 // Implementation - Hook procs
2673 static LRESULT CALLBACK CreateHookProc(int nCode, WPARAM wParam, LPARAM lParam)
2674 {
2675 const int cchClassName = 7;
2676 TCHAR szClassName[cchClassName] = { 0 };
2677
2678 if(nCode == HCBT_CREATEWND)
2679 {
2680 HWND hWndMenu = (HWND)wParam;
2681 #ifdef _CMDBAR_EXTRA_TRACE
2682 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_CREATEWND (HWND = %8.8X)\n"), hWndMenu);
2683 #endif
2684
2685 ::GetClassName(hWndMenu, szClassName, cchClassName);
2686 if(!lstrcmp(_T("#32768"), szClassName))
2687 s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu);
2688 }
2689 else if(nCode == HCBT_DESTROYWND)
2690 {
2691 HWND hWndMenu = (HWND)wParam;
2692 #ifdef _CMDBAR_EXTRA_TRACE
2693 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_DESTROYWND (HWND = %8.8X)\n"), hWndMenu);
2694 #endif
2695
2696 ::GetClassName(hWndMenu, szClassName, cchClassName);
2697 if(!lstrcmp(_T("#32768"), szClassName))
2698 {
2699 ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenuWnd.GetCurrent());
2700 s_pCurrentBar->m_stackMenuWnd.Pop();
2701 }
2702 }
2703
2704 return ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam);
2705 }
2706
2707 static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
2708 {
2709 LPMSG pMsg = (LPMSG)lParam;
2710
2711 if(nCode == HC_ACTION && wParam == PM_REMOVE && pMsg->message != GetGetBarMessage() && pMsg->message != WM_FORWARDMSG)
2712 {
2713 CCommandBarCtrlBase* pCmdBar = NULL;
2714 HWND hWnd = pMsg->hwnd;
2715 DWORD dwPID = 0;
2716 while(pCmdBar == NULL && hWnd != NULL)
2717 {
2718 pCmdBar = (CCommandBarCtrlBase*)::SendMessage(hWnd, GetGetBarMessage(), (WPARAM)&dwPID, 0L);
2719 hWnd = ::GetParent(hWnd);
2720 }
2721
2722 if(pCmdBar != NULL && dwPID == GetCurrentProcessId())
2723 {
2724 pCmdBar->m_hWndHook = pMsg->hwnd;
2725 ATLASSERT(pCmdBar->IsCommandBarBase());
2726
2727 if(::IsWindow(pCmdBar->m_hWnd))
2728 pCmdBar->SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
2729 else
2730 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook skipping message, can't find command bar!\n"));
2731 }
2732 }
2733
2734 LRESULT lRet = 0;
2735 ATLASSERT(s_pmapMsgHook != NULL);
2736 if(s_pmapMsgHook != NULL)
2737 {
2738 DWORD dwThreadID = ::GetCurrentThreadId();
2739 _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID);
2740 if(pData != NULL)
2741 {
2742 lRet = ::CallNextHookEx(pData->hMsgHook, nCode, wParam, lParam);
2743 }
2744 }
2745 return lRet;
2746 }
2747
2748 // Implementation
2749 void DoPopupMenu(int nIndex, bool bAnimate)
2750 {
2751 #ifdef _CMDBAR_EXTRA_TRACE
2752 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - DoPopupMenu, bAnimate = %s\n"), bAnimate ? "true" : "false");
2753 #endif
2754
2755 // Menu animation flags
2756 #ifndef TPM_VERPOSANIMATION
2757 const UINT TPM_VERPOSANIMATION = 0x1000L;
2758 #endif
2759 #ifndef TPM_NOANIMATION
2760 const UINT TPM_NOANIMATION = 0x4000L;
2761 #endif
2762 T* pT = static_cast<T*>(this);
2763
2764 // get popup menu and it's position
2765 RECT rect = { 0 };
2766 GetItemRect(nIndex, &rect);
2767 POINT pt = { rect.left, rect.bottom };
2768 MapWindowPoints(NULL, &pt, 1);
2769 MapWindowPoints(NULL, &rect);
2770 TPMPARAMS TPMParams = { 0 };
2771 TPMParams.cbSize = sizeof(TPMPARAMS);
2772 TPMParams.rcExclude = rect;
2773 HMENU hMenuPopup = ::GetSubMenu(m_hMenu, nIndex);
2774 ATLASSERT(hMenuPopup != NULL);
2775
2776 // get button ID
2777 TBBUTTON tbb = { 0 };
2778 GetButton(nIndex, &tbb);
2779 int nCmdID = tbb.idCommand;
2780
2781 m_nPopBtn = nIndex; // remember current button's index
2782
2783 // press button and display popup menu
2784 PressButton(nCmdID, TRUE);
2785 SetHotItem(nCmdID);
2786 pT->DoTrackPopupMenu(hMenuPopup, TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN |
2787 (s_bW2K ? (bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMATION) : 0), pt.x, pt.y, &TPMParams);
2788 PressButton(nCmdID, FALSE);
2789 if(::GetFocus() != m_hWnd)
2790 SetHotItem(-1);
2791
2792 m_nPopBtn = -1; // restore
2793
2794 // eat next message if click is on the same button
2795 MSG msg = { 0 };
2796 if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rect, msg.pt))
2797 ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
2798
2799 // check if another popup menu should be displayed
2800 if(m_nNextPopBtn != -1)
2801 {
2802 PostMessage(GetAutoPopupMessage(), m_nNextPopBtn & 0xFFFF);
2803 if(!(m_nNextPopBtn & 0xFFFF0000) && !m_bPopupItem)
2804 PostMessage(WM_KEYDOWN, VK_DOWN, 0);
2805 m_nNextPopBtn = -1;
2806 }
2807 else
2808 {
2809 m_bContextMenu = false;
2810 // If user didn't hit escape, give focus back
2811 if(!m_bEscapePressed)
2812 {
2813 if(m_bUseKeyboardCues && m_bShowKeyboardCues)
2814 m_bAllowKeyboardCues = false;
2815 pT->GiveFocusBack();
2816 }
2817 else
2818 {
2819 SetHotItem(nCmdID);
2820 SetAnchorHighlight(TRUE);
2821 }
2822 }
2823 }
2824
2825 BOOL DoTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS lpParams = NULL)
2826 {
2827 CMenuHandle menuPopup = hMenu;
2828
2829 CWindowCreateCriticalSectionLock lock;
2830 if(FAILED(lock.Lock()))
2831 {
2832 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::DoTrackPopupMenu.\n"));
2833 ATLASSERT(FALSE);
2834 return FALSE;
2835 }
2836
2837 ATLASSERT(s_hCreateHook == NULL);
2838
2839 s_pCurrentBar = static_cast<CCommandBarCtrlBase*>(this);
2840
2841 s_hCreateHook = ::SetWindowsHookEx(WH_CBT, CreateHookProc, ModuleHelper::GetModuleInstance(), GetCurrentThreadId());
2842 ATLASSERT(s_hCreateHook != NULL);
2843
2844 m_bPopupItem = false;
2845 m_bMenuActive = true;
2846
2847 BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd, lpParams);
2848 m_bMenuActive = false;
2849
2850 ::UnhookWindowsHookEx(s_hCreateHook);
2851
2852 s_hCreateHook = NULL;
2853 s_pCurrentBar = NULL;
2854
2855 lock.Unlock();
2856
2857 // cleanup - convert menus back to original state
2858 #ifdef _CMDBAR_EXTRA_TRACE
2859 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - TrackPopupMenu - cleanup\n"));
2860 #endif
2861
2862 ATLASSERT(m_stackMenuWnd.GetSize() == 0);
2863
2864 UpdateWindow();
2865 ATL::CWindow wndTL = GetTopLevelParent();
2866 wndTL.UpdateWindow();
2867
2868 // restore the menu items to the previous state for all menus that were converted
2869 if(m_bImagesVisible)
2870 {
2871 HMENU hMenuSav = NULL;
2872 while((hMenuSav = m_stackMenuHandle.Pop()) != NULL)
2873 {
2874 menuPopup = hMenuSav;
2875 BOOL bRet = FALSE;
2876 // restore state and delete menu item data
2877 for(int i = 0; i < menuPopup.GetMenuItemCount(); i++)
2878 {
2879 CMenuItemInfo mii;
2880 mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID;
2881 bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii);
2882 ATLASSERT(bRet);
2883
2884 _MenuItemData* pMI = (_MenuItemData*)mii.dwItemData;
2885 if(pMI != NULL && pMI->IsCmdBarMenuItem())
2886 {
2887 mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE;
2888 mii.fType = pMI->fType;
2889 mii.fState = pMI->fState;
2890 mii.dwTypeData = pMI->lpstrText;
2891 mii.cch = lstrlen(pMI->lpstrText);
2892 mii.dwItemData = NULL;
2893
2894 bRet = menuPopup.SetMenuItemInfo(i, TRUE, &mii);
2895 // this one triggers WM_MEASUREITEM
2896 menuPopup.ModifyMenu(i, MF_BYPOSITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText);
2897 ATLASSERT(bRet);
2898
2899 delete [] pMI->lpstrText;
2900 delete pMI;
2901 }
2902 }
2903 }
2904 }
2905 return bTrackRet;
2906 }
2907
2908 int GetPreviousMenuItem(int nBtn) const
2909 {
2910 if(nBtn == -1)
2911 return -1;
2912 #if (_WIN32_IE >= 0x0500)
2913 RECT rcClient = { 0 };
2914 GetClientRect(&rcClient);
2915 #endif // (_WIN32_IE >= 0x0500)
2916 int nNextBtn;
2917 for(nNextBtn = nBtn - 1; nNextBtn != nBtn; nNextBtn--)
2918 {
2919 if(nNextBtn < 0)
2920 nNextBtn = ::GetMenuItemCount(m_hMenu) - 1;
2921 TBBUTTON tbb = { 0 };
2922 GetButton(nNextBtn, &tbb);
2923 #if (_WIN32_IE >= 0x0500)
2924 RECT rcBtn = { 0 };
2925 GetItemRect(nNextBtn, &rcBtn);
2926 if(rcBtn.right > rcClient.right)
2927 {
2928 nNextBtn = -2; // chevron
2929 break;
2930 }
2931 #endif // (_WIN32_IE >= 0x0500)
2932 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0)
2933 break;
2934 }
2935 return (nNextBtn != nBtn) ? nNextBtn : -1;
2936 }
2937
2938 int GetNextMenuItem(int nBtn) const
2939 {
2940 if(nBtn == -1)
2941 return -1;
2942 #if (_WIN32_IE >= 0x0500)
2943 RECT rcClient = { 0 };
2944 GetClientRect(&rcClient);
2945 #endif // (_WIN32_IE >= 0x0500)
2946 int nNextBtn = 0;
2947 int nCount = ::GetMenuItemCount(m_hMenu);
2948 for(nNextBtn = nBtn + 1; nNextBtn != nBtn; nNextBtn++)
2949 {
2950 if(nNextBtn >= nCount)
2951 nNextBtn = 0;
2952 TBBUTTON tbb = { 0 };
2953 GetButton(nNextBtn, &tbb);
2954 #if (_WIN32_IE >= 0x0500)
2955 RECT rcBtn = { 0 };
2956 GetItemRect(nNextBtn, &rcBtn);
2957 if(rcBtn.right > rcClient.right)
2958 {
2959 nNextBtn = -2; // chevron
2960 break;
2961 }
2962 #endif // (_WIN32_IE >= 0x0500)
2963 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState & TBSTATE_HIDDEN) == 0)
2964 break;
2965 }
2966 return (nNextBtn != nBtn) ? nNextBtn : -1;
2967 }
2968
2969 #if (_WIN32_IE >= 0x0500)
2970 bool DisplayChevronMenu()
2971 {
2972 // assume we are in a rebar
2973 HWND hWndReBar = GetParent();
2974 int nCount = (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
2975 bool bRet = false;
2976 for(int i = 0; i < nCount; i++)
2977 {
2978 REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_STYLE };
2979 BOOL bRetBandInfo = (BOOL)::SendMessage(hWndReBar, RB_GETBANDINFO, i, (LPARAM)&rbbi);
2980 if(bRetBandInfo && rbbi.hwndChild == m_hWnd)
2981 {
2982 if((rbbi.fStyle & RBBS_USECHEVRON) != 0)
2983 {
2984 ::PostMessage(hWndReBar, RB_PUSHCHEVRON, i, 0L);
2985 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
2986 bRet = true;
2987 }
2988 break;
2989 }
2990 }
2991 return bRet;
2992 }
2993 #endif // (_WIN32_IE >= 0x0500)
2994
2995 void GetSystemSettings()
2996 {
2997 // refresh our font
2998 NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
2999 BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
3000 ATLASSERT(bRet);
3001 if(bRet)
3002 {
3003 LOGFONT logfont = { 0 };
3004 if(m_fontMenu.m_hFont != NULL)
3005 m_fontMenu.GetLogFont(logfont);
3006 if(logfont.lfHeight != info.lfMenuFont.lfHeight ||
3007 logfont.lfWidth != info.lfMenuFont.lfWidth ||
3008 logfont.lfEscapement != info.lfMenuFont.lfEscapement ||
3009 logfont.lfOrientation != info.lfMenuFont.lfOrientation ||
3010 logfont.lfWeight != info.lfMenuFont.lfWeight ||
3011 logfont.lfItalic != info.lfMenuFont.lfItalic ||
3012 logfont.lfUnderline != info.lfMenuFont.lfUnderline ||
3013 logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut ||
3014 logfont.lfCharSet != info.lfMenuFont.lfCharSet ||
3015 logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecision ||
3016 logfont.lfClipPrecision != info.lfMenuFont.lfClipPrecision ||
3017 logfont.lfQuality != info.lfMenuFont.lfQuality ||
3018 logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAndFamily ||
3019 lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceName) != 0)
3020 {
3021 HFONT hFontMenu = ::CreateFontIndirect(&info.lfMenuFont);
3022 ATLASSERT(hFontMenu != NULL);
3023 if(hFontMenu != NULL)
3024 {
3025 if(m_fontMenu.m_hFont != NULL)
3026 m_fontMenu.DeleteObject();
3027 m_fontMenu.Attach(hFontMenu);
3028 SetFont(m_fontMenu);
3029 AddStrings(_T("NS\0")); // for proper item height
3030 AutoSize();
3031 }
3032 }
3033 }
3034
3035 // check if we need extra spacing for menu item text
3036 CWindowDC dc(m_hWnd);
3037 HFONT hFontOld = dc.SelectFont(m_fontMenu);
3038 RECT rcText = { 0 };
3039 dc.DrawText(_T("\t"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
3040 if((rcText.right - rcText.left) < 4)
3041 {
3042 ::SetRectEmpty(&rcText);
3043 dc.DrawText(_T("x"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
3044 m_cxExtraSpacing = rcText.right - rcText.left;
3045 }
3046 else
3047 {
3048 m_cxExtraSpacing = 0;
3049 }
3050 dc.SelectFont(hFontOld);
3051
3052 // get Windows version
3053 #ifndef _versionhelpers_H_INCLUDED_
3054 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
3055 ::GetVersionEx(&ovi);
3056 #endif // !_versionhelpers_H_INCLUDED_
3057
3058 // query keyboard cues mode (Windows 2000 or later)
3059 #ifdef _versionhelpers_H_INCLUDED_
3060 if(::IsWindowsVersionOrGreater(5, 0, 0))
3061 #else // !_versionhelpers_H_INCLUDED_
3062 if (ovi.dwMajorVersion >= 5)
3063 #endif // _versionhelpers_H_INCLUDED_
3064 {
3065 #ifndef SPI_GETKEYBOARDCUES
3066 const UINT SPI_GETKEYBOARDCUES = 0x100A;
3067 #endif // !SPI_GETKEYBOARDCUES
3068 BOOL bRetVal = TRUE;
3069 bRet = ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &bRetVal, 0);
3070 m_bUseKeyboardCues = (bRet && !bRetVal);
3071 m_bAllowKeyboardCues = true;
3072 ShowKeyboardCues(!m_bUseKeyboardCues);
3073 }
3074
3075 // query flat menu mode (Windows XP or later)
3076 #ifdef _versionhelpers_H_INCLUDED_
3077 if(::IsWindowsXPOrGreater())
3078 #else // !_versionhelpers_H_INCLUDED_
3079 if ((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5))
3080 #endif // _versionhelpers_H_INCLUDED_
3081 {
3082 #ifndef SPI_GETFLATMENU
3083 const UINT SPI_GETFLATMENU = 0x1022;
3084 #endif // !SPI_GETFLATMENU
3085 BOOL bRetVal = FALSE;
3086 bRet = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &bRetVal, 0);
3087 m_bFlatMenus = (bRet && bRetVal);
3088 }
3089
3090 #if _WTL_CMDBAR_VISTA_MENUS
3091 // check if we should use Vista menus
3092 bool bVistaMenus = (((m_dwExtendedStyle & CBR_EX_NOVISTAMENUS) == 0) && RunTimeHelper::IsVista() && RunTimeHelper::IsThemeAvailable());
3093 if(!bVistaMenus && m_bVistaMenus && (m_hMenu != NULL) && (m_arrCommand.GetSize() > 0))
3094 {
3095 T* pT = static_cast<T*>(this);
3096 pT->_RemoveVistaBitmapsFromMenu();
3097 }
3098
3099 m_bVistaMenus = bVistaMenus;
3100 #endif // _WTL_CMDBAR_VISTA_MENUS
3101
3102 #ifdef _CMDBAR_EXTRA_TRACE
3103 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - GetSystemSettings:\n m_bFlatMenus = %s\n m_bUseKeyboardCues = %s m_bVistaMenus = %s\n"),
3104 m_bFlatMenus ? "true" : "false", m_bUseKeyboardCues ? "true" : "false", m_bVistaMenus ? "true" : "false");
3105 #endif
3106 }
3107
3108 // Implementation - alternate focus mode support
3109 void TakeFocus()
3110 {
3111 if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_hWndFocus == NULL)
3112 m_hWndFocus = ::GetFocus();
3113 SetFocus();
3114 }
3115
3116 void GiveFocusBack()
3117 {
3118 if(m_bParentActive)
3119 {
3120 if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && ::IsWindow(m_hWndFocus))
3121 ::SetFocus(m_hWndFocus);
3122 else if(!(m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_wndParent.IsWindow())
3123 m_wndParent.SetFocus();
3124 }
3125 m_hWndFocus = NULL;
3126 SetAnchorHighlight(FALSE);
3127 if(m_bUseKeyboardCues && m_bShowKeyboardCues)
3128 ShowKeyboardCues(false);
3129 m_bSkipPostDown = false;
3130 }
3131
3132 void ShowKeyboardCues(bool bShow)
3133 {
3134 m_bShowKeyboardCues = bShow;
3135 SetDrawTextFlags(DT_HIDEPREFIX, m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX);
3136 Invalidate();
3137 UpdateWindow();
3138 }
3139
3140 // Implementation - internal message helpers
3141 static UINT GetAutoPopupMessage()
3142 {
3143 static UINT uAutoPopupMessage = 0;
3144 if(uAutoPopupMessage == 0)
3145 {
3146 CStaticDataInitCriticalSectionLock lock;
3147 if(FAILED(lock.Lock()))
3148 {
3149 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetAutoPopupMessage.\n"));
3150 ATLASSERT(FALSE);
3151 return 0;
3152 }
3153
3154 if(uAutoPopupMessage == 0)
3155 uAutoPopupMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalAutoPopupMsg"));
3156
3157 lock.Unlock();
3158 }
3159 ATLASSERT(uAutoPopupMessage != 0);
3160 return uAutoPopupMessage;
3161 }
3162
3163 static UINT GetGetBarMessage()
3164 {
3165 static UINT uGetBarMessage = 0;
3166 if(uGetBarMessage == 0)
3167 {
3168 CStaticDataInitCriticalSectionLock lock;
3169 if(FAILED(lock.Lock()))
3170 {
3171 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CCommandBarCtrlImpl::GetGetBarMessage.\n"));
3172 ATLASSERT(FALSE);
3173 return 0;
3174 }
3175
3176 if(uGetBarMessage == 0)
3177 uGetBarMessage = ::RegisterWindowMessage(_T("WTL_CmdBar_InternalGetBarMsg"));
3178
3179 lock.Unlock();
3180 }
3181 ATLASSERT(uGetBarMessage != 0);
3182 return uGetBarMessage;
3183 }
3184
3185 // Implementation
3186 bool CreateInternalImageList(int cImages)
3187 {
3188 UINT uFlags = (m_bAlphaImages ? ILC_COLOR32 : ILC_COLOR24) | ILC_MASK;
3189 m_hImageList = ::ImageList_Create(m_szBitmap.cx, m_szBitmap.cy, uFlags, cImages, 1);
3190 ATLASSERT(m_hImageList != NULL);
3191 return (m_hImageList != NULL);
3192 }
3193
3194 // Implementation - support for Vista menus
3195 #if _WTL_CMDBAR_VISTA_MENUS
3196 void _AddVistaBitmapsFromImageList(int nStartIndex, int nCount)
3197 {
3198 // Create display compatible memory DC
3199 CClientDC dc(NULL);
3200 CDC dcMem;
3201 dcMem.CreateCompatibleDC(dc);
3202 HBITMAP hBitmapSave = dcMem.GetCurrentBitmap();
3203
3204 T* pT = static_cast<T*>(this);
3205 // Create bitmaps for all menu items
3206 for(int i = 0; i < nCount; i++)
3207 {
3208 HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nStartIndex + i, dc, dcMem);
3209 dcMem.SelectBitmap(hBitmapSave);
3210 m_arrVistaBitmap.Add(hBitmap);
3211 }
3212 }
3213
3214 void _AddVistaBitmapFromImageList(int nIndex)
3215 {
3216 // Create display compatible memory DC
3217 CClientDC dc(NULL);
3218 CDC dcMem;
3219 dcMem.CreateCompatibleDC(dc);
3220 HBITMAP hBitmapSave = dcMem.GetCurrentBitmap();
3221
3222 // Create bitmap for menu item
3223 T* pT = static_cast<T*>(this);
3224 HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, dc, dcMem);
3225
3226 // Select saved bitmap back and add bitmap to the array
3227 dcMem.SelectBitmap(hBitmapSave);
3228 m_arrVistaBitmap.Add(hBitmap);
3229 }
3230
3231 void _ReplaceVistaBitmapFromImageList(int nIndex)
3232 {
3233 // Delete existing bitmap
3234 if(m_arrVistaBitmap[nIndex] != NULL)
3235 ::DeleteObject(m_arrVistaBitmap[nIndex]);
3236
3237 // Create display compatible memory DC
3238 CClientDC dc(NULL);
3239 CDC dcMem;
3240 dcMem.CreateCompatibleDC(dc);
3241 HBITMAP hBitmapSave = dcMem.GetCurrentBitmap();
3242
3243 // Create bitmap for menu item
3244 T* pT = static_cast<T*>(this);
3245 HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, dc, dcMem);
3246
3247 // Select saved bitmap back and replace bitmap in the array
3248 dcMem.SelectBitmap(hBitmapSave);
3249 m_arrVistaBitmap.SetAtIndex(nIndex, hBitmap);
3250 }
3251
3252 HBITMAP _CreateVistaBitmapHelper(int nIndex, HDC hDCSource, HDC hDCTarget)
3253 {
3254 // Create 32-bit bitmap
3255 BITMAPINFO bi = { 0 };
3256 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
3257 bi.bmiHeader.biWidth = m_szBitmap.cx;
3258 bi.bmiHeader.biHeight = m_szBitmap.cy;
3259 bi.bmiHeader.biPlanes = 1;
3260 bi.bmiHeader.biBitCount = 32;
3261 bi.bmiHeader.biCompression = BI_RGB;
3262 bi.bmiHeader.biSizeImage = 0;
3263 bi.bmiHeader.biXPelsPerMeter = 0;
3264 bi.bmiHeader.biYPelsPerMeter = 0;
3265 bi.bmiHeader.biClrUsed = 0;
3266 bi.bmiHeader.biClrImportant = 0;
3267 HBITMAP hBitmap = ::CreateDIBSection(hDCSource, &bi, DIB_RGB_COLORS, NULL, NULL, 0);
3268 ATLASSERT(hBitmap != NULL);
3269
3270 // Select bitmap into target DC and draw from image list to it
3271 if(hBitmap != NULL)
3272 {
3273 ::SelectObject(hDCTarget, hBitmap);
3274
3275 IMAGELISTDRAWPARAMS ildp = { 0 };
3276 ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
3277 ildp.himl = m_hImageList;
3278 ildp.i = nIndex;
3279 ildp.hdcDst = hDCTarget;
3280 ildp.x = 0;
3281 ildp.y = 0;
3282 ildp.cx = 0;
3283 ildp.cy = 0;
3284 ildp.xBitmap = 0;
3285 ildp.yBitmap = 0;
3286 ildp.fStyle = ILD_TRANSPARENT;
3287 ildp.fState = ILS_ALPHA;
3288 ildp.Frame = 255;
3289 ::ImageList_DrawIndirect(&ildp);
3290 }
3291
3292 return hBitmap;
3293 }
3294
3295 void _RemoveVistaBitmapsFromMenu()
3296 {
3297 CMenuHandle menu = m_hMenu;
3298 for(int i = 0; i < m_arrCommand.GetSize(); i++)
3299 {
3300 CMenuItemInfo mii;
3301 mii.fMask = MIIM_BITMAP;
3302 mii.hbmpItem = NULL;
3303 menu.SetMenuItemInfo(m_arrCommand[i], FALSE, &mii);
3304 }
3305 }
3306 #endif // _WTL_CMDBAR_VISTA_MENUS
3307 };
3308
3309
3310 class CCommandBarCtrl : public CCommandBarCtrlImpl<CCommandBarCtrl>
3311 {
3312 public:
3313 DECLARE_WND_SUPERCLASS(_T("WTL_CommandBar"), GetWndClassName())
3314 };
3315
3316
3317 ///////////////////////////////////////////////////////////////////////////////
3318 // CMDICommandBarCtrl - ATL implementation of Command Bars for MDI apps
3319
3320 template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = ATL::CControlWinTraits>
3321 class ATL_NO_VTABLE CMDICommandBarCtrlImpl : public CCommandBarCtrlImpl< T, TBase, TWinTraits>
3322 {
3323 public:
3324 // Data members
3325 ATL::CContainedWindow m_wndMDIClient;
3326 bool m_bChildMaximized;
3327 HWND m_hWndChildMaximized;
3328 HICON m_hIconChildMaximized;
3329 int m_nBtnPressed;
3330 int m_nBtnWasPressed;
3331
3332 int m_cxyOffset; // offset between nonclient elements
3333 int m_cxIconWidth; // small icon width
3334 int m_cyIconHeight; // small icon height
3335 int m_cxBtnWidth; // nonclient button width
3336 int m_cyBtnHeight; // nonclient button height
3337 int m_cxLeft; // left nonclient area width
3338 int m_cxRight; // right nonclient area width
3339
3340 // Theme declarations and data members
3341 #ifndef _WTL_NO_AUTO_THEME
3342 #ifndef _UXTHEME_H_
3343 typedef HANDLE HTHEME;
3344 #endif // !_UXTHEME_H_
3345 typedef HTHEME (STDAPICALLTYPE *PFN_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
3346 typedef HRESULT (STDAPICALLTYPE *PFN_CloseThemeData)(HTHEME hTheme);
3347 typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect);
3348 typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeParentBackground)(HWND hwnd, HDC hdc, OPTIONAL RECT* prc);
3349
3350 HMODULE m_hThemeDLL;
3351 HTHEME m_hTheme;
3352 PFN_DrawThemeBackground m_pfnDrawThemeBackground;
3353 PFN_DrawThemeParentBackground m_pfnDrawThemeParentBackground;
3354 #endif // !_WTL_NO_AUTO_THEME
3355
3356 // Constructor/destructor
3357 CMDICommandBarCtrlImpl() :
3358 m_wndMDIClient(this, 2), m_bChildMaximized(false),
3359 m_hWndChildMaximized(NULL), m_hIconChildMaximized(NULL),
3360 m_nBtnPressed(-1), m_nBtnWasPressed(-1),
3361 #ifndef _WTL_NO_AUTO_THEME
3362 m_hThemeDLL(NULL), m_hTheme(NULL), m_pfnDrawThemeBackground(NULL), m_pfnDrawThemeParentBackground(NULL),
3363 #endif // !_WTL_NO_AUTO_THEME
3364 m_cxyOffset(2),
3365 m_cxIconWidth(16), m_cyIconHeight(16),
3366 m_cxBtnWidth(16), m_cyBtnHeight(14),
3367 m_cxLeft(20), m_cxRight(55)
3368 { }
3369
3370 ~CMDICommandBarCtrlImpl()
3371 {
3372 if(m_wndMDIClient.IsWindow())
3373 /*scary!*/ m_wndMDIClient.UnsubclassWindow();
3374 }
3375
3376 // Operations
3377 BOOL SetMDIClient(HWND hWndMDIClient)
3378 {
3379 ATLASSERT(::IsWindow(m_hWnd));
3380 ATLASSERT(::IsWindow(hWndMDIClient));
3381 if(!::IsWindow(hWndMDIClient))
3382 return FALSE;
3383
3384 #ifdef _DEBUG
3385 // BLOCK: Test if the passed window is MDICLIENT
3386 {
3387 LPCTSTR lpszMDIClientClass = _T("MDICLIENT");
3388 const int nNameLen = 9 + 1; // "MDICLIENT" + NULL
3389 TCHAR szClassName[nNameLen] = { 0 };
3390 ::GetClassName(hWndMDIClient, szClassName, nNameLen);
3391 ATLASSERT(lstrcmpi(szClassName, lpszMDIClientClass) == 0);
3392 }
3393 #endif // _DEBUG
3394
3395 if(m_wndMDIClient.IsWindow())
3396 /*scary!*/ m_wndMDIClient.UnsubclassWindow();
3397
3398 return m_wndMDIClient.SubclassWindow(hWndMDIClient);
3399 }
3400
3401 // Message maps
3402 typedef CCommandBarCtrlImpl< T, TBase, TWinTraits > _baseClass;
3403 BEGIN_MSG_MAP(CMDICommandBarCtrlImpl)
3404 MESSAGE_HANDLER(WM_CREATE, OnCreate)
3405 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
3406 #ifndef _WTL_NO_AUTO_THEME
3407 MESSAGE_HANDLER(_GetThemeChangedMsg(), OnThemeChanged)
3408 #endif // !_WTL_NO_AUTO_THEME
3409 MESSAGE_HANDLER(WM_SIZE, OnSize)
3410 MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
3411 MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
3412 MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
3413 MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
3414 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
3415 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
3416 MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk)
3417 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
3418 CHAIN_MSG_MAP(_baseClass)
3419 ALT_MSG_MAP(1) // Parent window messages
3420 MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate)
3421 CHAIN_MSG_MAP_ALT(_baseClass, 1)
3422 ALT_MSG_MAP(2) // MDI client window messages
3423 MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
3424 // no chaining needed since this was moved from the base class here
3425 ALT_MSG_MAP(3) // Message hook messages
3426 MESSAGE_RANGE_HANDLER(0, 0xFFFF, OnAllHookMessages)
3427 CHAIN_MSG_MAP_ALT(_baseClass, 3)
3428 END_MSG_MAP()
3429
3430 // Additional MDI message handlers
3431 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
3432 {
3433 LRESULT lRet = _baseClass::OnCreate(uMsg, wParam, lParam, bHandled);
3434 if(lRet == (LRESULT)-1)
3435 return lRet;
3436
3437 #ifndef _WTL_NO_AUTO_THEME
3438 // this will fail if theming is not supported
3439 m_hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
3440 if(m_hThemeDLL != NULL)
3441 {
3442 m_pfnDrawThemeBackground = (PFN_DrawThemeBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeBackground");
3443 ATLASSERT(m_pfnDrawThemeBackground != NULL);
3444 if(m_pfnDrawThemeBackground != NULL)
3445 {
3446 T* pT = static_cast<T*>(this);
3447 pT->_OpenThemeData();
3448 }
3449 else
3450 {
3451 ::FreeLibrary(m_hThemeDLL);
3452 m_hThemeDLL = NULL;
3453 }
3454 m_pfnDrawThemeParentBackground = (PFN_DrawThemeParentBackground)::GetProcAddress(m_hThemeDLL, "DrawThemeParentBackground");
3455 ATLASSERT(m_pfnDrawThemeParentBackground != NULL);
3456 }
3457 #endif // !_WTL_NO_AUTO_THEME
3458
3459 return lRet;
3460 }
3461
3462 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
3463 {
3464 LRESULT lRet = _baseClass::OnDestroy(uMsg, wParam, lParam, bHandled);
3465
3466 #ifndef _WTL_NO_AUTO_THEME
3467 if(m_hThemeDLL != NULL)
3468 {
3469 T* pT = static_cast<T*>(this);
3470 pT->_CloseThemeData();
3471 ::FreeLibrary(m_hThemeDLL);
3472 m_hThemeDLL = NULL;
3473 }
3474 #endif // !_WTL_NO_AUTO_THEME
3475
3476 return lRet;
3477 }
3478
3479 #ifndef _WTL_NO_AUTO_THEME
3480 LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
3481 {
3482 if(m_hThemeDLL != NULL)
3483 {
3484 T* pT = static_cast<T*>(this);
3485 pT->_CloseThemeData();
3486 pT->_OpenThemeData();
3487 }
3488 return 0;
3489 }
3490 #endif // !_WTL_NO_AUTO_THEME
3491
3492 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3493 {
3494 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
3495 T* pT = static_cast<T*>(this);
3496 pT->_AdjustBtnSize(GET_Y_LPARAM(lParam));
3497 return lRet;
3498 }
3499
3500 LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3501 {
3502 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
3503
3504 if(m_bChildMaximized && (BOOL)wParam)
3505 {
3506 LPNCCALCSIZE_PARAMS lpParams = (LPNCCALCSIZE_PARAMS)lParam;
3507 if(m_bLayoutRTL)
3508 {
3509 lpParams->rgrc[0].left += m_cxRight;
3510 lpParams->rgrc[0].right -= m_cxLeft;
3511 }
3512 else
3513 {
3514 lpParams->rgrc[0].left += m_cxLeft;
3515 lpParams->rgrc[0].right -= m_cxRight;
3516 }
3517 }
3518
3519 return lRet;
3520 }
3521
3522 LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3523 {
3524 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
3525
3526 if(!m_bChildMaximized)
3527 return lRet;
3528
3529 ATLASSERT(m_hWndChildMaximized != NULL && m_hIconChildMaximized != NULL);
3530
3531 // get DC and window rectangle
3532 CWindowDC dc(m_hWnd);
3533 RECT rect = { 0 };
3534 GetWindowRect(&rect);
3535 int cxWidth = rect.right - rect.left;
3536 int cyHeight = rect.bottom - rect.top;
3537
3538 // paint left side nonclient background and draw icon
3539 ::SetRect(&rect, 0, 0, m_cxLeft, cyHeight);
3540 #ifndef _WTL_NO_AUTO_THEME
3541 if(m_hTheme != NULL)
3542 {
3543 if(m_pfnDrawThemeParentBackground != NULL)
3544 m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect);
3545 else
3546 dc.FillRect(&rect, COLOR_WINDOW);
3547 }
3548 else
3549 #endif // !_WTL_NO_AUTO_THEME
3550 {
3551 if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0)
3552 dc.FillRect(&rect, COLOR_3DFACE);
3553 else
3554 dc.FillRect(&rect, COLOR_MENU);
3555 }
3556
3557 RECT rcIcon = { 0 };
3558 T* pT = static_cast<T*>(this);
3559 pT->_CalcIconRect(cxWidth, cyHeight, rcIcon);
3560 dc.DrawIconEx(rcIcon.left, rcIcon.top, m_hIconChildMaximized, m_cxIconWidth, m_cyIconHeight);
3561
3562 // paint right side nonclient background
3563 ::SetRect(&rect, cxWidth - m_cxRight, 0, cxWidth, cyHeight);
3564 #ifndef _WTL_NO_AUTO_THEME
3565 if(m_hTheme != NULL)
3566 {
3567 if(m_pfnDrawThemeParentBackground != NULL)
3568 {
3569 // this is to account for the left non-client area
3570 POINT ptOrg = { 0, 0 };
3571 dc.GetViewportOrg(&ptOrg);
3572 dc.SetViewportOrg(ptOrg.x + m_cxLeft, ptOrg.y);
3573 ::OffsetRect(&rect, -m_cxLeft, 0);
3574
3575 m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect);
3576
3577 // restore
3578 dc.SetViewportOrg(ptOrg);
3579 ::OffsetRect(&rect, m_cxLeft, 0);
3580 }
3581 else
3582 {
3583 dc.FillRect(&rect, COLOR_3DFACE);
3584 }
3585 }
3586 else
3587 #endif // !_WTL_NO_AUTO_THEME
3588 {
3589 if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0)
3590 dc.FillRect(&rect, COLOR_3DFACE);
3591 else
3592 dc.FillRect(&rect, COLOR_MENU);
3593 }
3594
3595 // draw buttons
3596 RECT arrRect[3] = { 0 };
3597 pT->_CalcBtnRects(cxWidth, cyHeight, arrRect);
3598 pT->_DrawMDIButton(dc, arrRect, -1); // draw all buttons
3599
3600 return lRet;
3601 }
3602
3603 LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3604 {
3605 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
3606 if(m_bChildMaximized)
3607 {
3608 RECT rect = { 0 };
3609 GetWindowRect(&rect);
3610 POINT pt = { GET_X_LPARAM(lParam) - rect.left, GET_Y_LPARAM(lParam) - rect.top };
3611 if(m_bLayoutRTL)
3612 {
3613 if((pt.x < m_cxRight) || (pt.x > ((rect.right - rect.left) - m_cxLeft)))
3614 lRet = HTBORDER;
3615 }
3616 else
3617 {
3618 if((pt.x < m_cxLeft) || (pt.x > ((rect.right - rect.left) - m_cxRight)))
3619 lRet = HTBORDER;
3620 }
3621 }
3622 return lRet;
3623 }
3624
3625 LRESULT OnNcLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
3626 {
3627 if(!m_bChildMaximized)
3628 {
3629 bHandled = FALSE;
3630 return 1;
3631 }
3632
3633 ATLASSERT(_DebugCheckChild());
3634
3635 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
3636 RECT rect = { 0 };
3637 GetWindowRect(&rect);
3638 pt.x -= rect.left;
3639 pt.y -= rect.top;
3640
3641 RECT rcIcon = { 0 };
3642 T* pT = static_cast<T*>(this);
3643 pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL);
3644 RECT arrRect[3] = { 0 };
3645 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
3646
3647 if(::PtInRect(&rcIcon, pt))
3648 {
3649 #ifdef _CMDBAR_EXTRA_TRACE
3650 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: icon\n"));
3651 #endif
3652 #ifndef TPM_VERPOSANIMATION
3653 const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag
3654 #endif
3655 CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE);
3656 UINT uRet = (UINT)menu.TrackPopupMenu(TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD |
3657 (s_bW2K ? TPM_VERPOSANIMATION : 0), m_bLayoutRTL ? rect.right : rect.left, rect.bottom, m_hWndChildMaximized);
3658
3659 // eat next message if click is on the same button
3660 ::OffsetRect(&rcIcon, rect.left, rect.top);
3661 MSG msg = { 0 };
3662 if(::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rcIcon, msg.pt))
3663 ::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, PM_REMOVE);
3664
3665 if(uRet != 0)
3666 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uRet, 0L);
3667 }
3668 else if(::PtInRect(&arrRect[0], pt))
3669 {
3670 #ifdef _CMDBAR_EXTRA_TRACE
3671 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: close button\n"));
3672 #endif
3673 m_nBtnWasPressed = m_nBtnPressed = 0;
3674 }
3675 else if(::PtInRect(&arrRect[1], pt))
3676 {
3677 #ifdef _CMDBAR_EXTRA_TRACE
3678 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: restore button\n"));
3679 #endif
3680 m_nBtnWasPressed = m_nBtnPressed = 1;
3681 }
3682 else if(::PtInRect(&arrRect[2], pt))
3683 {
3684 #ifdef _CMDBAR_EXTRA_TRACE
3685 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: minimize button\n"));
3686 #endif
3687 m_nBtnWasPressed = m_nBtnPressed = 2;
3688 }
3689 else
3690 {
3691 bHandled = FALSE;
3692 }
3693
3694 // draw the button state if it was pressed
3695 if(m_nBtnPressed != -1)
3696 {
3697 SetCapture();
3698 CWindowDC dc(m_hWnd);
3699 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect);
3700 pT->_DrawMDIButton(dc, arrRect, m_nBtnPressed);
3701 }
3702
3703 return 0;
3704 }
3705
3706 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
3707 {
3708 if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1)
3709 {
3710 bHandled = FALSE;
3711 return 1;
3712 }
3713
3714 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
3715 ClientToScreen(&pt);
3716 RECT rect = { 0 };
3717 GetWindowRect(&rect);
3718 pt.x -= rect.left;
3719 pt.y -= rect.top;
3720 RECT arrRect[3] = { 0 };
3721 T* pT = static_cast<T*>(this);
3722 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
3723 int nOldBtnPressed = m_nBtnPressed;
3724 m_nBtnPressed = ::PtInRect(&arrRect[m_nBtnWasPressed], pt) ? m_nBtnWasPressed : -1;
3725 if(nOldBtnPressed != m_nBtnPressed)
3726 {
3727 CWindowDC dc(m_hWnd);
3728 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect);
3729 pT->_DrawMDIButton(dc, arrRect, (m_nBtnPressed != -1) ? m_nBtnPressed : nOldBtnPressed);
3730 }
3731
3732 return 0;
3733 }
3734
3735 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
3736 {
3737 if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPressed == -1)
3738 {
3739 bHandled = FALSE;
3740 return 1;
3741 }
3742
3743 ATLASSERT(_DebugCheckChild());
3744
3745 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
3746 ClientToScreen(&pt);
3747 RECT rect = { 0 };
3748 GetWindowRect(&rect);
3749 pt.x -= rect.left;
3750 pt.y -= rect.top;
3751
3752 int nBtn = m_nBtnWasPressed;
3753 ReleaseCapture();
3754
3755 RECT arrRect[3] = { 0 };
3756 T* pT = static_cast<T*>(this);
3757 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
3758 if(::PtInRect(&arrRect[nBtn], pt))
3759 {
3760 switch(nBtn)
3761 {
3762 case 0: // close
3763 #ifdef _CMDBAR_EXTRA_TRACE
3764 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: close button\n"));
3765 #endif
3766 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_CLOSE, 0L);
3767 break;
3768 case 1: // restore
3769 #ifdef _CMDBAR_EXTRA_TRACE
3770 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: restore button\n"));
3771 #endif
3772 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_RESTORE, 0L);
3773 break;
3774 case 2: // minimize
3775 #ifdef _CMDBAR_EXTRA_TRACE
3776 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonUp: minimize button\n"));
3777 #endif
3778 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, SC_MINIMIZE, 0L);
3779 break;
3780 default:
3781 break;
3782 }
3783 }
3784
3785 return 0;
3786 }
3787
3788 LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
3789 {
3790 if(!m_bChildMaximized || m_nBtnWasPressed != -1)
3791 {
3792 bHandled = FALSE;
3793 return 1;
3794 }
3795
3796 ATLASSERT(_DebugCheckChild());
3797
3798 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
3799 RECT rect = { 0 };
3800 GetWindowRect(&rect);
3801 pt.x -= rect.left;
3802 pt.y -= rect.top;
3803
3804 RECT rcIcon = { 0 };
3805 T* pT = static_cast<T*>(this);
3806 pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top, rcIcon, m_bLayoutRTL);
3807 RECT arrRect[3] = { 0 };
3808 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect, m_bLayoutRTL);
3809
3810 if(::PtInRect(&rcIcon, pt))
3811 {
3812 CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized, FALSE);
3813 UINT uDefID = menu.GetMenuDefaultItem();
3814 if(uDefID == (UINT)-1)
3815 uDefID = SC_CLOSE;
3816 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uDefID, 0L);
3817 }
3818
3819 return 0;
3820 }
3821
3822 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
3823 {
3824 if(m_bChildMaximized)
3825 {
3826 if(m_nBtnPressed != -1)
3827 {
3828 ATLASSERT(m_nBtnPressed == m_nBtnWasPressed); // must be
3829 m_nBtnPressed = -1;
3830 RECT rect = { 0 };
3831 GetWindowRect(&rect);
3832 RECT arrRect[3] = { 0 };
3833 T* pT = static_cast<T*>(this);
3834 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top, arrRect);
3835 CWindowDC dc(m_hWnd);
3836 pT->_DrawMDIButton(dc, arrRect, m_nBtnWasPressed);
3837 }
3838 m_nBtnWasPressed = -1;
3839 }
3840 else
3841 {
3842 bHandled = FALSE;
3843 }
3844 return 0;
3845 }
3846
3847 // Parent window message handlers
3848 LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
3849 {
3850 m_bParentActive = (LOWORD(wParam) != WA_INACTIVE);
3851 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW);
3852 bHandled = FALSE;
3853 return 1;
3854 }
3855
3856 // MDI client window message handlers
3857 LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3858 {
3859 m_wndMDIClient.DefWindowProc(uMsg, NULL, lParam);
3860 HMENU hOldMenu = GetMenu();
3861 BOOL bRet = AttachMenu((HMENU)wParam);
3862 bRet; // avoid level 4 warning
3863 ATLASSERT(bRet);
3864
3865 #if (_WIN32_IE >= 0x0400)
3866 T* pT = static_cast<T*>(this);
3867 pT->UpdateRebarBandIdealSize();
3868 #endif // (_WIN32_IE >= 0x0400)
3869
3870 return (LRESULT)hOldMenu;
3871 }
3872
3873 // All messages from the message hook
3874 LRESULT OnAllHookMessages(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
3875 {
3876 T* pT = static_cast<T*>(this);
3877 pT->_ProcessAllHookMessages(uMsg, wParam, lParam);
3878
3879 bHandled = FALSE;
3880 return 1;
3881 }
3882
3883 // Overrideables
3884 // override this to provide different ideal size
3885 void UpdateRebarBandIdealSize()
3886 {
3887 // assuming we are in a rebar, change ideal size to our size
3888 // we hope that if we are not in a rebar, nCount will be 0
3889 int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L);
3890 for(int i = 0; i < nCount; i++)
3891 {
3892 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE };
3893 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
3894 if(rbi.hwndChild == m_hWnd)
3895 {
3896 rbi.fMask = RBBIM_IDEALSIZE;
3897 rbi.cxIdeal = m_bChildMaximized ? m_cxLeft + m_cxRight : 0;
3898 int nBtnCount = GetButtonCount();
3899 if(nBtnCount > 0)
3900 {
3901 RECT rect = { 0 };
3902 GetItemRect(nBtnCount - 1, &rect);
3903 rbi.cxIdeal += rect.right;
3904 }
3905 ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
3906 break;
3907 }
3908 }
3909 }
3910
3911 // all hook messages - check for the maximized MDI child window change
3912 void _ProcessAllHookMessages(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/)
3913 {
3914 if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU)
3915 return;
3916
3917 BOOL bMaximized = FALSE;
3918 HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
3919 bool bMaxOld = m_bChildMaximized;
3920 m_bChildMaximized = (hWndChild != NULL && bMaximized);
3921 HICON hIconOld = m_hIconChildMaximized;
3922
3923 if(m_bChildMaximized)
3924 {
3925 if(m_hWndChildMaximized != hWndChild)
3926 {
3927 ATL::CWindow wnd = m_hWndChildMaximized = hWndChild;
3928 m_hIconChildMaximized = wnd.GetIcon(FALSE);
3929 if(m_hIconChildMaximized == NULL)
3930 {
3931 m_hIconChildMaximized = wnd.GetIcon(TRUE);
3932 if(m_hIconChildMaximized == NULL)
3933 {
3934 // no icon set with WM_SETICON, get the class one
3935 // need conditional code because types don't match in winuser.h
3936 #ifdef _WIN64
3937 m_hIconChildMaximized = (HICON)::GetClassLongPtr(wnd, GCLP_HICONSM);
3938 #else
3939 m_hIconChildMaximized = (HICON)LongToHandle(::GetClassLongPtr(wnd, GCLP_HICONSM));
3940 #endif
3941 }
3942 }
3943 }
3944 }
3945 else
3946 {
3947 m_hWndChildMaximized = NULL;
3948 m_hIconChildMaximized = NULL;
3949 }
3950
3951 if(bMaxOld != m_bChildMaximized)
3952 {
3953 #ifdef _CMDBAR_EXTRA_TRACE
3954 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - All messages hook change: m_bChildMaximized = %s\n"), m_bChildMaximized ? "true" : "false");
3955 #endif
3956 // assuming we are in a rebar, change our size to accomodate new state
3957 // we hope that if we are not in a rebar, nCount will be 0
3958 int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0, 0L);
3959 int cxDiff = (m_bChildMaximized ? 1 : -1) * (m_cxLeft + m_cxRight);
3960 for(int i = 0; i < nCount; i++)
3961 {
3962 #if (_WIN32_IE >= 0x0500)
3963 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE };
3964 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
3965 if(rbi.hwndChild == m_hWnd)
3966 {
3967 if((rbi.fStyle & RBBS_USECHEVRON) != 0)
3968 {
3969 rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
3970 rbi.cxMinChild += cxDiff;
3971 rbi.cxIdeal += cxDiff;
3972 ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
3973 }
3974 break;
3975 }
3976 #elif (_WIN32_IE >= 0x0400)
3977 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE };
3978 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
3979 if(rbi.hwndChild == m_hWnd)
3980 {
3981 rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
3982 rbi.cxMinChild += cxDiff;
3983 rbi.cxIdeal += cxDiff;
3984 ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
3985 break;
3986 }
3987 #else // (_WIN32_IE < 0x0400)
3988 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE };
3989 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&rbi);
3990 if(rbi.hwndChild == m_hWnd)
3991 {
3992 rbi.fMask = RBBIM_CHILDSIZE;
3993 rbi.cxMinChild += cxDiff;
3994 ::SendMessage(GetParent(), RB_SETBANDINFO, i, (LPARAM)&rbi);
3995 break;
3996 }
3997 #endif // (_WIN32_IE < 0x0400)
3998 }
3999 }
4000
4001 if(bMaxOld != m_bChildMaximized || hIconOld != m_hIconChildMaximized)
4002 {
4003 // force size change and redraw everything
4004 RECT rect = { 0 };
4005 GetWindowRect(&rect);
4006 ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2);
4007 SetRedraw(FALSE);
4008 SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE);
4009 SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
4010 SetRedraw(TRUE);
4011 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
4012 }
4013 }
4014
4015 // Implementation
4016 void GetSystemSettings()
4017 {
4018 #ifdef _CMDBAR_EXTRA_TRACE
4019 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - GetSystemSettings\n"));
4020 #endif
4021 _baseClass::GetSystemSettings();
4022
4023 NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
4024 BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
4025 ATLASSERT(bRet);
4026 if(bRet)
4027 {
4028 m_cxIconWidth = ::GetSystemMetrics(SM_CXSMICON);
4029 m_cyIconHeight = ::GetSystemMetrics(SM_CYSMICON);
4030 m_cxLeft = m_cxIconWidth;
4031
4032 #ifndef _WTL_NO_AUTO_THEME
4033 if(m_hTheme != NULL)
4034 {
4035 m_cxBtnWidth = info.iCaptionWidth - 2 * m_cxyOffset;
4036 m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset;
4037 m_cxRight = 3 * m_cxBtnWidth;
4038 }
4039 else
4040 #endif // !_WTL_NO_AUTO_THEME
4041 {
4042 m_cxBtnWidth = info.iCaptionWidth - m_cxyOffset;
4043 m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyOffset;
4044 m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset;
4045 }
4046 }
4047
4048 RECT rect = { 0 };
4049 GetClientRect(&rect);
4050 T* pT = static_cast<T*>(this);
4051 pT->_AdjustBtnSize(rect.bottom);
4052 }
4053
4054 void _AdjustBtnSize(int cyHeight)
4055 {
4056 if(cyHeight > 1 && m_cyBtnHeight > cyHeight)
4057 {
4058 #ifndef _WTL_NO_AUTO_THEME
4059 if(m_hTheme != NULL)
4060 {
4061 m_cyBtnHeight = cyHeight;
4062 m_cxBtnWidth = cyHeight;
4063 m_cxRight = 3 * m_cxBtnWidth;
4064 }
4065 else
4066 #endif // !_WTL_NO_AUTO_THEME
4067 {
4068 m_cyBtnHeight = cyHeight;
4069 m_cxBtnWidth = cyHeight + m_cxyOffset;
4070 m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset;
4071 }
4072 }
4073 }
4074
4075 void _CalcIconRect(int cxWidth, int cyHeight, RECT& rect, bool bInvertX = false) const
4076 {
4077 int xStart = (m_cxLeft - m_cxIconWidth) / 2;
4078 if(xStart < 0)
4079 xStart = 0;
4080 int yStart = (cyHeight - m_cyIconHeight) / 2;
4081 if(yStart < 0)
4082 yStart = 0;
4083
4084 if(bInvertX)
4085 ::SetRect(&rect, cxWidth - (xStart + m_cxBtnWidth), yStart, cxWidth - xStart, yStart + m_cyBtnHeight);
4086 else
4087 ::SetRect(&rect, xStart, yStart, xStart + m_cxBtnWidth, yStart + m_cyBtnHeight);
4088 }
4089
4090 void _CalcBtnRects(int cxWidth, int cyHeight, RECT arrRect[3], bool bInvertX = false) const
4091 {
4092 int yStart = (cyHeight - m_cyBtnHeight) / 2;
4093 if(yStart < 0)
4094 yStart = 0;
4095
4096 RECT rcBtn = { cxWidth - m_cxBtnWidth, yStart, cxWidth, yStart + m_cyBtnHeight };
4097 int nDirection = -1;
4098 if(bInvertX)
4099 {
4100 ::SetRect(&rcBtn, 0, yStart, m_cxBtnWidth, yStart + m_cyBtnHeight);
4101 nDirection = 1;
4102 }
4103
4104 arrRect[0] = rcBtn;
4105 #ifndef _WTL_NO_AUTO_THEME
4106 if(m_hTheme != NULL)
4107 ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0);
4108 else
4109 #endif // !_WTL_NO_AUTO_THEME
4110 ::OffsetRect(&rcBtn, nDirection * (m_cxBtnWidth + m_cxyOffset), 0);
4111 arrRect[1] = rcBtn;
4112 ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0);
4113 arrRect[2] = rcBtn;
4114 }
4115
4116 void _DrawMDIButton(CWindowDC& dc, LPRECT pRects, int nBtn)
4117 {
4118 #ifndef _WTL_NO_AUTO_THEME
4119 if(m_hTheme != NULL)
4120 {
4121 #if !defined(TMSCHEMA_H) && !defined(__VSSYM32_H__)
4122 const int WP_MDICLOSEBUTTON = 20;
4123 const int CBS_NORMAL = 1;
4124 const int CBS_PUSHED = 3;
4125 const int CBS_DISABLED = 4;
4126 const int WP_MDIRESTOREBUTTON = 22;
4127 const int RBS_NORMAL = 1;
4128 const int RBS_PUSHED = 3;
4129 const int RBS_DISABLED = 4;
4130 const int WP_MDIMINBUTTON = 16;
4131 const int MINBS_NORMAL = 1;
4132 const int MINBS_PUSHED = 3;
4133 const int MINBS_DISABLED = 4;
4134 #endif // !defined(TMSCHEMA_H) && !defined(__VSSYM32_H__)
4135 if(nBtn == -1 || nBtn == 0)
4136 m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDICLOSEBUTTON, m_bParentActive ? ((m_nBtnPressed == 0) ? CBS_PUSHED : CBS_NORMAL) : CBS_DISABLED, &pRects[0], NULL);
4137 if(nBtn == -1 || nBtn == 1)
4138 m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIRESTOREBUTTON, m_bParentActive ? ((m_nBtnPressed == 1) ? RBS_PUSHED : RBS_NORMAL) : RBS_DISABLED, &pRects[1], NULL);
4139 if(nBtn == -1 || nBtn == 2)
4140 m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIMINBUTTON, m_bParentActive ? ((m_nBtnPressed == 2) ? MINBS_PUSHED : MINBS_NORMAL) : MINBS_DISABLED, &pRects[2], NULL);
4141 }
4142 else
4143 #endif // !_WTL_NO_AUTO_THEME
4144 {
4145 if(nBtn == -1 || nBtn == 0)
4146 dc.DrawFrameControl(&pRects[0], DFC_CAPTION, DFCS_CAPTIONCLOSE | ((m_nBtnPressed == 0) ? DFCS_PUSHED : 0));
4147 if(nBtn == -1 || nBtn == 1)
4148 dc.DrawFrameControl(&pRects[1], DFC_CAPTION, DFCS_CAPTIONRESTORE | ((m_nBtnPressed == 1) ? DFCS_PUSHED : 0));
4149 if(nBtn == -1 || nBtn == 2)
4150 dc.DrawFrameControl(&pRects[2], DFC_CAPTION, DFCS_CAPTIONMIN | ((m_nBtnPressed == 2) ? DFCS_PUSHED : 0));
4151 }
4152 }
4153
4154 #ifndef _WTL_NO_AUTO_THEME
4155 static UINT _GetThemeChangedMsg()
4156 {
4157 #ifndef WM_THEMECHANGED
4158 static const UINT WM_THEMECHANGED = 0x031A;
4159 #endif // !WM_THEMECHANGED
4160 return WM_THEMECHANGED;
4161 }
4162
4163 void _OpenThemeData()
4164 {
4165 ATLASSERT(m_hThemeDLL != NULL);
4166
4167 PFN_OpenThemeData pfnOpenThemeData = (PFN_OpenThemeData)::GetProcAddress(m_hThemeDLL, "OpenThemeData");
4168 ATLASSERT(pfnOpenThemeData != NULL);
4169 if(pfnOpenThemeData != NULL)
4170 m_hTheme = pfnOpenThemeData(m_hWnd, L"Window");
4171 }
4172
4173 void _CloseThemeData()
4174 {
4175 ATLASSERT(m_hThemeDLL != NULL);
4176
4177 if(m_hTheme == NULL)
4178 return; // nothing to do
4179
4180 PFN_CloseThemeData pfnCloseThemeData = (PFN_CloseThemeData)::GetProcAddress(m_hThemeDLL, "CloseThemeData");
4181 ATLASSERT(pfnCloseThemeData != NULL);
4182 if(pfnCloseThemeData != NULL)
4183 {
4184 pfnCloseThemeData(m_hTheme);
4185 m_hTheme = NULL;
4186 }
4187 }
4188 #endif // !_WTL_NO_AUTO_THEME
4189
4190 bool _DebugCheckChild()
4191 {
4192 #ifdef _DEBUG
4193 BOOL bMaximized = FALSE;
4194 HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
4195 return (bMaximized && hWndChild == m_hWndChildMaximized);
4196 #else // !_DEBUG
4197 return true;
4198 #endif // !_DEBUG
4199 }
4200 };
4201
4202 class CMDICommandBarCtrl : public CMDICommandBarCtrlImpl<CMDICommandBarCtrl>
4203 {
4204 public:
4205 DECLARE_WND_SUPERCLASS(_T("WTL_MDICommandBar"), GetWndClassName())
4206 };
4207
4208 }; // namespace WTL
4209
4210 #endif // __ATLCTRLW_H__
+0
-5120
src/third_party/wtl/Include/atlctrlx.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLCTRLX_H__
9 #define __ATLCTRLX_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlctrlx.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLCTRLS_H__
18 #error atlctrlx.h requires atlctrls.h to be included first
19 #endif
20
21 #ifndef WM_UPDATEUISTATE
22 #define WM_UPDATEUISTATE 0x0128
23 #endif // !WM_UPDATEUISTATE
24
25
26 ///////////////////////////////////////////////////////////////////////////////
27 // Classes in this file:
28 //
29 // CBitmapButtonImpl<T, TBase, TWinTraits>
30 // CBitmapButton
31 // CCheckListViewCtrlImpl<T, TBase, TWinTraits>
32 // CCheckListViewCtrl
33 // CHyperLinkImpl<T, TBase, TWinTraits>
34 // CHyperLink
35 // CWaitCursor
36 // CCustomWaitCursor
37 // CMultiPaneStatusBarCtrlImpl<T, TBase>
38 // CMultiPaneStatusBarCtrl
39 // CPaneContainerImpl<T, TBase, TWinTraits>
40 // CPaneContainer
41 // CSortListViewImpl<T>
42 // CSortListViewCtrlImpl<T, TBase, TWinTraits>
43 // CSortListViewCtrl
44 // CTabViewImpl<T, TBase, TWinTraits>
45 // CTabView
46
47 namespace WTL
48 {
49
50 ///////////////////////////////////////////////////////////////////////////////
51 // CBitmapButton - bitmap button implementation
52
53 #ifndef _WIN32_WCE
54
55 // bitmap button extended styles
56 #define BMPBTN_HOVER 0x00000001
57 #define BMPBTN_AUTO3D_SINGLE 0x00000002
58 #define BMPBTN_AUTO3D_DOUBLE 0x00000004
59 #define BMPBTN_AUTOSIZE 0x00000008
60 #define BMPBTN_SHAREIMAGELISTS 0x00000010
61 #define BMPBTN_AUTOFIRE 0x00000020
62 #define BMPBTN_CHECK 0x00000040
63 #define BMPBTN_AUTOCHECK 0x00000080
64
65 // Note: BMPBTN_CHECK/BMPBTN_AUTOCHECK disables BN_DOUBLECLICKED,
66 // BMPBTN_AUTOFIRE doesn't work with BMPBTN_CHECK/BMPBTN_AUTOCHECK
67
68 template <class T, class TBase = CButton, class TWinTraits = ATL::CControlWinTraits>
69 class ATL_NO_VTABLE CBitmapButtonImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
70 {
71 public:
72 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
73
74 enum
75 {
76 _nImageNormal = 0,
77 _nImagePushed,
78 _nImageFocusOrHover,
79 _nImageDisabled,
80
81 _nImageCount = 4,
82 };
83
84 enum
85 {
86 ID_TIMER_FIRST = 1000,
87 ID_TIMER_REPEAT = 1001
88 };
89
90 // Bitmap button specific extended styles
91 DWORD m_dwExtendedStyle;
92
93 CImageList m_ImageList;
94 int m_nImage[_nImageCount];
95
96 CToolTipCtrl m_tip;
97 LPTSTR m_lpstrToolTipText;
98
99 // Internal states
100 unsigned m_fMouseOver:1;
101 unsigned m_fFocus:1;
102 unsigned m_fPressed:1;
103 unsigned m_fChecked:1;
104
105
106 // Constructor/Destructor
107 CBitmapButtonImpl(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) :
108 m_dwExtendedStyle(dwExtendedStyle), m_ImageList(hImageList),
109 m_lpstrToolTipText(NULL),
110 m_fMouseOver(0), m_fFocus(0), m_fPressed(0), m_fChecked(0)
111 {
112 m_nImage[_nImageNormal] = -1;
113 m_nImage[_nImagePushed] = -1;
114 m_nImage[_nImageFocusOrHover] = -1;
115 m_nImage[_nImageDisabled] = -1;
116
117 #ifdef _DEBUG
118 if(((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) && IsCheckMode())
119 ATLTRACE2(atlTraceUI, 0, _T("CBitmapButtonImpl - Check mode and BMPBTN_AUTOFIRE cannot be used together, BMPBTN_AUTOFIRE will be ignored.\n"));
120 #endif // _DEBUG
121 }
122
123 ~CBitmapButtonImpl()
124 {
125 if((m_dwExtendedStyle & BMPBTN_SHAREIMAGELISTS) == 0)
126 m_ImageList.Destroy();
127 delete [] m_lpstrToolTipText;
128 }
129
130 // overridden to provide proper initialization
131 BOOL SubclassWindow(HWND hWnd)
132 {
133 #if (_MSC_VER >= 1300)
134 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
135 #else // !(_MSC_VER >= 1300)
136 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
137 BOOL bRet = _baseClass::SubclassWindow(hWnd);
138 #endif // !(_MSC_VER >= 1300)
139 if(bRet != FALSE)
140 {
141 T* pT = static_cast<T*>(this);
142 pT->Init();
143 }
144
145 return bRet;
146 }
147
148 // Attributes
149 DWORD GetBitmapButtonExtendedStyle() const
150 {
151 return m_dwExtendedStyle;
152 }
153
154 DWORD SetBitmapButtonExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
155 {
156 DWORD dwPrevStyle = m_dwExtendedStyle;
157 if(dwMask == 0)
158 m_dwExtendedStyle = dwExtendedStyle;
159 else
160 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
161
162 #ifdef _DEBUG
163 if(((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) && IsCheckMode())
164 ATLTRACE2(atlTraceUI, 0, _T("CBitmapButtonImpl - Check mode and BMPBTN_AUTOFIRE cannot be used together, BMPBTN_AUTOFIRE will be ignored.\n"));
165 #endif // _DEBUG
166
167 return dwPrevStyle;
168 }
169
170 HIMAGELIST GetImageList() const
171 {
172 return m_ImageList;
173 }
174
175 HIMAGELIST SetImageList(HIMAGELIST hImageList)
176 {
177 HIMAGELIST hImageListPrev = m_ImageList;
178 m_ImageList = hImageList;
179 if((m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0 && ::IsWindow(m_hWnd))
180 SizeToImage();
181
182 return hImageListPrev;
183 }
184
185 int GetToolTipTextLength() const
186 {
187 return (m_lpstrToolTipText == NULL) ? -1 : lstrlen(m_lpstrToolTipText);
188 }
189
190 bool GetToolTipText(LPTSTR lpstrText, int nLength) const
191 {
192 ATLASSERT(lpstrText != NULL);
193 if(m_lpstrToolTipText == NULL)
194 return false;
195
196 errno_t nRet = SecureHelper::strncpy_x(lpstrText, nLength, m_lpstrToolTipText, _TRUNCATE);
197
198 return (nRet == 0 || nRet == STRUNCATE);
199 }
200
201 bool SetToolTipText(LPCTSTR lpstrText)
202 {
203 if(m_lpstrToolTipText != NULL)
204 {
205 delete [] m_lpstrToolTipText;
206 m_lpstrToolTipText = NULL;
207 }
208
209 if(lpstrText == NULL)
210 {
211 if(m_tip.IsWindow())
212 m_tip.Activate(FALSE);
213 return true;
214 }
215
216 int cchLen = lstrlen(lpstrText) + 1;
217 ATLTRY(m_lpstrToolTipText = new TCHAR[cchLen]);
218 if(m_lpstrToolTipText == NULL)
219 return false;
220
221 SecureHelper::strcpy_x(m_lpstrToolTipText, cchLen, lpstrText);
222 if(m_tip.IsWindow())
223 {
224 m_tip.Activate(TRUE);
225 m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
226 }
227
228 return true;
229 }
230
231 bool GetCheck() const
232 {
233 return (m_fChecked == 1);
234 }
235
236 void SetCheck(bool bCheck, bool bUpdate = true)
237 {
238 m_fChecked = bCheck ? 1 : 0;
239
240 if(bUpdate)
241 {
242 Invalidate();
243 UpdateWindow();
244 }
245 }
246
247 // Operations
248 void SetImages(int nNormal, int nPushed = -1, int nFocusOrHover = -1, int nDisabled = -1)
249 {
250 if(nNormal != -1)
251 m_nImage[_nImageNormal] = nNormal;
252 if(nPushed != -1)
253 m_nImage[_nImagePushed] = nPushed;
254 if(nFocusOrHover != -1)
255 m_nImage[_nImageFocusOrHover] = nFocusOrHover;
256 if(nDisabled != -1)
257 m_nImage[_nImageDisabled] = nDisabled;
258 }
259
260 BOOL SizeToImage()
261 {
262 ATLASSERT(::IsWindow(m_hWnd) && m_ImageList.m_hImageList != NULL);
263 int cx = 0;
264 int cy = 0;
265 if(!m_ImageList.GetIconSize(cx, cy))
266 return FALSE;
267 return ResizeClient(cx, cy);
268 }
269
270 // Overrideables
271 void DoPaint(CDCHandle dc)
272 {
273 ATLASSERT(m_ImageList.m_hImageList != NULL); // image list must be set
274 ATLASSERT(m_nImage[0] != -1); // main bitmap must be set
275
276 // set bitmap according to the current button state
277 bool bHover = IsHoverMode();
278 bool bPressed = (m_fPressed == 1) || (IsCheckMode() && (m_fChecked == 1));
279 int nImage = -1;
280 if(!IsWindowEnabled())
281 nImage = m_nImage[_nImageDisabled];
282 else if(bPressed)
283 nImage = m_nImage[_nImagePushed];
284 else if((!bHover && (m_fFocus == 1)) || (bHover && (m_fMouseOver == 1)))
285 nImage = m_nImage[_nImageFocusOrHover];
286
287 // if none is set, use default one
288 if(nImage == -1)
289 nImage = m_nImage[_nImageNormal];
290
291 // draw the button image
292 bool bAuto3D = (m_dwExtendedStyle & (BMPBTN_AUTO3D_SINGLE | BMPBTN_AUTO3D_DOUBLE)) != 0;
293 int xyPos = (bPressed && bAuto3D && (m_nImage[_nImagePushed] == -1)) ? 1 : 0;
294 m_ImageList.Draw(dc, nImage, xyPos, xyPos, ILD_NORMAL);
295
296 // draw 3D border if required
297 if(bAuto3D)
298 {
299 RECT rect = { 0 };
300 GetClientRect(&rect);
301
302 if(bPressed)
303 dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_SUNKENOUTER : EDGE_SUNKEN, BF_RECT);
304 else if(!bHover || (m_fMouseOver == 1))
305 dc.DrawEdge(&rect, ((m_dwExtendedStyle & BMPBTN_AUTO3D_SINGLE) != 0) ? BDR_RAISEDINNER : EDGE_RAISED, BF_RECT);
306
307 if(!bHover && (m_fFocus == 1))
308 {
309 ::InflateRect(&rect, -2 * ::GetSystemMetrics(SM_CXEDGE), -2 * ::GetSystemMetrics(SM_CYEDGE));
310 dc.DrawFocusRect(&rect);
311 }
312 }
313 }
314
315 // Message map and handlers
316 BEGIN_MSG_MAP(CBitmapButtonImpl)
317 MESSAGE_HANDLER(WM_CREATE, OnCreate)
318 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
319 MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
320 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
321 MESSAGE_HANDLER(WM_PAINT, OnPaint)
322 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
323 MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
324 MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
325 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
326 MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
327 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
328 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
329 MESSAGE_HANDLER(WM_ENABLE, OnEnable)
330 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
331 MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
332 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
333 MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
334 MESSAGE_HANDLER(WM_TIMER, OnTimer)
335 MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
336 END_MSG_MAP()
337
338 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
339 {
340 T* pT = static_cast<T*>(this);
341 pT->Init();
342
343 bHandled = FALSE;
344 return 1;
345 }
346
347 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
348 {
349 if(m_tip.IsWindow())
350 {
351 m_tip.DestroyWindow();
352 m_tip.m_hWnd = NULL;
353 }
354 bHandled = FALSE;
355 return 1;
356 }
357
358 LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
359 {
360 MSG msg = { m_hWnd, uMsg, wParam, lParam };
361 if(m_tip.IsWindow())
362 m_tip.RelayEvent(&msg);
363 bHandled = FALSE;
364 return 1;
365 }
366
367 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
368 {
369 return 1; // no background needed
370 }
371
372 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
373 {
374 T* pT = static_cast<T*>(this);
375 if(wParam != NULL)
376 {
377 pT->DoPaint((HDC)wParam);
378 }
379 else
380 {
381 CPaintDC dc(m_hWnd);
382 pT->DoPaint(dc.m_hDC);
383 }
384 return 0;
385 }
386
387 LRESULT OnFocus(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
388 {
389 m_fFocus = (uMsg == WM_SETFOCUS) ? 1 : 0;
390 Invalidate();
391 UpdateWindow();
392 bHandled = FALSE;
393 return 1;
394 }
395
396 LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
397 {
398 LRESULT lRet = 0;
399 if(IsHoverMode())
400 SetCapture();
401 else
402 lRet = DefWindowProc(uMsg, wParam, lParam);
403 if(::GetCapture() == m_hWnd)
404 {
405 m_fPressed = 1;
406 Invalidate();
407 UpdateWindow();
408 }
409 if(((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0) && !IsCheckMode())
410 {
411 int nElapse = 250;
412 int nDelay = 0;
413 if(::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &nDelay, 0))
414 nElapse += nDelay * 250; // all milli-seconds
415 SetTimer(ID_TIMER_FIRST, nElapse);
416 }
417 return lRet;
418 }
419
420 LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
421 {
422 LRESULT lRet = 0;
423 if(!IsHoverMode() && !IsCheckMode())
424 lRet = DefWindowProc(uMsg, wParam, lParam);
425 if(::GetCapture() != m_hWnd)
426 SetCapture();
427 if(m_fPressed == 0)
428 {
429 m_fPressed = 1;
430 Invalidate();
431 UpdateWindow();
432 }
433 return lRet;
434 }
435
436 LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
437 {
438 if(((m_dwExtendedStyle & BMPBTN_AUTOCHECK) != 0) && (m_fPressed == 1))
439 SetCheck(!GetCheck(), false);
440
441 LRESULT lRet = 0;
442 if(!IsHoverMode() && !IsCheckMode())
443 lRet = DefWindowProc(uMsg, wParam, lParam);
444 if(::GetCapture() == m_hWnd)
445 {
446 if((IsHoverMode() || IsCheckMode()) && (m_fPressed == 1))
447 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
448 ::ReleaseCapture();
449 }
450 return lRet;
451 }
452
453 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
454 {
455 if(m_fPressed == 1)
456 {
457 m_fPressed = 0;
458 Invalidate();
459 UpdateWindow();
460 }
461 bHandled = FALSE;
462 return 1;
463 }
464
465 LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
466 {
467 Invalidate();
468 UpdateWindow();
469 bHandled = FALSE;
470 return 1;
471 }
472
473 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
474 {
475 if(::GetCapture() == m_hWnd)
476 {
477 POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
478 ClientToScreen(&ptCursor);
479 RECT rect = { 0 };
480 GetWindowRect(&rect);
481 unsigned int uPressed = ::PtInRect(&rect, ptCursor) ? 1 : 0;
482 if(m_fPressed != uPressed)
483 {
484 m_fPressed = uPressed;
485 Invalidate();
486 UpdateWindow();
487 }
488 }
489 else if(IsHoverMode() && m_fMouseOver == 0)
490 {
491 m_fMouseOver = 1;
492 Invalidate();
493 UpdateWindow();
494 StartTrackMouseLeave();
495 }
496 bHandled = FALSE;
497 return 1;
498 }
499
500 LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
501 {
502 if(m_fMouseOver == 1)
503 {
504 m_fMouseOver = 0;
505 Invalidate();
506 UpdateWindow();
507 }
508 return 0;
509 }
510
511 LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
512 {
513 if(wParam == VK_SPACE && IsHoverMode())
514 return 0; // ignore if in hover mode
515 if(wParam == VK_SPACE && m_fPressed == 0)
516 {
517 m_fPressed = 1;
518 Invalidate();
519 UpdateWindow();
520 }
521 bHandled = FALSE;
522 return 1;
523 }
524
525 LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
526 {
527 if(wParam == VK_SPACE && IsHoverMode())
528 return 0; // ignore if in hover mode
529 if(wParam == VK_SPACE && m_fPressed == 1)
530 {
531 m_fPressed = 0;
532 if((m_dwExtendedStyle & BMPBTN_AUTOCHECK) != 0)
533 SetCheck(!GetCheck(), false);
534 Invalidate();
535 UpdateWindow();
536 }
537 bHandled = FALSE;
538 return 1;
539 }
540
541 LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
542 {
543 ATLASSERT((m_dwExtendedStyle & BMPBTN_AUTOFIRE) != 0);
544 switch(wParam) // timer ID
545 {
546 case ID_TIMER_FIRST:
547 KillTimer(ID_TIMER_FIRST);
548 if(m_fPressed == 1)
549 {
550 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
551 int nElapse = 250;
552 int nRepeat = 40;
553 if(::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &nRepeat, 0))
554 nElapse = 10000 / (10 * nRepeat + 25); // milli-seconds, approximated
555 SetTimer(ID_TIMER_REPEAT, nElapse);
556 }
557 break;
558 case ID_TIMER_REPEAT:
559 if(m_fPressed == 1)
560 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
561 else if(::GetCapture() != m_hWnd)
562 KillTimer(ID_TIMER_REPEAT);
563 break;
564 default: // not our timer
565 break;
566 }
567 return 0;
568 }
569
570 LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
571 {
572 // If the control is subclassed or superclassed, this message can cause
573 // repainting without WM_PAINT. We don't use this state, so just do nothing.
574 return 0;
575 }
576
577 // Implementation
578 void Init()
579 {
580 // We need this style to prevent Windows from painting the button
581 ModifyStyle(0, BS_OWNERDRAW);
582
583 // create a tool tip
584 m_tip.Create(m_hWnd);
585 ATLASSERT(m_tip.IsWindow());
586 if(m_tip.IsWindow() && m_lpstrToolTipText != NULL)
587 {
588 m_tip.Activate(TRUE);
589 m_tip.AddTool(m_hWnd, m_lpstrToolTipText);
590 }
591
592 if(m_ImageList.m_hImageList != NULL && (m_dwExtendedStyle & BMPBTN_AUTOSIZE) != 0)
593 SizeToImage();
594 }
595
596 BOOL StartTrackMouseLeave()
597 {
598 TRACKMOUSEEVENT tme = { 0 };
599 tme.cbSize = sizeof(tme);
600 tme.dwFlags = TME_LEAVE;
601 tme.hwndTrack = m_hWnd;
602 return _TrackMouseEvent(&tme);
603 }
604
605 bool IsHoverMode() const
606 {
607 return ((m_dwExtendedStyle & BMPBTN_HOVER) != 0);
608 }
609
610 bool IsCheckMode() const
611 {
612 return ((m_dwExtendedStyle & (BMPBTN_CHECK | BMPBTN_AUTOCHECK)) != 0);
613 }
614 };
615
616 class CBitmapButton : public CBitmapButtonImpl<CBitmapButton>
617 {
618 public:
619 DECLARE_WND_SUPERCLASS(_T("WTL_BitmapButton"), GetWndClassName())
620
621 CBitmapButton(DWORD dwExtendedStyle = BMPBTN_AUTOSIZE, HIMAGELIST hImageList = NULL) :
622 CBitmapButtonImpl<CBitmapButton>(dwExtendedStyle, hImageList)
623 { }
624 };
625
626 #endif // !_WIN32_WCE
627
628
629 ///////////////////////////////////////////////////////////////////////////////
630 // CCheckListCtrlView - list view control with check boxes
631
632 template <DWORD t_dwStyle, DWORD t_dwExStyle, DWORD t_dwExListViewStyle>
633 class CCheckListViewCtrlImplTraits
634 {
635 public:
636 static DWORD GetWndStyle(DWORD dwStyle)
637 {
638 return (dwStyle == 0) ? t_dwStyle : dwStyle;
639 }
640
641 static DWORD GetWndExStyle(DWORD dwExStyle)
642 {
643 return (dwExStyle == 0) ? t_dwExStyle : dwExStyle;
644 }
645
646 static DWORD GetExtendedLVStyle()
647 {
648 return t_dwExListViewStyle;
649 }
650 };
651
652 typedef CCheckListViewCtrlImplTraits<WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS, WS_EX_CLIENTEDGE, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT> CCheckListViewCtrlTraits;
653
654 template <class T, class TBase = CListViewCtrl, class TWinTraits = CCheckListViewCtrlTraits>
655 class ATL_NO_VTABLE CCheckListViewCtrlImpl : public ATL::CWindowImpl<T, TBase, TWinTraits >
656 {
657 public:
658 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
659
660 // Attributes
661 static DWORD GetExtendedLVStyle()
662 {
663 return TWinTraits::GetExtendedLVStyle();
664 }
665
666 // Operations
667 BOOL SubclassWindow(HWND hWnd)
668 {
669 #if (_MSC_VER >= 1300)
670 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
671 #else // !(_MSC_VER >= 1300)
672 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
673 BOOL bRet = _baseClass::SubclassWindow(hWnd);
674 #endif // !(_MSC_VER >= 1300)
675 if(bRet != FALSE)
676 {
677 T* pT = static_cast<T*>(this);
678 pT->Init();
679 }
680
681 return bRet;
682 }
683
684 void CheckSelectedItems(int nCurrItem)
685 {
686 // first check if this item is selected
687 LVITEM lvi = { 0 };
688 lvi.iItem = nCurrItem;
689 lvi.iSubItem = 0;
690 lvi.mask = LVIF_STATE;
691 lvi.stateMask = LVIS_SELECTED;
692 GetItem(&lvi);
693 // if item is not selected, don't do anything
694 if(!(lvi.state & LVIS_SELECTED))
695 return;
696 // new check state will be reverse of the current state,
697 BOOL bCheck = !GetCheckState(nCurrItem);
698 int nItem = -1;
699 int nOldItem = -1;
700 while((nItem = GetNextItem(nOldItem, LVNI_SELECTED)) != -1)
701 {
702 if(nItem != nCurrItem)
703 SetCheckState(nItem, bCheck);
704 nOldItem = nItem;
705 }
706 }
707
708 // Implementation
709 void Init()
710 {
711 T* pT = static_cast<T*>(this);
712 pT; // avoid level 4 warning
713 ATLASSERT((pT->GetExtendedLVStyle() & LVS_EX_CHECKBOXES) != 0);
714 SetExtendedListViewStyle(pT->GetExtendedLVStyle());
715 }
716
717 // Message map and handlers
718 BEGIN_MSG_MAP(CCheckListViewCtrlImpl)
719 MESSAGE_HANDLER(WM_CREATE, OnCreate)
720 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
721 MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDown)
722 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
723 END_MSG_MAP()
724
725 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
726 {
727 // first let list view control initialize everything
728 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
729 if(lRet == 0)
730 {
731 T* pT = static_cast<T*>(this);
732 pT->Init();
733 }
734
735 return lRet;
736 }
737
738 LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
739 {
740 POINT ptMsg = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
741 LVHITTESTINFO lvh = { 0 };
742 lvh.pt = ptMsg;
743 if(HitTest(&lvh) != -1 && lvh.flags == LVHT_ONITEMSTATEICON && ::GetKeyState(VK_CONTROL) >= 0)
744 {
745 T* pT = static_cast<T*>(this);
746 pT->CheckSelectedItems(lvh.iItem);
747 }
748 bHandled = FALSE;
749 return 1;
750 }
751
752 LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
753 {
754 if(wParam == VK_SPACE)
755 {
756 int nCurrItem = GetNextItem(-1, LVNI_FOCUSED);
757 if(nCurrItem != -1 && ::GetKeyState(VK_CONTROL) >= 0)
758 {
759 T* pT = static_cast<T*>(this);
760 pT->CheckSelectedItems(nCurrItem);
761 }
762 }
763 bHandled = FALSE;
764 return 1;
765 }
766 };
767
768 class CCheckListViewCtrl : public CCheckListViewCtrlImpl<CCheckListViewCtrl>
769 {
770 public:
771 DECLARE_WND_SUPERCLASS(_T("WTL_CheckListView"), GetWndClassName())
772 };
773
774
775 ///////////////////////////////////////////////////////////////////////////////
776 // CHyperLink - hyper link control implementation
777
778 #if (WINVER < 0x0500) && !defined(_WIN32_WCE)
779 __declspec(selectany) struct
780 {
781 enum { cxWidth = 32, cyHeight = 32 };
782 int xHotSpot;
783 int yHotSpot;
784 unsigned char arrANDPlane[cxWidth * cyHeight / 8];
785 unsigned char arrXORPlane[cxWidth * cyHeight / 8];
786 } _AtlHyperLink_CursorData =
787 {
788 5, 0,
789 {
790 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF,
791 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF,
792 0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF,
793 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF,
794 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF,
795 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
796 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
797 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
798 },
799 {
800 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
801 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00,
802 0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00,
803 0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00,
804 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00,
805 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
808 }
809 };
810 #endif // (WINVER < 0x0500) && !defined(_WIN32_WCE)
811
812 #define HLINK_UNDERLINED 0x00000000
813 #define HLINK_NOTUNDERLINED 0x00000001
814 #define HLINK_UNDERLINEHOVER 0x00000002
815 #define HLINK_COMMANDBUTTON 0x00000004
816 #define HLINK_NOTIFYBUTTON 0x0000000C
817 #define HLINK_USETAGS 0x00000010
818 #define HLINK_USETAGSBOLD 0x00000030
819 #define HLINK_NOTOOLTIP 0x00000040
820 #define HLINK_AUTOCREATELINKFONT 0x00000080
821 #define HLINK_SINGLELINE 0x00000100
822
823 // Notes:
824 // - HLINK_USETAGS and HLINK_USETAGSBOLD are always left-aligned
825 // - When HLINK_USETAGSBOLD is used, the underlined styles will be ignored
826
827 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
828 class ATL_NO_VTABLE CHyperLinkImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
829 {
830 public:
831 LPTSTR m_lpstrLabel;
832 LPTSTR m_lpstrHyperLink;
833
834 HCURSOR m_hCursor;
835 HFONT m_hFontLink;
836 HFONT m_hFontNormal;
837
838 RECT m_rcLink;
839 #ifndef _WIN32_WCE
840 CToolTipCtrl m_tip;
841 #endif // !_WIN32_WCE
842
843 COLORREF m_clrLink;
844 COLORREF m_clrVisited;
845
846 DWORD m_dwExtendedStyle; // Hyper Link specific extended styles
847
848 bool m_bPaintLabel:1;
849 bool m_bVisited:1;
850 bool m_bHover:1;
851 bool m_bInternalLinkFont:1;
852 bool m_bInternalNormalFont:1;
853
854
855 // Constructor/Destructor
856 CHyperLinkImpl(DWORD dwExtendedStyle = HLINK_UNDERLINED) :
857 m_lpstrLabel(NULL), m_lpstrHyperLink(NULL),
858 m_hCursor(NULL), m_hFontLink(NULL), m_hFontNormal(NULL),
859 m_clrLink(RGB(0, 0, 255)), m_clrVisited(RGB(128, 0, 128)),
860 m_dwExtendedStyle(dwExtendedStyle),
861 m_bPaintLabel(true), m_bVisited(false),
862 m_bHover(false), m_bInternalLinkFont(false), m_bInternalNormalFont(false)
863 {
864 ::SetRectEmpty(&m_rcLink);
865 }
866
867 ~CHyperLinkImpl()
868 {
869 delete [] m_lpstrLabel;
870 delete [] m_lpstrHyperLink;
871 #if (WINVER < 0x0500) && !defined(_WIN32_WCE)
872 // It was created, not loaded, so we have to destroy it
873 if(m_hCursor != NULL)
874 ::DestroyCursor(m_hCursor);
875 #endif // (WINVER < 0x0500) && !defined(_WIN32_WCE)
876 }
877
878 // Attributes
879 DWORD GetHyperLinkExtendedStyle() const
880 {
881 return m_dwExtendedStyle;
882 }
883
884 DWORD SetHyperLinkExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
885 {
886 DWORD dwPrevStyle = m_dwExtendedStyle;
887 if(dwMask == 0)
888 m_dwExtendedStyle = dwExtendedStyle;
889 else
890 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
891 return dwPrevStyle;
892 }
893
894 bool GetLabel(LPTSTR lpstrBuffer, int nLength) const
895 {
896 if(m_lpstrLabel == NULL)
897 return false;
898 ATLASSERT(lpstrBuffer != NULL);
899 if(nLength <= lstrlen(m_lpstrLabel))
900 return false;
901
902 SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrLabel);
903
904 return true;
905 }
906
907 bool SetLabel(LPCTSTR lpstrLabel)
908 {
909 delete [] m_lpstrLabel;
910 m_lpstrLabel = NULL;
911 int cchLen = lstrlen(lpstrLabel) + 1;
912 ATLTRY(m_lpstrLabel = new TCHAR[cchLen]);
913 if(m_lpstrLabel == NULL)
914 return false;
915
916 SecureHelper::strcpy_x(m_lpstrLabel, cchLen, lpstrLabel);
917 T* pT = static_cast<T*>(this);
918 pT->CalcLabelRect();
919
920 if(m_hWnd != NULL)
921 SetWindowText(lpstrLabel); // Set this for accessibility
922
923 return true;
924 }
925
926 bool GetHyperLink(LPTSTR lpstrBuffer, int nLength) const
927 {
928 if(m_lpstrHyperLink == NULL)
929 return false;
930 ATLASSERT(lpstrBuffer != NULL);
931 if(nLength <= lstrlen(m_lpstrHyperLink))
932 return false;
933
934 SecureHelper::strcpy_x(lpstrBuffer, nLength, m_lpstrHyperLink);
935
936 return true;
937 }
938
939 bool SetHyperLink(LPCTSTR lpstrLink)
940 {
941 delete [] m_lpstrHyperLink;
942 m_lpstrHyperLink = NULL;
943 int cchLen = lstrlen(lpstrLink) + 1;
944 ATLTRY(m_lpstrHyperLink = new TCHAR[cchLen]);
945 if(m_lpstrHyperLink == NULL)
946 return false;
947
948 SecureHelper::strcpy_x(m_lpstrHyperLink, cchLen, lpstrLink);
949 if(m_lpstrLabel == NULL)
950 {
951 T* pT = static_cast<T*>(this);
952 pT->CalcLabelRect();
953 }
954 #ifndef _WIN32_WCE
955 if(m_tip.IsWindow())
956 {
957 m_tip.Activate(TRUE);
958 m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
959 }
960 #endif // !_WIN32_WCE
961 return true;
962 }
963
964 HFONT GetLinkFont() const
965 {
966 return m_hFontLink;
967 }
968
969 void SetLinkFont(HFONT hFont)
970 {
971 if(m_bInternalLinkFont)
972 {
973 ::DeleteObject(m_hFontLink);
974 m_bInternalLinkFont = false;
975 }
976
977 m_hFontLink = hFont;
978
979 T* pT = static_cast<T*>(this);
980 pT->CalcLabelRect();
981 }
982
983 int GetIdealHeight() const
984 {
985 ATLASSERT(::IsWindow(m_hWnd));
986 if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
987 return -1;
988 if(!m_bPaintLabel)
989 return -1;
990
991 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
992
993 CClientDC dc(m_hWnd);
994 RECT rect = { 0 };
995 GetClientRect(&rect);
996 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
997 RECT rcText = rect;
998 dc.DrawText(_T("NS"), -1, &rcText, DT_LEFT | uFormat | DT_CALCRECT);
999 dc.SelectFont(m_hFontLink);
1000 RECT rcLink = rect;
1001 dc.DrawText(_T("NS"), -1, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
1002 dc.SelectFont(hFontOld);
1003 return __max(rcText.bottom - rcText.top, rcLink.bottom - rcLink.top);
1004 }
1005
1006 bool GetIdealSize(SIZE& size) const
1007 {
1008 int cx = 0, cy = 0;
1009 bool bRet = GetIdealSize(cx, cy);
1010 if(bRet)
1011 {
1012 size.cx = cx;
1013 size.cy = cy;
1014 }
1015 return bRet;
1016 }
1017
1018 bool GetIdealSize(int& cx, int& cy) const
1019 {
1020 ATLASSERT(::IsWindow(m_hWnd));
1021 if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
1022 return false;
1023 if(!m_bPaintLabel)
1024 return false;
1025
1026 CClientDC dc(m_hWnd);
1027 RECT rcClient = { 0 };
1028 GetClientRect(&rcClient);
1029 RECT rcAll = rcClient;
1030
1031 if(IsUsingTags())
1032 {
1033 // find tags and label parts
1034 LPTSTR lpstrLeft = NULL;
1035 int cchLeft = 0;
1036 LPTSTR lpstrLink = NULL;
1037 int cchLink = 0;
1038 LPTSTR lpstrRight = NULL;
1039 int cchRight = 0;
1040
1041 const T* pT = static_cast<const T*>(this);
1042 pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
1043
1044 // get label part rects
1045 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1046
1047 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
1048 RECT rcLeft = rcClient;
1049 dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | uFormat | DT_CALCRECT);
1050
1051 dc.SelectFont(m_hFontLink);
1052 RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom };
1053 dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
1054
1055 dc.SelectFont(m_hFontNormal);
1056 RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom };
1057 dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | uFormat | DT_CALCRECT);
1058
1059 dc.SelectFont(hFontOld);
1060
1061 int cyMax = __max(rcLeft.bottom, __max(rcLink.bottom, rcRight.bottom));
1062 ::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax);
1063 }
1064 else
1065 {
1066 HFONT hOldFont = NULL;
1067 if(m_hFontLink != NULL)
1068 hOldFont = dc.SelectFont(m_hFontLink);
1069 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1070 DWORD dwStyle = GetStyle();
1071 UINT uFormat = DT_LEFT;
1072 if (dwStyle & SS_CENTER)
1073 uFormat = DT_CENTER;
1074 else if (dwStyle & SS_RIGHT)
1075 uFormat = DT_RIGHT;
1076 uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1077 dc.DrawText(lpstrText, -1, &rcAll, uFormat | DT_CALCRECT);
1078 if(m_hFontLink != NULL)
1079 dc.SelectFont(hOldFont);
1080 if (dwStyle & SS_CENTER)
1081 {
1082 int dx = (rcClient.right - rcAll.right) / 2;
1083 ::OffsetRect(&rcAll, dx, 0);
1084 }
1085 else if (dwStyle & SS_RIGHT)
1086 {
1087 int dx = rcClient.right - rcAll.right;
1088 ::OffsetRect(&rcAll, dx, 0);
1089 }
1090 }
1091
1092 cx = rcAll.right - rcAll.left;
1093 cy = rcAll.bottom - rcAll.top;
1094
1095 return true;
1096 }
1097
1098 // for command buttons only
1099 bool GetToolTipText(LPTSTR lpstrBuffer, int nLength) const
1100 {
1101 ATLASSERT(IsCommandButton());
1102 return GetHyperLink(lpstrBuffer, nLength);
1103 }
1104
1105 bool SetToolTipText(LPCTSTR lpstrToolTipText)
1106 {
1107 ATLASSERT(IsCommandButton());
1108 return SetHyperLink(lpstrToolTipText);
1109 }
1110
1111 // Operations
1112 BOOL SubclassWindow(HWND hWnd)
1113 {
1114 ATLASSERT(m_hWnd == NULL);
1115 ATLASSERT(::IsWindow(hWnd));
1116 if(m_hFontNormal == NULL)
1117 m_hFontNormal = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
1118
1119 #if (_MSC_VER >= 1300)
1120 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1121 #else // !(_MSC_VER >= 1300)
1122 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1123 BOOL bRet = _baseClass::SubclassWindow(hWnd);
1124 #endif // !(_MSC_VER >= 1300)
1125 if(bRet != FALSE)
1126 {
1127 T* pT = static_cast<T*>(this);
1128 pT->Init();
1129 }
1130
1131 return bRet;
1132 }
1133
1134 bool Navigate()
1135 {
1136 ATLASSERT(::IsWindow(m_hWnd));
1137 bool bRet = true;
1138 if(IsNotifyButton())
1139 {
1140 NMHDR nmhdr = { m_hWnd, (UINT_PTR)GetDlgCtrlID(), NM_CLICK };
1141 ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
1142 }
1143 else if(IsCommandButton())
1144 {
1145 ::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
1146 }
1147 else
1148 {
1149 ATLASSERT(m_lpstrHyperLink != NULL);
1150 #ifndef _WIN32_WCE
1151 DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL);
1152 bRet = (dwRet > 32);
1153 #else // CE specific
1154 SHELLEXECUTEINFO shExeInfo = { sizeof(SHELLEXECUTEINFO), 0, 0, L"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 };
1155 ::ShellExecuteEx(&shExeInfo);
1156 DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp;
1157 bRet = (dwRet == 0) || (dwRet > 32);
1158 #endif // _WIN32_WCE
1159 ATLASSERT(bRet);
1160 if(bRet)
1161 {
1162 m_bVisited = true;
1163 Invalidate();
1164 }
1165 }
1166 return bRet;
1167 }
1168
1169 void CreateLinkFontFromNormal()
1170 {
1171 if(m_bInternalLinkFont)
1172 {
1173 ::DeleteObject(m_hFontLink);
1174 m_bInternalLinkFont = false;
1175 }
1176
1177 CFontHandle font = (m_hFontNormal != NULL) ? m_hFontNormal : (HFONT)::GetStockObject(SYSTEM_FONT);
1178 LOGFONT lf = { 0 };
1179 font.GetLogFont(&lf);
1180
1181 if(IsUsingTagsBold())
1182 lf.lfWeight = FW_BOLD;
1183 else if(!IsNotUnderlined())
1184 lf.lfUnderline = TRUE;
1185
1186 m_hFontLink = ::CreateFontIndirect(&lf);
1187 m_bInternalLinkFont = true;
1188 ATLASSERT(m_hFontLink != NULL);
1189 }
1190
1191 // Message map and handlers
1192 BEGIN_MSG_MAP(CHyperLinkImpl)
1193 MESSAGE_HANDLER(WM_CREATE, OnCreate)
1194 #ifndef _WIN32_WCE
1195 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
1196 MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
1197 #endif // !_WIN32_WCE
1198 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
1199 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1200 #ifndef _WIN32_WCE
1201 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1202 #endif // !_WIN32_WCE
1203 MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
1204 MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
1205 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
1206 #ifndef _WIN32_WCE
1207 MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
1208 #endif // !_WIN32_WCE
1209 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
1210 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
1211 MESSAGE_HANDLER(WM_CHAR, OnChar)
1212 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
1213 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
1214 MESSAGE_HANDLER(WM_ENABLE, OnEnable)
1215 MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
1216 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
1217 MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
1218 MESSAGE_HANDLER(WM_SIZE, OnSize)
1219 END_MSG_MAP()
1220
1221 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1222 {
1223 T* pT = static_cast<T*>(this);
1224 pT->Init();
1225 return 0;
1226 }
1227
1228 #ifndef _WIN32_WCE
1229 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1230 {
1231 if(m_tip.IsWindow())
1232 {
1233 m_tip.DestroyWindow();
1234 m_tip.m_hWnd = NULL;
1235 }
1236
1237 if(m_bInternalLinkFont)
1238 {
1239 ::DeleteObject(m_hFontLink);
1240 m_hFontLink = NULL;
1241 m_bInternalLinkFont = false;
1242 }
1243
1244 if(m_bInternalNormalFont)
1245 {
1246 ::DeleteObject(m_hFontNormal);
1247 m_hFontNormal = NULL;
1248 m_bInternalNormalFont = false;
1249 }
1250
1251 bHandled = FALSE;
1252 return 1;
1253 }
1254
1255 LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1256 {
1257 MSG msg = { m_hWnd, uMsg, wParam, lParam };
1258 if(m_tip.IsWindow() && IsUsingToolTip())
1259 m_tip.RelayEvent(&msg);
1260 bHandled = FALSE;
1261 return 1;
1262 }
1263 #endif // !_WIN32_WCE
1264
1265 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1266 {
1267 return 1; // no background painting needed (we do it all during WM_PAINT)
1268 }
1269
1270 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1271 {
1272 if(!m_bPaintLabel)
1273 {
1274 bHandled = FALSE;
1275 return 1;
1276 }
1277
1278 T* pT = static_cast<T*>(this);
1279 if(wParam != NULL)
1280 {
1281 pT->DoEraseBackground((HDC)wParam);
1282 pT->DoPaint((HDC)wParam);
1283 }
1284 else
1285 {
1286 CPaintDC dc(m_hWnd);
1287 pT->DoEraseBackground(dc.m_hDC);
1288 pT->DoPaint(dc.m_hDC);
1289 }
1290
1291 return 0;
1292 }
1293
1294 LRESULT OnFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1295 {
1296 if(m_bPaintLabel)
1297 Invalidate();
1298 else
1299 bHandled = FALSE;
1300 return 0;
1301 }
1302
1303 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1304 {
1305 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1306 if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
1307 {
1308 ::SetCursor(m_hCursor);
1309 if(IsUnderlineHover())
1310 {
1311 if(!m_bHover)
1312 {
1313 m_bHover = true;
1314 InvalidateRect(&m_rcLink);
1315 UpdateWindow();
1316 #ifndef _WIN32_WCE
1317 StartTrackMouseLeave();
1318 #endif // !_WIN32_WCE
1319 }
1320 }
1321 }
1322 else
1323 {
1324 if(IsUnderlineHover())
1325 {
1326 if(m_bHover)
1327 {
1328 m_bHover = false;
1329 InvalidateRect(&m_rcLink);
1330 UpdateWindow();
1331 }
1332 }
1333 bHandled = FALSE;
1334 }
1335 return 0;
1336 }
1337
1338 #ifndef _WIN32_WCE
1339 LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1340 {
1341 if(IsUnderlineHover() && m_bHover)
1342 {
1343 m_bHover = false;
1344 InvalidateRect(&m_rcLink);
1345 UpdateWindow();
1346 }
1347 return 0;
1348 }
1349 #endif // !_WIN32_WCE
1350
1351 LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
1352 {
1353 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1354 if(::PtInRect(&m_rcLink, pt))
1355 {
1356 SetFocus();
1357 SetCapture();
1358 }
1359 return 0;
1360 }
1361
1362 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
1363 {
1364 if(GetCapture() == m_hWnd)
1365 {
1366 ReleaseCapture();
1367 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1368 if(::PtInRect(&m_rcLink, pt))
1369 {
1370 T* pT = static_cast<T*>(this);
1371 pT->Navigate();
1372 }
1373 }
1374 return 0;
1375 }
1376
1377 LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1378 {
1379 if(wParam == VK_RETURN || wParam == VK_SPACE)
1380 {
1381 T* pT = static_cast<T*>(this);
1382 pT->Navigate();
1383 }
1384 return 0;
1385 }
1386
1387 LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1388 {
1389 return DLGC_WANTCHARS;
1390 }
1391
1392 LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1393 {
1394 POINT pt = { 0, 0 };
1395 GetCursorPos(&pt);
1396 ScreenToClient(&pt);
1397 if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
1398 {
1399 return TRUE;
1400 }
1401 bHandled = FALSE;
1402 return FALSE;
1403 }
1404
1405 LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1406 {
1407 Invalidate();
1408 UpdateWindow();
1409 return 0;
1410 }
1411
1412 LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1413 {
1414 return (LRESULT)m_hFontNormal;
1415 }
1416
1417 LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1418 {
1419 if(m_bInternalNormalFont)
1420 {
1421 ::DeleteObject(m_hFontNormal);
1422 m_bInternalNormalFont = false;
1423 }
1424
1425 bool bCreateLinkFont = m_bInternalLinkFont;
1426
1427 m_hFontNormal = (HFONT)wParam;
1428
1429 if(bCreateLinkFont || IsAutoCreateLinkFont())
1430 CreateLinkFontFromNormal();
1431
1432 T* pT = static_cast<T*>(this);
1433 pT->CalcLabelRect();
1434
1435 if((BOOL)lParam)
1436 {
1437 Invalidate();
1438 UpdateWindow();
1439 }
1440
1441 return 0;
1442 }
1443
1444 LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1445 {
1446 // If the control is subclassed or superclassed, this message can cause
1447 // repainting without WM_PAINT. We don't use this state, so just do nothing.
1448 return 0;
1449 }
1450
1451 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1452 {
1453 T* pT = static_cast<T*>(this);
1454 pT->CalcLabelRect();
1455 pT->Invalidate();
1456 return 0;
1457 }
1458
1459 // Implementation
1460 void Init()
1461 {
1462 ATLASSERT(::IsWindow(m_hWnd));
1463
1464 // Check if we should paint a label
1465 const int cchBuff = 8;
1466 TCHAR szBuffer[cchBuff] = { 0 };
1467 if(::GetClassName(m_hWnd, szBuffer, cchBuff))
1468 {
1469 if(lstrcmpi(szBuffer, _T("static")) == 0)
1470 {
1471 ModifyStyle(0, SS_NOTIFY); // we need this
1472 DWORD dwStyle = GetStyle() & 0x000000FF;
1473 #ifndef _WIN32_WCE
1474 if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT ||
1475 dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME ||
1476 dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW ||
1477 dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE)
1478 #else // CE specific
1479 if(dwStyle == SS_ICON || dwStyle == SS_BITMAP)
1480 #endif // _WIN32_WCE
1481 m_bPaintLabel = false;
1482 }
1483 }
1484
1485 // create or load a cursor
1486 #if (WINVER >= 0x0500) || defined(_WIN32_WCE)
1487 m_hCursor = ::LoadCursor(NULL, IDC_HAND);
1488 #else
1489 m_hCursor = ::CreateCursor(ModuleHelper::GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane);
1490 #endif
1491 ATLASSERT(m_hCursor != NULL);
1492
1493 // set fonts
1494 if(m_bPaintLabel)
1495 {
1496 if(m_hFontNormal == NULL)
1497 {
1498 m_hFontNormal = AtlCreateControlFont();
1499 m_bInternalNormalFont = true;
1500 }
1501
1502 if(m_hFontLink == NULL)
1503 CreateLinkFontFromNormal();
1504 }
1505
1506 #ifndef _WIN32_WCE
1507 // create a tool tip
1508 m_tip.Create(m_hWnd);
1509 ATLASSERT(m_tip.IsWindow());
1510 #endif // !_WIN32_WCE
1511
1512 // set label (defaults to window text)
1513 if(m_lpstrLabel == NULL)
1514 {
1515 int nLen = GetWindowTextLength();
1516 if(nLen > 0)
1517 {
1518 ATLTRY(m_lpstrLabel = new TCHAR[nLen + 1]);
1519 if(m_lpstrLabel != NULL)
1520 ATLVERIFY(GetWindowText(m_lpstrLabel, nLen + 1) > 0);
1521 }
1522 }
1523
1524 T* pT = static_cast<T*>(this);
1525 pT->CalcLabelRect();
1526
1527 // set hyperlink (defaults to label), or just activate tool tip if already set
1528 if(m_lpstrHyperLink == NULL && !IsCommandButton())
1529 {
1530 if(m_lpstrLabel != NULL)
1531 SetHyperLink(m_lpstrLabel);
1532 }
1533 #ifndef _WIN32_WCE
1534 else
1535 {
1536 m_tip.Activate(TRUE);
1537 m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
1538 }
1539 #endif // !_WIN32_WCE
1540
1541 // set link colors
1542 if(m_bPaintLabel)
1543 {
1544 CRegKeyEx rk;
1545 LONG lRet = rk.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Internet Explorer\\Settings"));
1546 if(lRet == ERROR_SUCCESS)
1547 {
1548 const int cchValue = 12;
1549 TCHAR szValue[cchValue] = { 0 };
1550 ULONG ulCount = cchValue;
1551 lRet = rk.QueryStringValue(_T("Anchor Color"), szValue, &ulCount);
1552 if(lRet == ERROR_SUCCESS)
1553 {
1554 COLORREF clr = pT->_ParseColorString(szValue);
1555 ATLASSERT(clr != CLR_INVALID);
1556 if(clr != CLR_INVALID)
1557 m_clrLink = clr;
1558 }
1559
1560 ulCount = cchValue;
1561 lRet = rk.QueryStringValue(_T("Anchor Color Visited"), szValue, &ulCount);
1562 if(lRet == ERROR_SUCCESS)
1563 {
1564 COLORREF clr = pT->_ParseColorString(szValue);
1565 ATLASSERT(clr != CLR_INVALID);
1566 if(clr != CLR_INVALID)
1567 m_clrVisited = clr;
1568 }
1569 }
1570 }
1571 }
1572
1573 static COLORREF _ParseColorString(LPTSTR lpstr)
1574 {
1575 int c[3] = { -1, -1, -1 };
1576 LPTSTR p = NULL;
1577 for(int i = 0; i < 2; i++)
1578 {
1579 for(p = lpstr; *p != _T('\0'); p = ::CharNext(p))
1580 {
1581 if(*p == _T(','))
1582 {
1583 *p = _T('\0');
1584 c[i] = MinCrtHelper::_atoi(lpstr);
1585 lpstr = &p[1];
1586 break;
1587 }
1588 }
1589 if(c[i] == -1)
1590 return CLR_INVALID;
1591 }
1592 if(*lpstr == _T('\0'))
1593 return CLR_INVALID;
1594 c[2] = MinCrtHelper::_atoi(lpstr);
1595
1596 return RGB(c[0], c[1], c[2]);
1597 }
1598
1599 bool CalcLabelRect()
1600 {
1601 if(!::IsWindow(m_hWnd))
1602 return false;
1603 if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
1604 return false;
1605
1606 CClientDC dc(m_hWnd);
1607 RECT rcClient = { 0 };
1608 GetClientRect(&rcClient);
1609 m_rcLink = rcClient;
1610 if(!m_bPaintLabel)
1611 return true;
1612
1613 if(IsUsingTags())
1614 {
1615 // find tags and label parts
1616 LPTSTR lpstrLeft = NULL;
1617 int cchLeft = 0;
1618 LPTSTR lpstrLink = NULL;
1619 int cchLink = 0;
1620 LPTSTR lpstrRight = NULL;
1621 int cchRight = 0;
1622
1623 T* pT = static_cast<T*>(this);
1624 pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
1625 ATLASSERT(lpstrLink != NULL);
1626 ATLASSERT(cchLink > 0);
1627
1628 // get label part rects
1629 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
1630
1631 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1632
1633 RECT rcLeft = rcClient;
1634 if(lpstrLeft != NULL)
1635 dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | uFormat | DT_CALCRECT);
1636
1637 dc.SelectFont(m_hFontLink);
1638 RECT rcLink = rcClient;
1639 if(lpstrLeft != NULL)
1640 rcLink.left = rcLeft.right;
1641 dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | uFormat | DT_CALCRECT);
1642
1643 dc.SelectFont(hFontOld);
1644
1645 m_rcLink = rcLink;
1646 }
1647 else
1648 {
1649 HFONT hOldFont = NULL;
1650 if(m_hFontLink != NULL)
1651 hOldFont = dc.SelectFont(m_hFontLink);
1652 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1653 DWORD dwStyle = GetStyle();
1654 UINT uFormat = DT_LEFT;
1655 if (dwStyle & SS_CENTER)
1656 uFormat = DT_CENTER;
1657 else if (dwStyle & SS_RIGHT)
1658 uFormat = DT_RIGHT;
1659 uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1660 dc.DrawText(lpstrText, -1, &m_rcLink, uFormat | DT_CALCRECT);
1661 if(m_hFontLink != NULL)
1662 dc.SelectFont(hOldFont);
1663 if (dwStyle & SS_CENTER)
1664 {
1665 int dx = (rcClient.right - m_rcLink.right) / 2;
1666 ::OffsetRect(&m_rcLink, dx, 0);
1667 }
1668 else if (dwStyle & SS_RIGHT)
1669 {
1670 int dx = rcClient.right - m_rcLink.right;
1671 ::OffsetRect(&m_rcLink, dx, 0);
1672 }
1673 }
1674
1675 return true;
1676 }
1677
1678 void CalcLabelParts(LPTSTR& lpstrLeft, int& cchLeft, LPTSTR& lpstrLink, int& cchLink, LPTSTR& lpstrRight, int& cchRight) const
1679 {
1680 lpstrLeft = NULL;
1681 cchLeft = 0;
1682 lpstrLink = NULL;
1683 cchLink = 0;
1684 lpstrRight = NULL;
1685 cchRight = 0;
1686
1687 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1688 int cchText = lstrlen(lpstrText);
1689 bool bOutsideLink = true;
1690 for(int i = 0; i < cchText; i++)
1691 {
1692 if(lpstrText[i] != _T('<'))
1693 continue;
1694
1695 if(bOutsideLink)
1696 {
1697 if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T("<A>"), 3) == CSTR_EQUAL)
1698 {
1699 if(i > 0)
1700 {
1701 lpstrLeft = lpstrText;
1702 cchLeft = i;
1703 }
1704 lpstrLink = &lpstrText[i + 3];
1705 bOutsideLink = false;
1706 }
1707 }
1708 else
1709 {
1710 if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T("</A>"), 4) == CSTR_EQUAL)
1711 {
1712 cchLink = i - 3 - cchLeft;
1713 if(lpstrText[i + 4] != 0)
1714 {
1715 lpstrRight = &lpstrText[i + 4];
1716 cchRight = cchText - (i + 4);
1717 break;
1718 }
1719 }
1720 }
1721 }
1722
1723 }
1724
1725 void DoEraseBackground(CDCHandle dc)
1726 {
1727 HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd);
1728 if(hBrush != NULL)
1729 {
1730 RECT rect = { 0 };
1731 GetClientRect(&rect);
1732 dc.FillRect(&rect, hBrush);
1733 }
1734 }
1735
1736 void DoPaint(CDCHandle dc)
1737 {
1738 if(IsUsingTags())
1739 {
1740 // find tags and label parts
1741 LPTSTR lpstrLeft = NULL;
1742 int cchLeft = 0;
1743 LPTSTR lpstrLink = NULL;
1744 int cchLink = 0;
1745 LPTSTR lpstrRight = NULL;
1746 int cchRight = 0;
1747
1748 T* pT = static_cast<T*>(this);
1749 pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
1750
1751 // get label part rects
1752 RECT rcClient = { 0 };
1753 GetClientRect(&rcClient);
1754
1755 dc.SetBkMode(TRANSPARENT);
1756 HFONT hFontOld = dc.SelectFont(m_hFontNormal);
1757
1758 UINT uFormat = IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1759
1760 if(lpstrLeft != NULL)
1761 dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | uFormat);
1762
1763 COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
1764 if(m_hFontLink != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
1765 dc.SelectFont(m_hFontLink);
1766 else
1767 dc.SelectFont(m_hFontNormal);
1768
1769 dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | uFormat);
1770
1771 dc.SetTextColor(clrOld);
1772 dc.SelectFont(m_hFontNormal);
1773 if(lpstrRight != NULL)
1774 {
1775 RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom };
1776 dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | uFormat);
1777 }
1778
1779 if(GetFocus() == m_hWnd)
1780 dc.DrawFocusRect(&m_rcLink);
1781
1782 dc.SelectFont(hFontOld);
1783 }
1784 else
1785 {
1786 dc.SetBkMode(TRANSPARENT);
1787 COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
1788
1789 HFONT hFontOld = NULL;
1790 if(m_hFontLink != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
1791 hFontOld = dc.SelectFont(m_hFontLink);
1792 else
1793 hFontOld = dc.SelectFont(m_hFontNormal);
1794
1795 LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
1796
1797 DWORD dwStyle = GetStyle();
1798 UINT uFormat = DT_LEFT;
1799 if (dwStyle & SS_CENTER)
1800 uFormat = DT_CENTER;
1801 else if (dwStyle & SS_RIGHT)
1802 uFormat = DT_RIGHT;
1803 uFormat |= IsSingleLine() ? DT_SINGLELINE : DT_WORDBREAK;
1804
1805 dc.DrawText(lpstrText, -1, &m_rcLink, uFormat);
1806
1807 if(GetFocus() == m_hWnd)
1808 dc.DrawFocusRect(&m_rcLink);
1809
1810 dc.SetTextColor(clrOld);
1811 dc.SelectFont(hFontOld);
1812 }
1813 }
1814
1815 #ifndef _WIN32_WCE
1816 BOOL StartTrackMouseLeave()
1817 {
1818 TRACKMOUSEEVENT tme = { 0 };
1819 tme.cbSize = sizeof(tme);
1820 tme.dwFlags = TME_LEAVE;
1821 tme.hwndTrack = m_hWnd;
1822 return _TrackMouseEvent(&tme);
1823 }
1824 #endif // !_WIN32_WCE
1825
1826 // Implementation helpers
1827 bool IsUnderlined() const
1828 {
1829 return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0);
1830 }
1831
1832 bool IsNotUnderlined() const
1833 {
1834 return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0);
1835 }
1836
1837 bool IsUnderlineHover() const
1838 {
1839 return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0);
1840 }
1841
1842 bool IsCommandButton() const
1843 {
1844 return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0);
1845 }
1846
1847 bool IsNotifyButton() const
1848 {
1849 return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON);
1850 }
1851
1852 bool IsUsingTags() const
1853 {
1854 return ((m_dwExtendedStyle & HLINK_USETAGS) != 0);
1855 }
1856
1857 bool IsUsingTagsBold() const
1858 {
1859 return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD);
1860 }
1861
1862 bool IsUsingToolTip() const
1863 {
1864 return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0);
1865 }
1866
1867 bool IsAutoCreateLinkFont() const
1868 {
1869 return ((m_dwExtendedStyle & HLINK_AUTOCREATELINKFONT) == HLINK_AUTOCREATELINKFONT);
1870 }
1871
1872 bool IsSingleLine() const
1873 {
1874 return ((m_dwExtendedStyle & HLINK_SINGLELINE) == HLINK_SINGLELINE);
1875 }
1876 };
1877
1878 class CHyperLink : public CHyperLinkImpl<CHyperLink>
1879 {
1880 public:
1881 DECLARE_WND_CLASS(_T("WTL_HyperLink"))
1882 };
1883
1884
1885 ///////////////////////////////////////////////////////////////////////////////
1886 // CWaitCursor - displays a wait cursor
1887
1888 class CWaitCursor
1889 {
1890 public:
1891 // Data
1892 HCURSOR m_hWaitCursor;
1893 HCURSOR m_hOldCursor;
1894 bool m_bInUse;
1895
1896 // Constructor/destructor
1897 CWaitCursor(bool bSet = true, LPCTSTR lpstrCursor = IDC_WAIT, bool bSys = true) : m_hOldCursor(NULL), m_bInUse(false)
1898 {
1899 HINSTANCE hInstance = bSys ? NULL : ModuleHelper::GetResourceInstance();
1900 m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor);
1901 ATLASSERT(m_hWaitCursor != NULL);
1902
1903 if(bSet)
1904 Set();
1905 }
1906
1907 ~CWaitCursor()
1908 {
1909 Restore();
1910 }
1911
1912 // Methods
1913 bool Set()
1914 {
1915 if(m_bInUse)
1916 return false;
1917 m_hOldCursor = ::SetCursor(m_hWaitCursor);
1918 m_bInUse = true;
1919 return true;
1920 }
1921
1922 bool Restore()
1923 {
1924 if(!m_bInUse)
1925 return false;
1926 ::SetCursor(m_hOldCursor);
1927 m_bInUse = false;
1928 return true;
1929 }
1930 };
1931
1932
1933 ///////////////////////////////////////////////////////////////////////////////
1934 // CCustomWaitCursor - for custom and animated cursors
1935
1936 class CCustomWaitCursor : public CWaitCursor
1937 {
1938 public:
1939 // Constructor/destructor
1940 CCustomWaitCursor(ATL::_U_STRINGorID cursor, bool bSet = true, HINSTANCE hInstance = NULL) :
1941 CWaitCursor(false, IDC_WAIT, true)
1942 {
1943 if(hInstance == NULL)
1944 hInstance = ModuleHelper::GetResourceInstance();
1945 m_hWaitCursor = (HCURSOR)::LoadImage(hInstance, cursor.m_lpstr, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
1946
1947 if(bSet)
1948 Set();
1949 }
1950
1951 ~CCustomWaitCursor()
1952 {
1953 Restore();
1954 #if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
1955 ::DestroyCursor(m_hWaitCursor);
1956 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
1957 }
1958 };
1959
1960
1961 ///////////////////////////////////////////////////////////////////////////////
1962 // CMultiPaneStatusBarCtrl - Status Bar with multiple panes
1963
1964 template <class T, class TBase = CStatusBarCtrl>
1965 class ATL_NO_VTABLE CMultiPaneStatusBarCtrlImpl : public ATL::CWindowImpl< T, TBase >
1966 {
1967 public:
1968 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
1969
1970 // Data
1971 enum { m_cxPaneMargin = 3 };
1972
1973 int m_nPanes;
1974 int* m_pPane;
1975
1976 // Constructor/destructor
1977 CMultiPaneStatusBarCtrlImpl() : m_nPanes(0), m_pPane(NULL)
1978 { }
1979
1980 ~CMultiPaneStatusBarCtrlImpl()
1981 {
1982 delete [] m_pPane;
1983 }
1984
1985 // Methods
1986 HWND Create(HWND hWndParent, LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
1987 {
1988 #if (_MSC_VER >= 1300)
1989 return ATL::CWindowImpl< T, TBase >::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
1990 #else // !(_MSC_VER >= 1300)
1991 typedef ATL::CWindowImpl< T, TBase > _baseClass;
1992 return _baseClass::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
1993 #endif // !(_MSC_VER >= 1300)
1994 }
1995
1996 HWND Create(HWND hWndParent, UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
1997 {
1998 const int cchMax = 128; // max text length is 127 for status bars (+1 for null)
1999 TCHAR szText[cchMax] = { 0 };
2000 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
2001 return Create(hWndParent, szText, dwStyle, nID);
2002 }
2003
2004 BOOL SetPanes(int* pPanes, int nPanes, bool bSetText = true)
2005 {
2006 ATLASSERT(::IsWindow(m_hWnd));
2007 ATLASSERT(nPanes > 0);
2008
2009 m_nPanes = nPanes;
2010 delete [] m_pPane;
2011 m_pPane = NULL;
2012
2013 ATLTRY(m_pPane = new int[nPanes]);
2014 ATLASSERT(m_pPane != NULL);
2015 if(m_pPane == NULL)
2016 return FALSE;
2017
2018 CTempBuffer<int, _WTL_STACK_ALLOC_THRESHOLD> buff;
2019 int* pPanesPos = buff.Allocate(nPanes);
2020 ATLASSERT(pPanesPos != NULL);
2021 if(pPanesPos == NULL)
2022 return FALSE;
2023
2024 SecureHelper::memcpy_x(m_pPane, nPanes * sizeof(int), pPanes, nPanes * sizeof(int));
2025
2026 // get status bar DC and set font
2027 CClientDC dc(m_hWnd);
2028 HFONT hOldFont = dc.SelectFont(GetFont());
2029
2030 // get status bar borders
2031 int arrBorders[3] = { 0 };
2032 GetBorders(arrBorders);
2033
2034 const int cchBuff = 128;
2035 TCHAR szBuff[cchBuff] = { 0 };
2036 SIZE size = { 0, 0 };
2037 int cxLeft = arrBorders[0];
2038
2039 // calculate right edge of each part
2040 for(int i = 0; i < nPanes; i++)
2041 {
2042 if(pPanes[i] == ID_DEFAULT_PANE)
2043 {
2044 // make very large, will be resized later
2045 pPanesPos[i] = INT_MAX / 2;
2046 }
2047 else
2048 {
2049 ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff);
2050 dc.GetTextExtent(szBuff, lstrlen(szBuff), &size);
2051 T* pT = static_cast<T*>(this);
2052 pT;
2053 pPanesPos[i] = cxLeft + size.cx + arrBorders[2] + 2 * pT->m_cxPaneMargin;
2054 }
2055 cxLeft = pPanesPos[i];
2056 }
2057
2058 BOOL bRet = SetParts(nPanes, pPanesPos);
2059
2060 if(bRet && bSetText)
2061 {
2062 for(int i = 0; i < nPanes; i++)
2063 {
2064 if(pPanes[i] != ID_DEFAULT_PANE)
2065 {
2066 ::LoadString(ModuleHelper::GetResourceInstance(), pPanes[i], szBuff, cchBuff);
2067 SetPaneText(m_pPane[i], szBuff);
2068 }
2069 }
2070 }
2071
2072 dc.SelectFont(hOldFont);
2073 return bRet;
2074 }
2075
2076 bool GetPaneTextLength(int nPaneID, int* pcchLength = NULL, int* pnType = NULL) const
2077 {
2078 ATLASSERT(::IsWindow(m_hWnd));
2079 int nIndex = GetPaneIndexFromID(nPaneID);
2080 if(nIndex == -1)
2081 return false;
2082
2083 int nLength = GetTextLength(nIndex, pnType);
2084 if(pcchLength != NULL)
2085 *pcchLength = nLength;
2086
2087 return true;
2088 }
2089
2090 BOOL GetPaneText(int nPaneID, LPTSTR lpstrText, int* pcchLength = NULL, int* pnType = NULL) const
2091 {
2092 ATLASSERT(::IsWindow(m_hWnd));
2093 int nIndex = GetPaneIndexFromID(nPaneID);
2094 if(nIndex == -1)
2095 return FALSE;
2096
2097 int nLength = GetText(nIndex, lpstrText, pnType);
2098 if(pcchLength != NULL)
2099 *pcchLength = nLength;
2100
2101 return TRUE;
2102 }
2103
2104 BOOL SetPaneText(int nPaneID, LPCTSTR lpstrText, int nType = 0)
2105 {
2106 ATLASSERT(::IsWindow(m_hWnd));
2107 int nIndex = GetPaneIndexFromID(nPaneID);
2108 if(nIndex == -1)
2109 return FALSE;
2110
2111 return SetText(nIndex, lpstrText, nType);
2112 }
2113
2114 BOOL GetPaneRect(int nPaneID, LPRECT lpRect) const
2115 {
2116 ATLASSERT(::IsWindow(m_hWnd));
2117 int nIndex = GetPaneIndexFromID(nPaneID);
2118 if(nIndex == -1)
2119 return FALSE;
2120
2121 return GetRect(nIndex, lpRect);
2122 }
2123
2124 BOOL SetPaneWidth(int nPaneID, int cxWidth)
2125 {
2126 ATLASSERT(::IsWindow(m_hWnd));
2127 ATLASSERT(nPaneID != ID_DEFAULT_PANE); // Can't resize this one
2128 int nIndex = GetPaneIndexFromID(nPaneID);
2129 if(nIndex == -1)
2130 return FALSE;
2131
2132 // get pane positions
2133 CTempBuffer<int, _WTL_STACK_ALLOC_THRESHOLD> buff;
2134 int* pPanesPos = buff.Allocate(m_nPanes);
2135 if(pPanesPos == NULL)
2136 return FALSE;
2137 GetParts(m_nPanes, pPanesPos);
2138 // calculate offset
2139 int cxPaneWidth = pPanesPos[nIndex] - ((nIndex == 0) ? 0 : pPanesPos[nIndex - 1]);
2140 int cxOff = cxWidth - cxPaneWidth;
2141 // find variable width pane
2142 int nDef = m_nPanes;
2143 for(int i = 0; i < m_nPanes; i++)
2144 {
2145 if(m_pPane[i] == ID_DEFAULT_PANE)
2146 {
2147 nDef = i;
2148 break;
2149 }
2150 }
2151 // resize
2152 if(nIndex < nDef) // before default pane
2153 {
2154 for(int i = nIndex; i < nDef; i++)
2155 pPanesPos[i] += cxOff;
2156
2157 }
2158 else // after default one
2159 {
2160 for(int i = nDef; i < nIndex; i++)
2161 pPanesPos[i] -= cxOff;
2162 }
2163 // set pane postions
2164 return SetParts(m_nPanes, pPanesPos);
2165 }
2166
2167 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
2168 BOOL GetPaneTipText(int nPaneID, LPTSTR lpstrText, int nSize) const
2169 {
2170 ATLASSERT(::IsWindow(m_hWnd));
2171 int nIndex = GetPaneIndexFromID(nPaneID);
2172 if(nIndex == -1)
2173 return FALSE;
2174
2175 GetTipText(nIndex, lpstrText, nSize);
2176 return TRUE;
2177 }
2178
2179 BOOL SetPaneTipText(int nPaneID, LPCTSTR lpstrText)
2180 {
2181 ATLASSERT(::IsWindow(m_hWnd));
2182 int nIndex = GetPaneIndexFromID(nPaneID);
2183 if(nIndex == -1)
2184 return FALSE;
2185
2186 SetTipText(nIndex, lpstrText);
2187 return TRUE;
2188 }
2189 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
2190
2191 #if ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
2192 BOOL GetPaneIcon(int nPaneID, HICON& hIcon) const
2193 {
2194 ATLASSERT(::IsWindow(m_hWnd));
2195 int nIndex = GetPaneIndexFromID(nPaneID);
2196 if(nIndex == -1)
2197 return FALSE;
2198
2199 hIcon = GetIcon(nIndex);
2200 return TRUE;
2201 }
2202
2203 BOOL SetPaneIcon(int nPaneID, HICON hIcon)
2204 {
2205 ATLASSERT(::IsWindow(m_hWnd));
2206 int nIndex = GetPaneIndexFromID(nPaneID);
2207 if(nIndex == -1)
2208 return FALSE;
2209
2210 return SetIcon(nIndex, hIcon);
2211 }
2212 #endif // ((_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)) || (defined(_WIN32_WCE) && (_WIN32_WCE >= 0x0500))
2213
2214 // Message map and handlers
2215 BEGIN_MSG_MAP(CMultiPaneStatusBarCtrlImpl< T >)
2216 MESSAGE_HANDLER(WM_SIZE, OnSize)
2217 END_MSG_MAP()
2218
2219 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
2220 {
2221 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
2222 if(wParam != SIZE_MINIMIZED && m_nPanes > 0)
2223 {
2224 T* pT = static_cast<T*>(this);
2225 pT->UpdatePanesLayout();
2226 }
2227 return lRet;
2228 }
2229
2230 // Implementation
2231 BOOL UpdatePanesLayout()
2232 {
2233 // get pane positions
2234 CTempBuffer<int, _WTL_STACK_ALLOC_THRESHOLD> buff;
2235 int* pPanesPos = buff.Allocate(m_nPanes);
2236 ATLASSERT(pPanesPos != NULL);
2237 if(pPanesPos == NULL)
2238 return FALSE;
2239 int nRet = GetParts(m_nPanes, pPanesPos);
2240 ATLASSERT(nRet == m_nPanes);
2241 if(nRet != m_nPanes)
2242 return FALSE;
2243 // calculate offset
2244 RECT rcClient = { 0 };
2245 GetClientRect(&rcClient);
2246 int cxOff = rcClient.right - pPanesPos[m_nPanes - 1];
2247 #ifndef _WIN32_WCE
2248 // Move panes left if size grip box is present
2249 if((GetStyle() & SBARS_SIZEGRIP) != 0)
2250 cxOff -= ::GetSystemMetrics(SM_CXVSCROLL) + ::GetSystemMetrics(SM_CXEDGE);
2251 #endif // !_WIN32_WCE
2252 // find variable width pane
2253 int i;
2254 for(i = 0; i < m_nPanes; i++)
2255 {
2256 if(m_pPane[i] == ID_DEFAULT_PANE)
2257 break;
2258 }
2259 // resize all panes from the variable one to the right
2260 if((i < m_nPanes) && (pPanesPos[i] + cxOff) > ((i == 0) ? 0 : pPanesPos[i - 1]))
2261 {
2262 for(; i < m_nPanes; i++)
2263 pPanesPos[i] += cxOff;
2264 }
2265 // set pane postions
2266 return SetParts(m_nPanes, pPanesPos);
2267 }
2268
2269 int GetPaneIndexFromID(int nPaneID) const
2270 {
2271 for(int i = 0; i < m_nPanes; i++)
2272 {
2273 if(m_pPane[i] == nPaneID)
2274 return i;
2275 }
2276
2277 return -1; // not found
2278 }
2279 };
2280
2281 class CMultiPaneStatusBarCtrl : public CMultiPaneStatusBarCtrlImpl<CMultiPaneStatusBarCtrl>
2282 {
2283 public:
2284 DECLARE_WND_SUPERCLASS(_T("WTL_MultiPaneStatusBar"), GetWndClassName())
2285 };
2286
2287
2288 ///////////////////////////////////////////////////////////////////////////////
2289 // CPaneContainer - provides header with title and close button for panes
2290
2291 // pane container extended styles
2292 #define PANECNT_NOCLOSEBUTTON 0x00000001
2293 #define PANECNT_VERTICAL 0x00000002
2294 #define PANECNT_FLATBORDER 0x00000004
2295 #define PANECNT_NOBORDER 0x00000008
2296 #define PANECNT_DIVIDER 0x00000010
2297 #define PANECNT_GRADIENT 0x00000020
2298
2299 // Note: PANECNT_GRADIENT doesn't work with _ATL_NO_MSIMG
2300
2301 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
2302 class ATL_NO_VTABLE CPaneContainerImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CCustomDraw< T >
2303 {
2304 public:
2305 DECLARE_WND_CLASS_EX(NULL, 0, -1)
2306
2307 // Constants
2308 enum
2309 {
2310 m_cxyBorder = 2,
2311 m_cxyTextOffset = 4,
2312 m_cxyBtnOffset = 1,
2313
2314 m_cchTitle = 80,
2315
2316 m_cxImageTB = 13,
2317 m_cyImageTB = 11,
2318 m_cxyBtnAddTB = 7,
2319
2320 m_cxToolBar = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + m_cxyBtnOffset,
2321
2322 m_xBtnImageLeft = 6,
2323 m_yBtnImageTop = 5,
2324 m_xBtnImageRight = 12,
2325 m_yBtnImageBottom = 11,
2326
2327 m_nCloseBtnID = ID_PANE_CLOSE
2328 };
2329
2330 // Data members
2331 CToolBarCtrl m_tb;
2332 ATL::CWindow m_wndClient;
2333 int m_cxyHeader;
2334 TCHAR m_szTitle[m_cchTitle];
2335 DWORD m_dwExtendedStyle; // Pane container specific extended styles
2336 HFONT m_hFont;
2337 bool m_bInternalFont;
2338
2339
2340 // Constructor
2341 CPaneContainerImpl() : m_cxyHeader(0), m_dwExtendedStyle(0), m_hFont(NULL), m_bInternalFont(false)
2342 {
2343 m_szTitle[0] = 0;
2344 }
2345
2346 // Attributes
2347 DWORD GetPaneContainerExtendedStyle() const
2348 {
2349 return m_dwExtendedStyle;
2350 }
2351
2352 DWORD SetPaneContainerExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
2353 {
2354 DWORD dwPrevStyle = m_dwExtendedStyle;
2355 if(dwMask == 0)
2356 m_dwExtendedStyle = dwExtendedStyle;
2357 else
2358 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
2359 if(m_hWnd != NULL)
2360 {
2361 T* pT = static_cast<T*>(this);
2362 bool bUpdate = false;
2363
2364 if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) != 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)) // add close button
2365 {
2366 pT->CreateCloseButton();
2367 bUpdate = true;
2368 }
2369 else if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) == 0) && ((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) != 0)) // remove close button
2370 {
2371 pT->DestroyCloseButton();
2372 bUpdate = true;
2373 }
2374
2375 if((dwPrevStyle & PANECNT_VERTICAL) != (m_dwExtendedStyle & PANECNT_VERTICAL)) // change orientation
2376 {
2377 pT->CalcSize();
2378 bUpdate = true;
2379 }
2380
2381 if((dwPrevStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER)) !=
2382 (m_dwExtendedStyle & (PANECNT_FLATBORDER | PANECNT_NOBORDER))) // change border
2383 {
2384 bUpdate = true;
2385 }
2386
2387 #if (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420)
2388 if((dwPrevStyle & PANECNT_GRADIENT) != (m_dwExtendedStyle & PANECNT_GRADIENT)) // change background
2389 {
2390 bUpdate = true;
2391 }
2392 #endif // (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420)
2393
2394 if(bUpdate)
2395 pT->UpdateLayout();
2396 }
2397 return dwPrevStyle;
2398 }
2399
2400 HWND GetClient() const
2401 {
2402 return m_wndClient;
2403 }
2404
2405 HWND SetClient(HWND hWndClient)
2406 {
2407 HWND hWndOldClient = m_wndClient;
2408 m_wndClient = hWndClient;
2409 if(m_hWnd != NULL)
2410 {
2411 T* pT = static_cast<T*>(this);
2412 pT->UpdateLayout();
2413 }
2414 return hWndOldClient;
2415 }
2416
2417 BOOL GetTitle(LPTSTR lpstrTitle, int cchLength) const
2418 {
2419 ATLASSERT(lpstrTitle != NULL);
2420
2421 errno_t nRet = SecureHelper::strncpy_x(lpstrTitle, cchLength, m_szTitle, _TRUNCATE);
2422
2423 return (nRet == 0 || nRet == STRUNCATE);
2424 }
2425
2426 BOOL SetTitle(LPCTSTR lpstrTitle)
2427 {
2428 ATLASSERT(lpstrTitle != NULL);
2429
2430 errno_t nRet = SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE);
2431 bool bRet = (nRet == 0 || nRet == STRUNCATE);
2432 if(bRet && m_hWnd != NULL)
2433 {
2434 T* pT = static_cast<T*>(this);
2435 pT->UpdateLayout();
2436 }
2437
2438 return bRet;
2439 }
2440
2441 int GetTitleLength() const
2442 {
2443 return lstrlen(m_szTitle);
2444 }
2445
2446 // Methods
2447 HWND Create(HWND hWndParent, LPCTSTR lpstrTitle = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2448 DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
2449 {
2450 if(lpstrTitle != NULL)
2451 SecureHelper::strncpy_x(m_szTitle, m_cchTitle, lpstrTitle, _TRUNCATE);
2452 #if (_MSC_VER >= 1300)
2453 return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2454 #else // !(_MSC_VER >= 1300)
2455 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
2456 return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2457 #endif // !(_MSC_VER >= 1300)
2458 }
2459
2460 HWND Create(HWND hWndParent, UINT uTitleID, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2461 DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
2462 {
2463 if(uTitleID != 0U)
2464 ::LoadString(ModuleHelper::GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle);
2465 #if (_MSC_VER >= 1300)
2466 return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2467 #else // !(_MSC_VER >= 1300)
2468 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
2469 return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
2470 #endif // !(_MSC_VER >= 1300)
2471 }
2472
2473 BOOL SubclassWindow(HWND hWnd)
2474 {
2475 #if (_MSC_VER >= 1300)
2476 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
2477 #else // !(_MSC_VER >= 1300)
2478 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
2479 BOOL bRet = _baseClass::SubclassWindow(hWnd);
2480 #endif // !(_MSC_VER >= 1300)
2481 if(bRet != FALSE)
2482 {
2483 T* pT = static_cast<T*>(this);
2484 pT->Init();
2485
2486 RECT rect = { 0 };
2487 GetClientRect(&rect);
2488 pT->UpdateLayout(rect.right, rect.bottom);
2489 }
2490
2491 return bRet;
2492 }
2493
2494 BOOL EnableCloseButton(BOOL bEnable)
2495 {
2496 ATLASSERT(::IsWindow(m_hWnd));
2497 T* pT = static_cast<T*>(this);
2498 pT; // avoid level 4 warning
2499 return (m_tb.m_hWnd != NULL) ? m_tb.EnableButton(pT->m_nCloseBtnID, bEnable) : FALSE;
2500 }
2501
2502 void UpdateLayout()
2503 {
2504 RECT rcClient = { 0 };
2505 GetClientRect(&rcClient);
2506 T* pT = static_cast<T*>(this);
2507 pT->UpdateLayout(rcClient.right, rcClient.bottom);
2508 }
2509
2510 // Message map and handlers
2511 BEGIN_MSG_MAP(CPaneContainerImpl)
2512 MESSAGE_HANDLER(WM_CREATE, OnCreate)
2513 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
2514 MESSAGE_HANDLER(WM_SIZE, OnSize)
2515 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
2516 MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
2517 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
2518 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
2519 MESSAGE_HANDLER(WM_PAINT, OnPaint)
2520 #ifndef _WIN32_WCE
2521 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
2522 #endif // !_WIN32_WCE
2523 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
2524 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
2525 FORWARD_NOTIFICATIONS()
2526 END_MSG_MAP()
2527
2528 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2529 {
2530 T* pT = static_cast<T*>(this);
2531 pT->Init();
2532
2533 return 0;
2534 }
2535
2536 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2537 {
2538 if(m_bInternalFont)
2539 {
2540 ::DeleteObject(m_hFont);
2541 m_hFont = NULL;
2542 m_bInternalFont = false;
2543 }
2544
2545 return 0;
2546 }
2547
2548 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
2549 {
2550 T* pT = static_cast<T*>(this);
2551 pT->UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
2552 return 0;
2553 }
2554
2555 LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2556 {
2557 if(m_wndClient.m_hWnd != NULL)
2558 m_wndClient.SetFocus();
2559 return 0;
2560 }
2561
2562 LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2563 {
2564 return (LRESULT)m_hFont;
2565 }
2566
2567 LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
2568 {
2569 if(m_bInternalFont)
2570 {
2571 ::DeleteObject(m_hFont);
2572 m_bInternalFont = false;
2573 }
2574
2575 m_hFont = (HFONT)wParam;
2576
2577 T* pT = static_cast<T*>(this);
2578 pT->CalcSize();
2579
2580 if((BOOL)lParam != FALSE)
2581 pT->UpdateLayout();
2582
2583 return 0;
2584 }
2585
2586 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2587 {
2588 T* pT = static_cast<T*>(this);
2589 pT->DrawPaneTitleBackground((HDC)wParam);
2590
2591 return 1;
2592 }
2593
2594 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2595 {
2596 T* pT = static_cast<T*>(this);
2597 if(wParam != NULL)
2598 {
2599 pT->DrawPaneTitle((HDC)wParam);
2600
2601 if(m_wndClient.m_hWnd == NULL) // no client window
2602 pT->DrawPane((HDC)wParam);
2603 }
2604 else
2605 {
2606 CPaintDC dc(m_hWnd);
2607 pT->DrawPaneTitle(dc.m_hDC);
2608
2609 if(m_wndClient.m_hWnd == NULL) // no client window
2610 pT->DrawPane(dc.m_hDC);
2611 }
2612
2613 return 0;
2614 }
2615
2616 LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
2617 {
2618 if(m_tb.m_hWnd == NULL)
2619 {
2620 bHandled = FALSE;
2621 return 1;
2622 }
2623
2624 T* pT = static_cast<T*>(this);
2625 pT;
2626 LPNMHDR lpnmh = (LPNMHDR)lParam;
2627 LRESULT lRet = 0;
2628
2629 // pass toolbar custom draw notifications to the base class
2630 if(lpnmh->code == NM_CUSTOMDRAW && lpnmh->hwndFrom == m_tb.m_hWnd)
2631 lRet = CCustomDraw< T >::OnCustomDraw(0, lpnmh, bHandled);
2632 #ifndef _WIN32_WCE
2633 // tooltip notifications come with the tooltip window handle and button ID,
2634 // pass them to the parent if we don't handle them
2635 else if(lpnmh->code == TTN_GETDISPINFO && lpnmh->idFrom == pT->m_nCloseBtnID)
2636 bHandled = pT->GetToolTipText(lpnmh);
2637 #endif // !_WIN32_WCE
2638 // only let notifications not from the toolbar go to the parent
2639 else if(lpnmh->hwndFrom != m_tb.m_hWnd && lpnmh->idFrom != pT->m_nCloseBtnID)
2640 bHandled = FALSE;
2641
2642 return lRet;
2643 }
2644
2645 LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2646 {
2647 // if command comes from the close button, substitute HWND of the pane container instead
2648 if(m_tb.m_hWnd != NULL && (HWND)lParam == m_tb.m_hWnd)
2649 return ::SendMessage(GetParent(), WM_COMMAND, wParam, (LPARAM)m_hWnd);
2650
2651 bHandled = FALSE;
2652 return 1;
2653 }
2654
2655 // Custom draw overrides
2656 DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
2657 {
2658 return CDRF_NOTIFYITEMDRAW; // we need per-item notifications
2659 }
2660
2661 DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
2662 {
2663 return CDRF_NOTIFYPOSTPAINT;
2664 }
2665
2666 DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
2667 {
2668 CDCHandle dc = lpNMCustomDraw->hdc;
2669 #if (_WIN32_IE >= 0x0400)
2670 RECT& rc = lpNMCustomDraw->rc;
2671 #else // !(_WIN32_IE >= 0x0400)
2672 RECT rc = { 0 };
2673 m_tb.GetItemRect(0, &rc);
2674 #endif // !(_WIN32_IE >= 0x0400)
2675
2676 RECT rcImage = { m_xBtnImageLeft, m_yBtnImageTop, m_xBtnImageRight + 1, m_yBtnImageBottom + 1 };
2677 ::OffsetRect(&rcImage, rc.left, rc.top);
2678 T* pT = static_cast<T*>(this);
2679
2680 if((lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0)
2681 {
2682 RECT rcShadow = rcImage;
2683 ::OffsetRect(&rcShadow, 1, 1);
2684 CPen pen1;
2685 pen1.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
2686 pT->DrawButtonImage(dc, rcShadow, pen1);
2687 CPen pen2;
2688 pen2.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
2689 pT->DrawButtonImage(dc, rcImage, pen2);
2690 }
2691 else
2692 {
2693 if((lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0)
2694 ::OffsetRect(&rcImage, 1, 1);
2695 CPen pen;
2696 pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT));
2697 pT->DrawButtonImage(dc, rcImage, pen);
2698 }
2699
2700 return CDRF_DODEFAULT; // continue with the default item painting
2701 }
2702
2703 // Implementation - overrideable methods
2704 void Init()
2705 {
2706 if(m_hFont == NULL)
2707 {
2708 // The same as AtlCreateControlFont() for horizontal pane
2709 #ifndef _WIN32_WCE
2710 LOGFONT lf = { 0 };
2711 ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
2712 if(IsVertical())
2713 lf.lfEscapement = 900; // 90 degrees
2714 m_hFont = ::CreateFontIndirect(&lf);
2715 #else // CE specific
2716 m_hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
2717 if(IsVertical())
2718 {
2719 CLogFont lf(m_hFont);
2720 lf.lfEscapement = 900; // 90 degrees
2721 m_hFont = ::CreateFontIndirect(&lf);
2722 }
2723 #endif // _WIN32_WCE
2724 m_bInternalFont = true;
2725 }
2726
2727 T* pT = static_cast<T*>(this);
2728 pT->CalcSize();
2729
2730 if((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)
2731 pT->CreateCloseButton();
2732 }
2733
2734 void UpdateLayout(int cxWidth, int cyHeight)
2735 {
2736 ATLASSERT(::IsWindow(m_hWnd));
2737 RECT rect = { 0 };
2738
2739 if(IsVertical())
2740 {
2741 ::SetRect(&rect, 0, 0, m_cxyHeader, cyHeight);
2742 if(m_tb.m_hWnd != NULL)
2743 m_tb.SetWindowPos(NULL, m_cxyBorder, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
2744
2745 if(m_wndClient.m_hWnd != NULL)
2746 m_wndClient.SetWindowPos(NULL, m_cxyHeader, 0, cxWidth - m_cxyHeader, cyHeight, SWP_NOZORDER);
2747 else
2748 rect.right = cxWidth;
2749 }
2750 else
2751 {
2752 ::SetRect(&rect, 0, 0, cxWidth, m_cxyHeader);
2753 if(m_tb.m_hWnd != NULL)
2754 m_tb.SetWindowPos(NULL, rect.right - m_cxToolBar, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
2755
2756 if(m_wndClient.m_hWnd != NULL)
2757 m_wndClient.SetWindowPos(NULL, 0, m_cxyHeader, cxWidth, cyHeight - m_cxyHeader, SWP_NOZORDER);
2758 else
2759 rect.bottom = cyHeight;
2760 }
2761
2762 InvalidateRect(&rect);
2763 }
2764
2765 void CreateCloseButton()
2766 {
2767 ATLASSERT(m_tb.m_hWnd == NULL);
2768 // create toolbar for the "x" button
2769 m_tb.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NOMOVEY | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0);
2770 ATLASSERT(m_tb.IsWindow());
2771
2772 if(m_tb.m_hWnd != NULL)
2773 {
2774 T* pT = static_cast<T*>(this);
2775 pT; // avoid level 4 warning
2776
2777 m_tb.SetButtonStructSize();
2778
2779 TBBUTTON tbbtn = { 0 };
2780 tbbtn.idCommand = pT->m_nCloseBtnID;
2781 tbbtn.fsState = TBSTATE_ENABLED;
2782 tbbtn.fsStyle = BTNS_BUTTON;
2783 m_tb.AddButtons(1, &tbbtn);
2784
2785 m_tb.SetBitmapSize(m_cxImageTB, m_cyImageTB);
2786 m_tb.SetButtonSize(m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB);
2787
2788 if(IsVertical())
2789 m_tb.SetWindowPos(NULL, m_cxyBorder + m_cxyBtnOffset, m_cxyBorder + m_cxyBtnOffset, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB + 1, SWP_NOZORDER | SWP_NOACTIVATE);
2790 else
2791 m_tb.SetWindowPos(NULL, 0, 0, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB + 1, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
2792 }
2793 }
2794
2795 void DestroyCloseButton()
2796 {
2797 if(m_tb.m_hWnd != NULL)
2798 m_tb.DestroyWindow();
2799 }
2800
2801 void CalcSize()
2802 {
2803 T* pT = static_cast<T*>(this);
2804 CFontHandle font = pT->GetTitleFont();
2805 if(font.IsNull())
2806 font = (HFONT)::GetStockObject(SYSTEM_FONT);
2807 LOGFONT lf = { 0 };
2808 font.GetLogFont(lf);
2809 if(IsVertical())
2810 {
2811 m_cxyHeader = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + 1;
2812 }
2813 else
2814 {
2815 int cyFont = abs(lf.lfHeight) + m_cxyBorder + 2 * m_cxyTextOffset;
2816 int cyBtn = m_cyImageTB + m_cxyBtnAddTB + m_cxyBorder + 2 * m_cxyBtnOffset + 1;
2817 m_cxyHeader = __max(cyFont, cyBtn);
2818 }
2819 }
2820
2821 HFONT GetTitleFont() const
2822 {
2823 return m_hFont;
2824 }
2825
2826 #ifndef _WIN32_WCE
2827 BOOL GetToolTipText(LPNMHDR /*lpnmh*/)
2828 {
2829 return FALSE;
2830 }
2831 #endif // !_WIN32_WCE
2832
2833 void DrawPaneTitle(CDCHandle dc)
2834 {
2835 RECT rect = { 0 };
2836 GetClientRect(&rect);
2837
2838 UINT uBorder = BF_LEFT | BF_TOP | BF_ADJUST;
2839 if(IsVertical())
2840 {
2841 rect.right = rect.left + m_cxyHeader;
2842 uBorder |= BF_BOTTOM;
2843 }
2844 else
2845 {
2846 rect.bottom = rect.top + m_cxyHeader;
2847 uBorder |= BF_RIGHT;
2848 }
2849
2850 if((m_dwExtendedStyle & PANECNT_NOBORDER) == 0)
2851 {
2852 if((m_dwExtendedStyle & PANECNT_FLATBORDER) != 0)
2853 uBorder |= BF_FLAT;
2854 dc.DrawEdge(&rect, EDGE_ETCHED, uBorder);
2855 }
2856
2857 if((m_dwExtendedStyle & PANECNT_DIVIDER) != 0)
2858 {
2859 uBorder = BF_FLAT | BF_ADJUST | (IsVertical() ? BF_RIGHT : BF_BOTTOM);
2860 dc.DrawEdge(&rect, BDR_SUNKENOUTER, uBorder);
2861 }
2862
2863 // draw title text
2864 dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
2865 dc.SetBkMode(TRANSPARENT);
2866 T* pT = static_cast<T*>(this);
2867 HFONT hFontOld = dc.SelectFont(pT->GetTitleFont());
2868 #if defined(_WIN32_WCE) && !defined(DT_END_ELLIPSIS)
2869 const UINT DT_END_ELLIPSIS = 0;
2870 #endif // defined(_WIN32_WCE) && !defined(DT_END_ELLIPSIS)
2871
2872 if(IsVertical())
2873 {
2874 rect.top += m_cxyTextOffset;
2875 rect.bottom -= m_cxyTextOffset;
2876 if(m_tb.m_hWnd != NULL)
2877 rect.top += m_cxToolBar;;
2878
2879 RECT rcCalc = { rect.left, rect.bottom, rect.right, rect.top };
2880 int cxFont = dc.DrawText(m_szTitle, -1, &rcCalc, DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS | DT_CALCRECT);
2881 RECT rcText = { 0 };
2882 rcText.left = (rect.right - rect.left - cxFont) / 2;
2883 rcText.right = rcText.left + (rect.bottom - rect.top);
2884 rcText.top = rect.bottom;
2885 rcText.bottom = rect.top;
2886 dc.DrawText(m_szTitle, -1, &rcText, DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS);
2887 }
2888 else
2889 {
2890 rect.left += m_cxyTextOffset;
2891 rect.right -= m_cxyTextOffset;
2892 if(m_tb.m_hWnd != NULL)
2893 rect.right -= m_cxToolBar;;
2894
2895 dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
2896 }
2897
2898 dc.SelectFont(hFontOld);
2899 }
2900
2901 void DrawPaneTitleBackground(CDCHandle dc)
2902 {
2903 RECT rect = { 0 };
2904 GetClientRect(&rect);
2905 if(IsVertical())
2906 rect.right = m_cxyHeader;
2907 else
2908 rect.bottom = m_cxyHeader;
2909
2910 #if (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420)
2911 if((m_dwExtendedStyle & PANECNT_GRADIENT) != 0)
2912 dc.GradientFillRect(rect, ::GetSysColor(COLOR_WINDOW), ::GetSysColor(COLOR_3DFACE), IsVertical());
2913 else
2914 #endif // (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420)
2915 dc.FillRect(&rect, COLOR_3DFACE);
2916 }
2917
2918 // called only if pane is empty
2919 void DrawPane(CDCHandle dc)
2920 {
2921 RECT rect = { 0 };
2922 GetClientRect(&rect);
2923 if(IsVertical())
2924 rect.left += m_cxyHeader;
2925 else
2926 rect.top += m_cxyHeader;
2927 if((GetExStyle() & WS_EX_CLIENTEDGE) == 0)
2928 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
2929 dc.FillRect(&rect, COLOR_APPWORKSPACE);
2930 }
2931
2932 // drawing helper - draws "x" button image
2933 void DrawButtonImage(CDCHandle dc, RECT& rcImage, HPEN hPen)
2934 {
2935 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
2936 HPEN hPenOld = dc.SelectPen(hPen);
2937
2938 dc.MoveTo(rcImage.left, rcImage.top);
2939 dc.LineTo(rcImage.right, rcImage.bottom);
2940 dc.MoveTo(rcImage.left + 1, rcImage.top);
2941 dc.LineTo(rcImage.right + 1, rcImage.bottom);
2942
2943 dc.MoveTo(rcImage.left, rcImage.bottom - 1);
2944 dc.LineTo(rcImage.right, rcImage.top - 1);
2945 dc.MoveTo(rcImage.left + 1, rcImage.bottom - 1);
2946 dc.LineTo(rcImage.right + 1, rcImage.top - 1);
2947
2948 dc.SelectPen(hPenOld);
2949 #else // (_WIN32_WCE < 400)
2950 rcImage;
2951 hPen;
2952 // no support for the "x" button image
2953 #endif // (_WIN32_WCE < 400)
2954 }
2955
2956 bool IsVertical() const
2957 {
2958 return ((m_dwExtendedStyle & PANECNT_VERTICAL) != 0);
2959 }
2960 };
2961
2962 class CPaneContainer : public CPaneContainerImpl<CPaneContainer>
2963 {
2964 public:
2965 DECLARE_WND_CLASS_EX(_T("WTL_PaneContainer"), 0, -1)
2966 };
2967
2968
2969 ///////////////////////////////////////////////////////////////////////////////
2970 // CSortListViewCtrl - implements sorting for a listview control
2971
2972 // sort listview extended styles
2973 #define SORTLV_USESHELLBITMAPS 0x00000001
2974
2975 // Notification sent to parent when sort column is changed by user clicking header.
2976 #define SLVN_SORTCHANGED LVN_LAST
2977
2978 // A LPNMSORTLISTVIEW is sent with the SLVN_SORTCHANGED notification
2979 typedef struct tagNMSORTLISTVIEW
2980 {
2981 NMHDR hdr;
2982 int iNewSortColumn;
2983 int iOldSortColumn;
2984 } NMSORTLISTVIEW, *LPNMSORTLISTVIEW;
2985
2986 // Column sort types. Can be set on a per-column basis with the SetColumnSortType method.
2987 enum
2988 {
2989 LVCOLSORT_NONE,
2990 LVCOLSORT_TEXT, // default
2991 LVCOLSORT_TEXTNOCASE,
2992 LVCOLSORT_LONG,
2993 LVCOLSORT_DOUBLE,
2994 LVCOLSORT_DECIMAL,
2995 LVCOLSORT_DATETIME,
2996 LVCOLSORT_DATE,
2997 LVCOLSORT_TIME,
2998 LVCOLSORT_CUSTOM,
2999 LVCOLSORT_LAST = LVCOLSORT_CUSTOM
3000 };
3001
3002
3003 template <class T>
3004 class CSortListViewImpl
3005 {
3006 public:
3007 enum
3008 {
3009 m_cchCmpTextMax = 32, // overrideable
3010 m_cxSortImage = 16,
3011 m_cySortImage = 15,
3012 m_cxSortArrow = 11,
3013 m_cySortArrow = 6,
3014 m_iSortUp = 0, // index of sort bitmaps
3015 m_iSortDown = 1,
3016 m_nShellSortUpID = 133
3017 };
3018
3019 // passed to LVCompare functions as lParam1 and lParam2
3020 struct LVCompareParam
3021 {
3022 int iItem;
3023 DWORD_PTR dwItemData;
3024 union
3025 {
3026 long lValue;
3027 double dblValue;
3028 DECIMAL decValue;
3029 LPCTSTR pszValue;
3030 };
3031 };
3032
3033 // passed to LVCompare functions as the lParamSort parameter
3034 struct LVSortInfo
3035 {
3036 T* pT;
3037 int iSortCol;
3038 bool bDescending;
3039 };
3040
3041 bool m_bSortDescending;
3042 bool m_bCommCtrl6;
3043 int m_iSortColumn;
3044 CBitmap m_bmSort[2];
3045 int m_fmtOldSortCol;
3046 HBITMAP m_hbmOldSortCol;
3047 DWORD m_dwSortLVExtendedStyle;
3048 ATL::CSimpleArray<WORD> m_arrColSortType;
3049 bool m_bUseWaitCursor;
3050
3051 CSortListViewImpl() :
3052 m_bSortDescending(false),
3053 m_bCommCtrl6(false),
3054 m_iSortColumn(-1),
3055 m_fmtOldSortCol(0),
3056 m_hbmOldSortCol(NULL),
3057 m_dwSortLVExtendedStyle(SORTLV_USESHELLBITMAPS),
3058 m_bUseWaitCursor(true)
3059 {
3060 #ifndef _WIN32_WCE
3061 DWORD dwMajor = 0;
3062 DWORD dwMinor = 0;
3063 HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
3064 m_bCommCtrl6 = SUCCEEDED(hRet) && dwMajor >= 6;
3065 #endif // !_WIN32_WCE
3066 }
3067
3068 // Attributes
3069 void SetSortColumn(int iCol)
3070 {
3071 T* pT = static_cast<T*>(this);
3072 ATLASSERT(::IsWindow(pT->m_hWnd));
3073 CHeaderCtrl header = pT->GetHeader();
3074 ATLASSERT(header.m_hWnd != NULL);
3075 ATLASSERT(iCol >= -1 && iCol < m_arrColSortType.GetSize());
3076
3077 int iOldSortCol = m_iSortColumn;
3078 m_iSortColumn = iCol;
3079 if(m_bCommCtrl6)
3080 {
3081 #ifndef HDF_SORTUP
3082 const int HDF_SORTUP = 0x0400;
3083 #endif // HDF_SORTUP
3084 #ifndef HDF_SORTDOWN
3085 const int HDF_SORTDOWN = 0x0200;
3086 #endif // HDF_SORTDOWN
3087 const int nMask = HDF_SORTUP | HDF_SORTDOWN;
3088 HDITEM hditem = { HDI_FORMAT };
3089 if(iOldSortCol != iCol && iOldSortCol >= 0 && header.GetItem(iOldSortCol, &hditem))
3090 {
3091 hditem.fmt &= ~nMask;
3092 header.SetItem(iOldSortCol, &hditem);
3093 }
3094 if(iCol >= 0 && header.GetItem(iCol, &hditem))
3095 {
3096 hditem.fmt &= ~nMask;
3097 hditem.fmt |= m_bSortDescending ? HDF_SORTDOWN : HDF_SORTUP;
3098 header.SetItem(iCol, &hditem);
3099 }
3100 return;
3101 }
3102
3103 if(m_bmSort[m_iSortUp].IsNull())
3104 pT->CreateSortBitmaps();
3105
3106 // restore previous sort column's bitmap, if any, and format
3107 HDITEM hditem = { HDI_BITMAP | HDI_FORMAT };
3108 if(iOldSortCol != iCol && iOldSortCol >= 0)
3109 {
3110 hditem.hbm = m_hbmOldSortCol;
3111 hditem.fmt = m_fmtOldSortCol;
3112 header.SetItem(iOldSortCol, &hditem);
3113 }
3114
3115 // save new sort column's bitmap and format, and add our sort bitmap
3116 if(iCol >= 0 && header.GetItem(iCol, &hditem))
3117 {
3118 if(iOldSortCol != iCol)
3119 {
3120 m_fmtOldSortCol = hditem.fmt;
3121 m_hbmOldSortCol = hditem.hbm;
3122 }
3123 hditem.fmt &= ~HDF_IMAGE;
3124 hditem.fmt |= HDF_BITMAP | HDF_BITMAP_ON_RIGHT;
3125 int i = m_bSortDescending ? m_iSortDown : m_iSortUp;
3126 hditem.hbm = m_bmSort[i];
3127 header.SetItem(iCol, &hditem);
3128 }
3129 }
3130
3131 int GetSortColumn() const
3132 {
3133 return m_iSortColumn;
3134 }
3135
3136 void SetColumnSortType(int iCol, WORD wType)
3137 {
3138 ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize());
3139 ATLASSERT(wType >= LVCOLSORT_NONE && wType <= LVCOLSORT_LAST);
3140 m_arrColSortType[iCol] = wType;
3141 }
3142
3143 WORD GetColumnSortType(int iCol) const
3144 {
3145 ATLASSERT((iCol >= 0) && iCol < m_arrColSortType.GetSize());
3146 return m_arrColSortType[iCol];
3147 }
3148
3149 int GetColumnCount() const
3150 {
3151 const T* pT = static_cast<const T*>(this);
3152 ATLASSERT(::IsWindow(pT->m_hWnd));
3153 CHeaderCtrl header = pT->GetHeader();
3154 return header.m_hWnd != NULL ? header.GetItemCount() : 0;
3155 }
3156
3157 bool IsSortDescending() const
3158 {
3159 return m_bSortDescending;
3160 }
3161
3162 DWORD GetSortListViewExtendedStyle() const
3163 {
3164 return m_dwSortLVExtendedStyle;
3165 }
3166
3167 DWORD SetSortListViewExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
3168 {
3169 DWORD dwPrevStyle = m_dwSortLVExtendedStyle;
3170 if(dwMask == 0)
3171 m_dwSortLVExtendedStyle = dwExtendedStyle;
3172 else
3173 m_dwSortLVExtendedStyle = (m_dwSortLVExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
3174 return dwPrevStyle;
3175 }
3176
3177 // Operations
3178 bool DoSortItems(int iCol, bool bDescending = false)
3179 {
3180 T* pT = static_cast<T*>(this);
3181 ATLASSERT(::IsWindow(pT->m_hWnd));
3182 ATLASSERT(iCol >= 0 && iCol < m_arrColSortType.GetSize());
3183
3184 WORD wType = m_arrColSortType[iCol];
3185 if(wType == LVCOLSORT_NONE)
3186 return false;
3187
3188 int nCount = pT->GetItemCount();
3189 if(nCount < 2)
3190 {
3191 m_bSortDescending = bDescending;
3192 SetSortColumn(iCol);
3193 return true;
3194 }
3195
3196 CWaitCursor waitCursor(false);
3197 if(m_bUseWaitCursor)
3198 waitCursor.Set();
3199
3200 LVCompareParam* pParam = NULL;
3201 ATLTRY(pParam = new LVCompareParam[nCount]);
3202 PFNLVCOMPARE pFunc = NULL;
3203 TCHAR pszTemp[pT->m_cchCmpTextMax] = { 0 };
3204 bool bStrValue = false;
3205
3206 switch(wType)
3207 {
3208 case LVCOLSORT_TEXT:
3209 pFunc = (PFNLVCOMPARE)pT->LVCompareText;
3210 case LVCOLSORT_TEXTNOCASE:
3211 if(pFunc == NULL)
3212 pFunc = (PFNLVCOMPARE)pT->LVCompareTextNoCase;
3213 case LVCOLSORT_CUSTOM:
3214 {
3215 if(pFunc == NULL)
3216 pFunc = (PFNLVCOMPARE)pT->LVCompareCustom;
3217
3218 for(int i = 0; i < nCount; i++)
3219 {
3220 pParam[i].iItem = i;
3221 pParam[i].dwItemData = pT->GetItemData(i);
3222 pParam[i].pszValue = new TCHAR[pT->m_cchCmpTextMax];
3223 pT->GetItemText(i, iCol, (LPTSTR)pParam[i].pszValue, pT->m_cchCmpTextMax);
3224 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3225 }
3226 bStrValue = true;
3227 }
3228 break;
3229 case LVCOLSORT_LONG:
3230 {
3231 pFunc = (PFNLVCOMPARE)pT->LVCompareLong;
3232 for(int i = 0; i < nCount; i++)
3233 {
3234 pParam[i].iItem = i;
3235 pParam[i].dwItemData = pT->GetItemData(i);
3236 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3237 pParam[i].lValue = pT->StrToLong(pszTemp);
3238 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3239 }
3240 }
3241 break;
3242 case LVCOLSORT_DOUBLE:
3243 {
3244 pFunc = (PFNLVCOMPARE)pT->LVCompareDouble;
3245 for(int i = 0; i < nCount; i++)
3246 {
3247 pParam[i].iItem = i;
3248 pParam[i].dwItemData = pT->GetItemData(i);
3249 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3250 pParam[i].dblValue = pT->StrToDouble(pszTemp);
3251 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3252 }
3253 }
3254 break;
3255 case LVCOLSORT_DECIMAL:
3256 {
3257 pFunc = (PFNLVCOMPARE)pT->LVCompareDecimal;
3258 for(int i = 0; i < nCount; i++)
3259 {
3260 pParam[i].iItem = i;
3261 pParam[i].dwItemData = pT->GetItemData(i);
3262 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3263 pT->StrToDecimal(pszTemp, &pParam[i].decValue);
3264 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3265 }
3266 }
3267 break;
3268 case LVCOLSORT_DATETIME:
3269 case LVCOLSORT_DATE:
3270 case LVCOLSORT_TIME:
3271 {
3272 pFunc = (PFNLVCOMPARE)pT->LVCompareDouble;
3273 DWORD dwFlags = LOCALE_NOUSEROVERRIDE;
3274 if(wType == LVCOLSORT_DATE)
3275 dwFlags |= VAR_DATEVALUEONLY;
3276 else if(wType == LVCOLSORT_TIME)
3277 dwFlags |= VAR_TIMEVALUEONLY;
3278 for(int i = 0; i < nCount; i++)
3279 {
3280 pParam[i].iItem = i;
3281 pParam[i].dwItemData = pT->GetItemData(i);
3282 pT->GetItemText(i, iCol, pszTemp, pT->m_cchCmpTextMax);
3283 pParam[i].dblValue = pT->DateStrToDouble(pszTemp, dwFlags);
3284 pT->SetItemData(i, (DWORD_PTR)&pParam[i]);
3285 }
3286 }
3287 break;
3288 default:
3289 ATLTRACE2(atlTraceUI, 0, _T("Unknown value for sort type in CSortListViewImpl::DoSortItems()\n"));
3290 break;
3291 } // switch(wType)
3292
3293 ATLASSERT(pFunc != NULL);
3294 LVSortInfo lvsi = { pT, iCol, bDescending };
3295 bool bRet = ((BOOL)pT->DefWindowProc(LVM_SORTITEMS, (WPARAM)&lvsi, (LPARAM)pFunc) != FALSE);
3296 for(int i = 0; i < nCount; i++)
3297 {
3298 DWORD_PTR dwItemData = pT->GetItemData(i);
3299 LVCompareParam* p = (LVCompareParam*)dwItemData;
3300 ATLASSERT(p != NULL);
3301 if(bStrValue)
3302 delete [] (TCHAR*)p->pszValue;
3303 pT->SetItemData(i, p->dwItemData);
3304 }
3305 delete [] pParam;
3306
3307 if(bRet)
3308 {
3309 m_bSortDescending = bDescending;
3310 SetSortColumn(iCol);
3311 }
3312
3313 if(m_bUseWaitCursor)
3314 waitCursor.Restore();
3315
3316 return bRet;
3317 }
3318
3319 void CreateSortBitmaps()
3320 {
3321 if((m_dwSortLVExtendedStyle & SORTLV_USESHELLBITMAPS) != 0)
3322 {
3323 bool bFree = false;
3324 LPCTSTR pszModule = _T("shell32.dll");
3325 HINSTANCE hShell = ::GetModuleHandle(pszModule);
3326
3327 if (hShell == NULL)
3328 {
3329 hShell = ::LoadLibrary(pszModule);
3330 bFree = true;
3331 }
3332
3333 if (hShell != NULL)
3334 {
3335 bool bSuccess = true;
3336 for(int i = m_iSortUp; i <= m_iSortDown; i++)
3337 {
3338 if(!m_bmSort[i].IsNull())
3339 m_bmSort[i].DeleteObject();
3340 m_bmSort[i] = (HBITMAP)::LoadImage(hShell, MAKEINTRESOURCE(m_nShellSortUpID + i),
3341 #ifndef _WIN32_WCE
3342 IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
3343 #else // CE specific
3344 IMAGE_BITMAP, 0, 0, 0);
3345 #endif // _WIN32_WCE
3346 if(m_bmSort[i].IsNull())
3347 {
3348 bSuccess = false;
3349 break;
3350 }
3351 }
3352 if(bFree)
3353 ::FreeLibrary(hShell);
3354 if(bSuccess)
3355 return;
3356 }
3357 }
3358
3359 T* pT = static_cast<T*>(this);
3360 for(int i = m_iSortUp; i <= m_iSortDown; i++)
3361 {
3362 if(!m_bmSort[i].IsNull())
3363 m_bmSort[i].DeleteObject();
3364
3365 CDC dcMem;
3366 CClientDC dc(::GetDesktopWindow());
3367 dcMem.CreateCompatibleDC(dc.m_hDC);
3368 m_bmSort[i].CreateCompatibleBitmap(dc.m_hDC, m_cxSortImage, m_cySortImage);
3369 HBITMAP hbmOld = dcMem.SelectBitmap(m_bmSort[i]);
3370 RECT rc = { 0, 0, m_cxSortImage, m_cySortImage };
3371 pT->DrawSortBitmap(dcMem.m_hDC, i, &rc);
3372 dcMem.SelectBitmap(hbmOld);
3373 dcMem.DeleteDC();
3374 }
3375 }
3376
3377 void NotifyParentSortChanged(int iNewSortCol, int iOldSortCol)
3378 {
3379 T* pT = static_cast<T*>(this);
3380 int nID = pT->GetDlgCtrlID();
3381 NMSORTLISTVIEW nm = { { pT->m_hWnd, (UINT_PTR)nID, SLVN_SORTCHANGED }, iNewSortCol, iOldSortCol };
3382 ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nID, (LPARAM)&nm);
3383 }
3384
3385 // Overrideables
3386 int CompareItemsCustom(LVCompareParam* /*pItem1*/, LVCompareParam* /*pItem2*/, int /*iSortCol*/)
3387 {
3388 // pItem1 and pItem2 contain valid iItem, dwItemData, and pszValue members.
3389 // If item1 > item2 return 1, if item1 < item2 return -1, else return 0.
3390 return 0;
3391 }
3392
3393 void DrawSortBitmap(CDCHandle dc, int iBitmap, LPRECT prc)
3394 {
3395 dc.FillRect(prc, ::GetSysColorBrush(COLOR_BTNFACE));
3396 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
3397 CPen pen;
3398 pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNSHADOW));
3399 HPEN hpenOld = dc.SelectPen(pen);
3400 POINT ptOrg = { (m_cxSortImage - m_cxSortArrow) / 2, (m_cySortImage - m_cySortArrow) / 2 };
3401 if(iBitmap == m_iSortUp)
3402 {
3403 POINT pts[3] =
3404 {
3405 { ptOrg.x + m_cxSortArrow / 2, ptOrg.y },
3406 { ptOrg.x, ptOrg.y + m_cySortArrow - 1 },
3407 { ptOrg.x + m_cxSortArrow - 1, ptOrg.y + m_cySortArrow - 1 }
3408 };
3409 dc.Polygon(pts, 3);
3410 }
3411 else
3412 {
3413 POINT pts[3] =
3414 {
3415 { ptOrg.x, ptOrg.y },
3416 { ptOrg.x + m_cxSortArrow / 2, ptOrg.y + m_cySortArrow - 1 },
3417 { ptOrg.x + m_cxSortArrow - 1, ptOrg.y }
3418 };
3419 dc.Polygon(pts, 3);
3420 }
3421 dc.SelectBrush(hbrOld);
3422 dc.SelectPen(hpenOld);
3423 }
3424
3425 double DateStrToDouble(LPCTSTR lpstr, DWORD dwFlags)
3426 {
3427 ATLASSERT(lpstr != NULL);
3428 if(lpstr == NULL || lpstr[0] == _T('\0'))
3429 return 0;
3430
3431 USES_CONVERSION;
3432 HRESULT hRet = E_FAIL;
3433 DATE dRet = 0;
3434 if (FAILED(hRet = ::VarDateFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, dwFlags, &dRet)))
3435 {
3436 ATLTRACE2(atlTraceUI, 0, _T("VarDateFromStr failed with result of 0x%8.8X\n"), hRet);
3437 dRet = 0;
3438 }
3439 return dRet;
3440 }
3441
3442 long StrToLong(LPCTSTR lpstr)
3443 {
3444 ATLASSERT(lpstr != NULL);
3445 if(lpstr == NULL || lpstr[0] == _T('\0'))
3446 return 0;
3447
3448 USES_CONVERSION;
3449 HRESULT hRet = E_FAIL;
3450 long lRet = 0;
3451 if (FAILED(hRet = ::VarI4FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &lRet)))
3452 {
3453 ATLTRACE2(atlTraceUI, 0, _T("VarI4FromStr failed with result of 0x%8.8X\n"), hRet);
3454 lRet = 0;
3455 }
3456 return lRet;
3457 }
3458
3459 double StrToDouble(LPCTSTR lpstr)
3460 {
3461 ATLASSERT(lpstr != NULL);
3462 if(lpstr == NULL || lpstr[0] == _T('\0'))
3463 return 0;
3464
3465 USES_CONVERSION;
3466 HRESULT hRet = E_FAIL;
3467 double dblRet = 0;
3468 if (FAILED(hRet = ::VarR8FromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &dblRet)))
3469 {
3470 ATLTRACE2(atlTraceUI, 0, _T("VarR8FromStr failed with result of 0x%8.8X\n"), hRet);
3471 dblRet = 0;
3472 }
3473 return dblRet;
3474 }
3475
3476 bool StrToDecimal(LPCTSTR lpstr, DECIMAL* pDecimal)
3477 {
3478 ATLASSERT(lpstr != NULL);
3479 ATLASSERT(pDecimal != NULL);
3480 if(lpstr == NULL || pDecimal == NULL)
3481 return false;
3482
3483 USES_CONVERSION;
3484 HRESULT hRet = E_FAIL;
3485 if (FAILED(hRet = ::VarDecFromStr((LPOLESTR)T2COLE(lpstr), LANG_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, pDecimal)))
3486 {
3487 ATLTRACE2(atlTraceUI, 0, _T("VarDecFromStr failed with result of 0x%8.8X\n"), hRet);
3488 pDecimal->Lo64 = 0;
3489 pDecimal->Hi32 = 0;
3490 pDecimal->signscale = 0;
3491 return false;
3492 }
3493 return true;
3494 }
3495
3496 // Overrideable PFNLVCOMPARE functions
3497 static int CALLBACK LVCompareText(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3498 {
3499 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3500
3501 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3502 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3503 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3504
3505 int nRet = lstrcmp(pParam1->pszValue, pParam2->pszValue);
3506 return pInfo->bDescending ? -nRet : nRet;
3507 }
3508
3509 static int CALLBACK LVCompareTextNoCase(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3510 {
3511 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3512
3513 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3514 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3515 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3516
3517 int nRet = lstrcmpi(pParam1->pszValue, pParam2->pszValue);
3518 return pInfo->bDescending ? -nRet : nRet;
3519 }
3520
3521 static int CALLBACK LVCompareLong(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3522 {
3523 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3524
3525 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3526 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3527 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3528
3529 int nRet = 0;
3530 if(pParam1->lValue > pParam2->lValue)
3531 nRet = 1;
3532 else if(pParam1->lValue < pParam2->lValue)
3533 nRet = -1;
3534 return pInfo->bDescending ? -nRet : nRet;
3535 }
3536
3537 static int CALLBACK LVCompareDouble(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3538 {
3539 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3540
3541 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3542 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3543 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3544
3545 int nRet = 0;
3546 if(pParam1->dblValue > pParam2->dblValue)
3547 nRet = 1;
3548 else if(pParam1->dblValue < pParam2->dblValue)
3549 nRet = -1;
3550 return pInfo->bDescending ? -nRet : nRet;
3551 }
3552
3553 static int CALLBACK LVCompareCustom(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3554 {
3555 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3556
3557 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3558 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3559 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3560
3561 int nRet = pInfo->pT->CompareItemsCustom(pParam1, pParam2, pInfo->iSortCol);
3562 return pInfo->bDescending ? -nRet : nRet;
3563 }
3564
3565 #ifndef _WIN32_WCE
3566 static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3567 {
3568 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3569
3570 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3571 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3572 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3573
3574 int nRet = (int)::VarDecCmp(&pParam1->decValue, &pParam2->decValue);
3575 nRet--;
3576 return pInfo->bDescending ? -nRet : nRet;
3577 }
3578 #else
3579 // Compare mantissas, ignore sign and scale
3580 static int CompareMantissas(const DECIMAL& decLeft, const DECIMAL& decRight)
3581 {
3582 if (decLeft.Hi32 < decRight.Hi32)
3583 {
3584 return -1;
3585 }
3586 if (decLeft.Hi32 > decRight.Hi32)
3587 {
3588 return 1;
3589 }
3590 // Here, decLeft.Hi32 == decRight.Hi32
3591 if (decLeft.Lo64 < decRight.Lo64)
3592 {
3593 return -1;
3594 }
3595 if (decLeft.Lo64 > decRight.Lo64)
3596 {
3597 return 1;
3598 }
3599 return 0;
3600 }
3601
3602 // return values: VARCMP_LT, VARCMP_EQ, VARCMP_GT, VARCMP_NULL
3603 static HRESULT VarDecCmp(const DECIMAL* pdecLeft, const DECIMAL* pdecRight)
3604 {
3605 static const ULONG powersOfTen[] =
3606 {
3607 10ul,
3608 100ul,
3609 1000ul,
3610 10000ul,
3611 100000ul,
3612 1000000ul,
3613 10000000ul,
3614 100000000ul,
3615 1000000000ul
3616 };
3617 static const int largestPower = sizeof(powersOfTen) / sizeof(powersOfTen[0]);
3618 if (!pdecLeft || !pdecRight)
3619 {
3620 return VARCMP_NULL;
3621 }
3622
3623 // Degenerate case - at least one comparand is of the form
3624 // [+-]0*10^N (denormalized zero)
3625 bool bLeftZero = (!pdecLeft->Lo64 && !pdecLeft->Hi32);
3626 bool bRightZero = (!pdecRight->Lo64 && !pdecRight->Hi32);
3627 if (bLeftZero && bRightZero)
3628 {
3629 return VARCMP_EQ;
3630 }
3631 bool bLeftNeg = ((pdecLeft->sign & DECIMAL_NEG) != 0);
3632 bool bRightNeg = ((pdecRight->sign & DECIMAL_NEG) != 0);
3633 if (bLeftZero)
3634 {
3635 return (bRightNeg ? VARCMP_GT : VARCMP_LT);
3636 }
3637 // This also covers the case where the comparands have different signs
3638 if (bRightZero || bLeftNeg != bRightNeg)
3639 {
3640 return (bLeftNeg ? VARCMP_LT : VARCMP_GT);
3641 }
3642
3643 // Here both comparands have the same sign and need to be compared
3644 // on mantissa and scale. The result is obvious when
3645 // 1. Scales are equal (then compare mantissas)
3646 // 2. A number with smaller scale is also the one with larger mantissa
3647 // (then this number is obviously larger)
3648 // In the remaining case, we would multiply the number with smaller
3649 // scale by 10 and simultaneously increment its scale (which amounts to
3650 // adding trailing zeros after decimal point), until the numbers fall under
3651 // one of the two cases above
3652 DECIMAL temp;
3653 bool bInvert = bLeftNeg; // the final result needs to be inverted
3654 if (pdecLeft->scale < pdecRight->scale)
3655 {
3656 temp = *pdecLeft;
3657 }
3658 else
3659 {
3660 temp = *pdecRight;
3661 pdecRight = pdecLeft;
3662 bInvert = !bInvert;
3663 }
3664
3665 // Now temp is the number with smaller (or equal) scale, and
3666 // we can modify it freely without touching original parameters
3667 int comp;
3668 while ((comp = CompareMantissas(temp, *pdecRight)) < 0 &&
3669 temp.scale < pdecRight->scale)
3670 {
3671 // Multiply by an appropriate power of 10
3672 int scaleDiff = pdecRight->scale - temp.scale;
3673 if (scaleDiff > largestPower)
3674 {
3675 // Keep the multiplier representable in 32bit
3676 scaleDiff = largestPower;
3677 }
3678 DWORDLONG power = powersOfTen[scaleDiff - 1];
3679 // Multiply temp's mantissa by power
3680 DWORDLONG product = temp.Lo32 * power;
3681 ULONG carry = static_cast<ULONG>(product >> 32);
3682 temp.Lo32 = static_cast<ULONG>(product);
3683 product = temp.Mid32 * power + carry;
3684 carry = static_cast<ULONG>(product >> 32);
3685 temp.Mid32 = static_cast<ULONG>(product);
3686 product = temp.Hi32 * power + carry;
3687 if (static_cast<ULONG>(product >> 32))
3688 {
3689 // Multiplication overflowed - pdecLeft is clearly larger
3690 break;
3691 }
3692 temp.Hi32 = static_cast<ULONG>(product);
3693 temp.scale = (BYTE)(temp.scale + scaleDiff);
3694 }
3695 if (temp.scale < pdecRight->scale)
3696 {
3697 comp = 1;
3698 }
3699 if (bInvert)
3700 {
3701 comp = -comp;
3702 }
3703 return (comp > 0 ? VARCMP_GT : comp < 0 ? VARCMP_LT : VARCMP_EQ);
3704 }
3705
3706 static int CALLBACK LVCompareDecimal(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
3707 {
3708 ATLASSERT(lParam1 != NULL && lParam2 != NULL && lParamSort != NULL);
3709
3710 LVCompareParam* pParam1 = (LVCompareParam*)lParam1;
3711 LVCompareParam* pParam2 = (LVCompareParam*)lParam2;
3712 LVSortInfo* pInfo = (LVSortInfo*)lParamSort;
3713
3714 int nRet = (int)VarDecCmp(&pParam1->decValue, &pParam2->decValue);
3715 nRet--;
3716 return pInfo->bDescending ? -nRet : nRet;
3717 }
3718 #endif // !_WIN32_WCE
3719
3720 BEGIN_MSG_MAP(CSortListViewImpl)
3721 MESSAGE_HANDLER(LVM_INSERTCOLUMN, OnInsertColumn)
3722 MESSAGE_HANDLER(LVM_DELETECOLUMN, OnDeleteColumn)
3723 NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, OnHeaderItemClick)
3724 NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, OnHeaderItemClick)
3725 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
3726 END_MSG_MAP()
3727
3728 LRESULT OnInsertColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3729 {
3730 T* pT = static_cast<T*>(this);
3731 LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
3732 if(lRet == -1)
3733 return -1;
3734
3735 WORD wType = 0;
3736 m_arrColSortType.Add(wType);
3737 int nCount = m_arrColSortType.GetSize();
3738 ATLASSERT(nCount == GetColumnCount());
3739
3740 for(int i = nCount - 1; i > lRet; i--)
3741 m_arrColSortType[i] = m_arrColSortType[i - 1];
3742 m_arrColSortType[(int)lRet] = LVCOLSORT_TEXT;
3743
3744 if(lRet <= m_iSortColumn)
3745 m_iSortColumn++;
3746
3747 return lRet;
3748 }
3749
3750 LRESULT OnDeleteColumn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3751 {
3752 T* pT = static_cast<T*>(this);
3753 LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
3754 if(lRet == 0)
3755 return 0;
3756
3757 int iCol = (int)wParam;
3758 if(m_iSortColumn == iCol)
3759 m_iSortColumn = -1;
3760 else if(m_iSortColumn > iCol)
3761 m_iSortColumn--;
3762 m_arrColSortType.RemoveAt(iCol);
3763
3764 return lRet;
3765 }
3766
3767 LRESULT OnHeaderItemClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
3768 {
3769 LPNMHEADER p = (LPNMHEADER)pnmh;
3770 if(p->iButton == 0)
3771 {
3772 int iOld = m_iSortColumn;
3773 bool bDescending = (m_iSortColumn == p->iItem) ? !m_bSortDescending : false;
3774 if(DoSortItems(p->iItem, bDescending))
3775 NotifyParentSortChanged(p->iItem, iOld);
3776 }
3777 bHandled = FALSE;
3778 return 0;
3779 }
3780
3781 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
3782 {
3783 #ifndef _WIN32_WCE
3784 if(wParam == SPI_SETNONCLIENTMETRICS)
3785 GetSystemSettings();
3786 #else // CE specific
3787 wParam; // avoid level 4 warning
3788 GetSystemSettings();
3789 #endif // _WIN32_WCE
3790 bHandled = FALSE;
3791 return 0;
3792 }
3793
3794 void GetSystemSettings()
3795 {
3796 if(!m_bCommCtrl6 && !m_bmSort[m_iSortUp].IsNull())
3797 {
3798 T* pT = static_cast<T*>(this);
3799 pT->CreateSortBitmaps();
3800 if(m_iSortColumn != -1)
3801 SetSortColumn(m_iSortColumn);
3802 }
3803 }
3804
3805 };
3806
3807
3808 typedef ATL::CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | LVS_REPORT | LVS_SHOWSELALWAYS , WS_EX_CLIENTEDGE> CSortListViewCtrlTraits;
3809
3810 template <class T, class TBase = CListViewCtrl, class TWinTraits = CSortListViewCtrlTraits>
3811 class ATL_NO_VTABLE CSortListViewCtrlImpl: public ATL::CWindowImpl<T, TBase, TWinTraits>, public CSortListViewImpl<T>
3812 {
3813 public:
3814 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
3815
3816 bool SortItems(int iCol, bool bDescending = false)
3817 {
3818 return DoSortItems(iCol, bDescending);
3819 }
3820
3821 BEGIN_MSG_MAP(CSortListViewCtrlImpl)
3822 MESSAGE_HANDLER(LVM_INSERTCOLUMN, CSortListViewImpl<T>::OnInsertColumn)
3823 MESSAGE_HANDLER(LVM_DELETECOLUMN, CSortListViewImpl<T>::OnDeleteColumn)
3824 NOTIFY_CODE_HANDLER(HDN_ITEMCLICKA, CSortListViewImpl<T>::OnHeaderItemClick)
3825 NOTIFY_CODE_HANDLER(HDN_ITEMCLICKW, CSortListViewImpl<T>::OnHeaderItemClick)
3826 MESSAGE_HANDLER(WM_SETTINGCHANGE, CSortListViewImpl<T>::OnSettingChange)
3827 END_MSG_MAP()
3828 };
3829
3830 class CSortListViewCtrl : public CSortListViewCtrlImpl<CSortListViewCtrl>
3831 {
3832 public:
3833 DECLARE_WND_SUPERCLASS(_T("WTL_SortListViewCtrl"), GetWndClassName())
3834 };
3835
3836
3837 ///////////////////////////////////////////////////////////////////////////////
3838 // CTabView - implements tab view window
3839
3840 // TabView Notifications
3841 #define TBVN_PAGEACTIVATED (0U-741)
3842 #define TBVN_CONTEXTMENU (0U-742)
3843
3844 // Notification data for TBVN_CONTEXTMENU
3845 struct TBVCONTEXTMENUINFO
3846 {
3847 NMHDR hdr;
3848 POINT pt;
3849 };
3850
3851 typedef TBVCONTEXTMENUINFO* LPTBVCONTEXTMENUINFO;
3852
3853
3854 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
3855 class ATL_NO_VTABLE CTabViewImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >
3856 {
3857 public:
3858 DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE)
3859
3860 // Declarations and enums
3861 struct TABVIEWPAGE
3862 {
3863 HWND hWnd;
3864 LPTSTR lpstrTitle;
3865 LPVOID pData;
3866 };
3867
3868 struct TCITEMEXTRA
3869 {
3870 TCITEMHEADER tciheader;
3871 TABVIEWPAGE tvpage;
3872
3873 operator LPTCITEM() { return (LPTCITEM)this; }
3874 };
3875
3876 enum
3877 {
3878 m_nTabID = 1313,
3879 m_cxMoveMark = 6,
3880 m_cyMoveMark = 3,
3881 m_nMenuItemsMax = (ID_WINDOW_TABLAST - ID_WINDOW_TABFIRST + 1)
3882 };
3883
3884 // Data members
3885 ATL::CContainedWindowT<CTabCtrl> m_tab;
3886 int m_cyTabHeight;
3887
3888 int m_nActivePage;
3889
3890 int m_nInsertItem;
3891 POINT m_ptStartDrag;
3892
3893 CMenuHandle m_menu;
3894
3895 int m_cchTabTextLength;
3896
3897 int m_nMenuItemsCount;
3898
3899 ATL::CWindow m_wndTitleBar;
3900 LPTSTR m_lpstrTitleBarBase;
3901 int m_cchTitleBarLength;
3902
3903 CImageList m_ilDrag;
3904
3905 bool m_bDestroyPageOnRemove:1;
3906 bool m_bDestroyImageList:1;
3907 bool m_bActivePageMenuItem:1;
3908 bool m_bActiveAsDefaultMenuItem:1;
3909 bool m_bEmptyMenuItem:1;
3910 bool m_bWindowsMenuItem:1;
3911 bool m_bNoTabDrag:1;
3912 // internal
3913 bool m_bTabCapture:1;
3914 bool m_bTabDrag:1;
3915 bool m_bInternalFont:1;
3916
3917 // Constructor/destructor
3918 CTabViewImpl() :
3919 m_nActivePage(-1),
3920 m_cyTabHeight(0),
3921 m_tab(this, 1),
3922 m_nInsertItem(-1),
3923 m_cchTabTextLength(30),
3924 m_nMenuItemsCount(10),
3925 m_lpstrTitleBarBase(NULL),
3926 m_cchTitleBarLength(100),
3927 m_bDestroyPageOnRemove(true),
3928 m_bDestroyImageList(true),
3929 m_bActivePageMenuItem(true),
3930 m_bActiveAsDefaultMenuItem(false),
3931 m_bEmptyMenuItem(false),
3932 m_bWindowsMenuItem(false),
3933 m_bNoTabDrag(false),
3934 m_bTabCapture(false),
3935 m_bTabDrag(false),
3936 m_bInternalFont(false)
3937 {
3938 m_ptStartDrag.x = 0;
3939 m_ptStartDrag.y = 0;
3940 }
3941
3942 ~CTabViewImpl()
3943 {
3944 delete [] m_lpstrTitleBarBase;
3945 }
3946
3947 // Message filter function - to be called from PreTranslateMessage of the main window
3948 BOOL PreTranslateMessage(MSG* pMsg)
3949 {
3950 if(IsWindow() == FALSE)
3951 return FALSE;
3952
3953 BOOL bRet = FALSE;
3954
3955 // Check for TabView built-in accelerators (Ctrl+Tab/Ctrl+Shift+Tab - next/previous page)
3956 int nCount = GetPageCount();
3957 if(nCount > 0)
3958 {
3959 bool bControl = (::GetKeyState(VK_CONTROL) < 0);
3960 if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) && bControl)
3961 {
3962 if(nCount > 1)
3963 {
3964 int nPage = m_nActivePage;
3965 bool bShift = (::GetKeyState(VK_SHIFT) < 0);
3966 if(bShift)
3967 nPage = (nPage > 0) ? (nPage - 1) : (nCount - 1);
3968 else
3969 nPage = ((nPage >= 0) && (nPage < (nCount - 1))) ? (nPage + 1) : 0;
3970
3971 SetActivePage(nPage);
3972 T* pT = static_cast<T*>(this);
3973 pT->OnPageActivated(m_nActivePage);
3974 }
3975
3976 bRet = TRUE;
3977 }
3978 }
3979
3980 // If we are doing drag-drop, check for Escape key that cancels it
3981 if(bRet == FALSE)
3982 {
3983 if(m_bTabCapture && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE)
3984 {
3985 ::ReleaseCapture();
3986 bRet = TRUE;
3987 }
3988 }
3989
3990 // Pass the message to the active page
3991 if(bRet == FALSE)
3992 {
3993 if(m_nActivePage != -1)
3994 bRet = (BOOL)::SendMessage(GetPageHWND(m_nActivePage), WM_FORWARDMSG, 0, (LPARAM)pMsg);
3995 }
3996
3997 return bRet;
3998 }
3999
4000 // Attributes
4001 int GetPageCount() const
4002 {
4003 ATLASSERT(::IsWindow(m_hWnd));
4004 return m_tab.GetItemCount();
4005 }
4006
4007 int GetActivePage() const
4008 {
4009 return m_nActivePage;
4010 }
4011
4012 void SetActivePage(int nPage)
4013 {
4014 ATLASSERT(::IsWindow(m_hWnd));
4015 ATLASSERT(IsValidPageIndex(nPage));
4016
4017 T* pT = static_cast<T*>(this);
4018
4019 SetRedraw(FALSE);
4020
4021 if(m_nActivePage != -1)
4022 ::ShowWindow(GetPageHWND(m_nActivePage), FALSE);
4023 m_nActivePage = nPage;
4024 m_tab.SetCurSel(m_nActivePage);
4025 ::ShowWindow(GetPageHWND(m_nActivePage), TRUE);
4026
4027 pT->UpdateLayout();
4028
4029 SetRedraw(TRUE);
4030 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
4031
4032 if(::GetFocus() != m_tab.m_hWnd)
4033 ::SetFocus(GetPageHWND(m_nActivePage));
4034
4035 pT->UpdateTitleBar();
4036 pT->UpdateMenu();
4037 }
4038
4039 HIMAGELIST GetImageList() const
4040 {
4041 ATLASSERT(::IsWindow(m_hWnd));
4042 return m_tab.GetImageList();
4043 }
4044
4045 HIMAGELIST SetImageList(HIMAGELIST hImageList)
4046 {
4047 ATLASSERT(::IsWindow(m_hWnd));
4048 return m_tab.SetImageList(hImageList);
4049 }
4050
4051 void SetWindowMenu(HMENU hMenu)
4052 {
4053 ATLASSERT(::IsWindow(m_hWnd));
4054
4055 m_menu = hMenu;
4056
4057 T* pT = static_cast<T*>(this);
4058 pT->UpdateMenu();
4059 }
4060
4061 void SetTitleBarWindow(HWND hWnd)
4062 {
4063 ATLASSERT(::IsWindow(m_hWnd));
4064
4065 delete [] m_lpstrTitleBarBase;
4066 m_lpstrTitleBarBase = NULL;
4067
4068 m_wndTitleBar = hWnd;
4069 if(hWnd == NULL)
4070 return;
4071
4072 int cchLen = m_wndTitleBar.GetWindowTextLength() + 1;
4073 ATLTRY(m_lpstrTitleBarBase = new TCHAR[cchLen]);
4074 if(m_lpstrTitleBarBase != NULL)
4075 {
4076 m_wndTitleBar.GetWindowText(m_lpstrTitleBarBase, cchLen);
4077 T* pT = static_cast<T*>(this);
4078 pT->UpdateTitleBar();
4079 }
4080 }
4081
4082 // Page attributes
4083 HWND GetPageHWND(int nPage) const
4084 {
4085 ATLASSERT(::IsWindow(m_hWnd));
4086 ATLASSERT(IsValidPageIndex(nPage));
4087
4088 TCITEMEXTRA tcix = { 0 };
4089 tcix.tciheader.mask = TCIF_PARAM;
4090 m_tab.GetItem(nPage, tcix);
4091
4092 return tcix.tvpage.hWnd;
4093 }
4094
4095 LPCTSTR GetPageTitle(int nPage) const
4096 {
4097 ATLASSERT(::IsWindow(m_hWnd));
4098 ATLASSERT(IsValidPageIndex(nPage));
4099
4100 TCITEMEXTRA tcix = { 0 };
4101 tcix.tciheader.mask = TCIF_PARAM;
4102 if(m_tab.GetItem(nPage, tcix) == FALSE)
4103 return NULL;
4104
4105 return tcix.tvpage.lpstrTitle;
4106 }
4107
4108 bool SetPageTitle(int nPage, LPCTSTR lpstrTitle)
4109 {
4110 ATLASSERT(::IsWindow(m_hWnd));
4111 ATLASSERT(IsValidPageIndex(nPage));
4112
4113 T* pT = static_cast<T*>(this);
4114
4115 int cchBuff = lstrlen(lpstrTitle) + 1;
4116 LPTSTR lpstrBuff = NULL;
4117 ATLTRY(lpstrBuff = new TCHAR[cchBuff]);
4118 if(lpstrBuff == NULL)
4119 return false;
4120
4121 SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle);
4122 TCITEMEXTRA tcix = { 0 };
4123 tcix.tciheader.mask = TCIF_PARAM;
4124 if(m_tab.GetItem(nPage, tcix) == FALSE)
4125 return false;
4126
4127 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
4128 LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
4129 if(lpstrTabText == NULL)
4130 return false;
4131
4132 delete [] tcix.tvpage.lpstrTitle;
4133
4134 pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1);
4135
4136 tcix.tciheader.mask = TCIF_TEXT | TCIF_PARAM;
4137 tcix.tciheader.pszText = lpstrTabText;
4138 tcix.tvpage.lpstrTitle = lpstrBuff;
4139 if(m_tab.SetItem(nPage, tcix) == FALSE)
4140 return false;
4141
4142 pT->UpdateTitleBar();
4143 pT->UpdateMenu();
4144
4145 return true;
4146 }
4147
4148 LPVOID GetPageData(int nPage) const
4149 {
4150 ATLASSERT(::IsWindow(m_hWnd));
4151 ATLASSERT(IsValidPageIndex(nPage));
4152
4153 TCITEMEXTRA tcix = { 0 };
4154 tcix.tciheader.mask = TCIF_PARAM;
4155 m_tab.GetItem(nPage, tcix);
4156
4157 return tcix.tvpage.pData;
4158 }
4159
4160 LPVOID SetPageData(int nPage, LPVOID pData)
4161 {
4162 ATLASSERT(::IsWindow(m_hWnd));
4163 ATLASSERT(IsValidPageIndex(nPage));
4164
4165 TCITEMEXTRA tcix = { 0 };
4166 tcix.tciheader.mask = TCIF_PARAM;
4167 m_tab.GetItem(nPage, tcix);
4168 LPVOID pDataOld = tcix.tvpage.pData;
4169
4170 tcix.tvpage.pData = pData;
4171 m_tab.SetItem(nPage, tcix);
4172
4173 return pDataOld;
4174 }
4175
4176 int GetPageImage(int nPage) const
4177 {
4178 ATLASSERT(::IsWindow(m_hWnd));
4179 ATLASSERT(IsValidPageIndex(nPage));
4180
4181 TCITEMEXTRA tcix = { 0 };
4182 tcix.tciheader.mask = TCIF_IMAGE;
4183 m_tab.GetItem(nPage, tcix);
4184
4185 return tcix.tciheader.iImage;
4186 }
4187
4188 int SetPageImage(int nPage, int nImage)
4189 {
4190 ATLASSERT(::IsWindow(m_hWnd));
4191 ATLASSERT(IsValidPageIndex(nPage));
4192
4193 TCITEMEXTRA tcix = { 0 };
4194 tcix.tciheader.mask = TCIF_IMAGE;
4195 m_tab.GetItem(nPage, tcix);
4196 int nImageOld = tcix.tciheader.iImage;
4197
4198 tcix.tciheader.iImage = nImage;
4199 m_tab.SetItem(nPage, tcix);
4200
4201 return nImageOld;
4202 }
4203
4204 // Operations
4205 bool AddPage(HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL)
4206 {
4207 return InsertPage(GetPageCount(), hWndView, lpstrTitle, nImage, pData);
4208 }
4209
4210 bool InsertPage(int nPage, HWND hWndView, LPCTSTR lpstrTitle, int nImage = -1, LPVOID pData = NULL)
4211 {
4212 ATLASSERT(::IsWindow(m_hWnd));
4213 ATLASSERT(nPage == GetPageCount() || IsValidPageIndex(nPage));
4214
4215 T* pT = static_cast<T*>(this);
4216
4217 int cchBuff = lstrlen(lpstrTitle) + 1;
4218 LPTSTR lpstrBuff = NULL;
4219 ATLTRY(lpstrBuff = new TCHAR[cchBuff]);
4220 if(lpstrBuff == NULL)
4221 return false;
4222
4223 SecureHelper::strcpy_x(lpstrBuff, cchBuff, lpstrTitle);
4224
4225 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
4226 LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
4227 if(lpstrTabText == NULL)
4228 return false;
4229
4230 pT->ShortenTitle(lpstrTitle, lpstrTabText, m_cchTabTextLength + 1);
4231
4232 SetRedraw(FALSE);
4233
4234 TCITEMEXTRA tcix = { 0 };
4235 tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
4236 tcix.tciheader.pszText = lpstrTabText;
4237 tcix.tciheader.iImage = nImage;
4238 tcix.tvpage.hWnd = hWndView;
4239 tcix.tvpage.lpstrTitle = lpstrBuff;
4240 tcix.tvpage.pData = pData;
4241 int nItem = m_tab.InsertItem(nPage, tcix);
4242 if(nItem == -1)
4243 {
4244 delete [] lpstrBuff;
4245 SetRedraw(TRUE);
4246 return false;
4247 }
4248
4249 // adjust active page index, if inserted before it
4250 if(nPage <= m_nActivePage)
4251 m_nActivePage++;
4252
4253 SetActivePage(nItem);
4254 pT->OnPageActivated(m_nActivePage);
4255
4256 if(GetPageCount() == 1)
4257 pT->ShowTabControl(true);
4258
4259 pT->UpdateLayout();
4260
4261 SetRedraw(TRUE);
4262 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
4263
4264 return true;
4265 }
4266
4267 void RemovePage(int nPage)
4268 {
4269 ATLASSERT(::IsWindow(m_hWnd));
4270 ATLASSERT(IsValidPageIndex(nPage));
4271
4272 T* pT = static_cast<T*>(this);
4273
4274 SetRedraw(FALSE);
4275
4276 if(GetPageCount() == 1)
4277 pT->ShowTabControl(false);
4278
4279 if(m_bDestroyPageOnRemove)
4280 ::DestroyWindow(GetPageHWND(nPage));
4281 else
4282 ::ShowWindow(GetPageHWND(nPage), FALSE);
4283 LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(nPage);
4284 delete [] lpstrTitle;
4285
4286 ATLVERIFY(m_tab.DeleteItem(nPage) != FALSE);
4287
4288 if(m_nActivePage == nPage)
4289 {
4290 m_nActivePage = -1;
4291
4292 if(nPage > 0)
4293 {
4294 SetActivePage(nPage - 1);
4295 }
4296 else if(GetPageCount() > 0)
4297 {
4298 SetActivePage(nPage);
4299 }
4300 else
4301 {
4302 SetRedraw(TRUE);
4303 Invalidate();
4304 UpdateWindow();
4305 pT->UpdateTitleBar();
4306 pT->UpdateMenu();
4307 }
4308 }
4309 else
4310 {
4311 nPage = (nPage < m_nActivePage) ? (m_nActivePage - 1) : m_nActivePage;
4312 m_nActivePage = -1;
4313 SetActivePage(nPage);
4314 }
4315
4316 pT->OnPageActivated(m_nActivePage);
4317 }
4318
4319 void RemoveAllPages()
4320 {
4321 ATLASSERT(::IsWindow(m_hWnd));
4322
4323 if(GetPageCount() == 0)
4324 return;
4325
4326 T* pT = static_cast<T*>(this);
4327
4328 SetRedraw(FALSE);
4329
4330 pT->ShowTabControl(false);
4331
4332 for(int i = 0; i < GetPageCount(); i++)
4333 {
4334 if(m_bDestroyPageOnRemove)
4335 ::DestroyWindow(GetPageHWND(i));
4336 else
4337 ::ShowWindow(GetPageHWND(i), FALSE);
4338 LPTSTR lpstrTitle = (LPTSTR)GetPageTitle(i);
4339 delete [] lpstrTitle;
4340 }
4341 m_tab.DeleteAllItems();
4342
4343 m_nActivePage = -1;
4344 pT->OnPageActivated(m_nActivePage);
4345
4346 SetRedraw(TRUE);
4347 Invalidate();
4348 UpdateWindow();
4349
4350 pT->UpdateTitleBar();
4351 pT->UpdateMenu();
4352 }
4353
4354 int PageIndexFromHwnd(HWND hWnd) const
4355 {
4356 int nIndex = -1;
4357
4358 for(int i = 0; i < GetPageCount(); i++)
4359 {
4360 if(GetPageHWND(i) == hWnd)
4361 {
4362 nIndex = i;
4363 break;
4364 }
4365 }
4366
4367 return nIndex;
4368 }
4369
4370 void BuildWindowMenu(HMENU hMenu, int nMenuItemsCount = 10, bool bEmptyMenuItem = true, bool bWindowsMenuItem = true, bool bActivePageMenuItem = true, bool bActiveAsDefaultMenuItem = false)
4371 {
4372 ATLASSERT(::IsWindow(m_hWnd));
4373
4374 CMenuHandle menu = hMenu;
4375 T* pT = static_cast<T*>(this);
4376 pT; // avoid level 4 warning
4377 int nFirstPos = 0;
4378
4379 // Find first menu item in our range
4380 #ifndef _WIN32_WCE
4381 for(nFirstPos = 0; nFirstPos < menu.GetMenuItemCount(); nFirstPos++)
4382 {
4383 UINT nID = menu.GetMenuItemID(nFirstPos);
4384 if((nID >= ID_WINDOW_TABFIRST && nID <= ID_WINDOW_TABLAST) || nID == ID_WINDOW_SHOWTABLIST)
4385 break;
4386 }
4387 #else // CE specific
4388 for(nFirstPos = 0; ; nFirstPos++)
4389 {
4390 CMenuItemInfo mii;
4391 mii.fMask = MIIM_ID;
4392 BOOL bRet = menu.GetMenuItemInfo(nFirstPos, TRUE, &mii);
4393 if(bRet == FALSE)
4394 break;
4395 if((mii.wID >= ID_WINDOW_TABFIRST && mii.wID <= ID_WINDOW_TABLAST) || mii.wID == ID_WINDOW_SHOWTABLIST)
4396 break;
4397 }
4398 #endif // _WIN32_WCE
4399
4400 // Remove all menu items for tab pages
4401 BOOL bRet = TRUE;
4402 while(bRet != FALSE)
4403 bRet = menu.DeleteMenu(nFirstPos, MF_BYPOSITION);
4404
4405 // Add separator if it's not already there
4406 int nPageCount = GetPageCount();
4407 if((bWindowsMenuItem || (nPageCount > 0)) && (nFirstPos > 0))
4408 {
4409 CMenuItemInfo mii;
4410 mii.fMask = MIIM_TYPE;
4411 menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii);
4412 if((nFirstPos <= 0) || ((mii.fType & MFT_SEPARATOR) == 0))
4413 {
4414 menu.AppendMenu(MF_SEPARATOR);
4415 nFirstPos++;
4416 }
4417 }
4418
4419 // Add menu items for all pages
4420 if(nPageCount > 0)
4421 {
4422 // Append menu items for all pages
4423 const int cchPrefix = 3; // 2 digits + space
4424 nMenuItemsCount = __min(__min(nPageCount, nMenuItemsCount), (int)m_nMenuItemsMax);
4425 ATLASSERT(nMenuItemsCount < 100); // 2 digits only
4426 if(nMenuItemsCount >= 100)
4427 nMenuItemsCount = 99;
4428
4429 for(int i = 0; i < nMenuItemsCount; i++)
4430 {
4431 LPCTSTR lpstrTitle = GetPageTitle(i);
4432 int nLen = lstrlen(lpstrTitle);
4433 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
4434 LPTSTR lpstrText = buff.Allocate(cchPrefix + nLen + 1);
4435 ATLASSERT(lpstrText != NULL);
4436 if(lpstrText != NULL)
4437 {
4438 LPCTSTR lpstrFormat = (i < 9) ? _T("&%i %s") : _T("%i %s");
4439 SecureHelper::wsprintf_x(lpstrText, cchPrefix + nLen + 1, lpstrFormat, i + 1, lpstrTitle);
4440 menu.AppendMenu(MF_STRING, ID_WINDOW_TABFIRST + i, lpstrText);
4441 }
4442 }
4443
4444 // Mark active page
4445 if(bActivePageMenuItem && (m_nActivePage != -1))
4446 {
4447 #ifndef _WIN32_WCE
4448 if(bActiveAsDefaultMenuItem)
4449 {
4450 menu.SetMenuDefaultItem((UINT)-1, TRUE);
4451 menu.SetMenuDefaultItem(nFirstPos + m_nActivePage, TRUE);
4452 }
4453 else
4454 #else // CE specific
4455 bActiveAsDefaultMenuItem; // avoid level 4 warning
4456 #endif // _WIN32_WCE
4457 {
4458 menu.CheckMenuRadioItem(nFirstPos, nFirstPos + nMenuItemsCount, nFirstPos + m_nActivePage, MF_BYPOSITION);
4459 }
4460 }
4461 }
4462 else
4463 {
4464 if(bEmptyMenuItem)
4465 {
4466 menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_TABFIRST, pT->GetEmptyListText());
4467 menu.EnableMenuItem(ID_WINDOW_TABFIRST, MF_GRAYED);
4468 }
4469
4470 // Remove separator if nothing else is there
4471 if(!bEmptyMenuItem && !bWindowsMenuItem && (nFirstPos > 0))
4472 {
4473 CMenuItemInfo mii;
4474 mii.fMask = MIIM_TYPE;
4475 menu.GetMenuItemInfo(nFirstPos - 1, TRUE, &mii);
4476 if((mii.fType & MFT_SEPARATOR) != 0)
4477 menu.DeleteMenu(nFirstPos - 1, MF_BYPOSITION);
4478 }
4479 }
4480
4481 // Add "Windows..." menu item
4482 if(bWindowsMenuItem)
4483 menu.AppendMenu(MF_BYPOSITION | MF_STRING, ID_WINDOW_SHOWTABLIST, pT->GetWindowsMenuItemText());
4484 }
4485
4486 BOOL SubclassWindow(HWND hWnd)
4487 {
4488 #if (_MSC_VER >= 1300)
4489 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
4490 #else // !(_MSC_VER >= 1300)
4491 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
4492 BOOL bRet = _baseClass::SubclassWindow(hWnd);
4493 #endif // !(_MSC_VER >= 1300)
4494 if(bRet != FALSE)
4495 {
4496 T* pT = static_cast<T*>(this);
4497 pT->CreateTabControl();
4498 pT->UpdateLayout();
4499 }
4500
4501 return bRet;
4502 }
4503
4504 // Message map and handlers
4505 BEGIN_MSG_MAP(CTabViewImpl)
4506 MESSAGE_HANDLER(WM_CREATE, OnCreate)
4507 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
4508 MESSAGE_HANDLER(WM_SIZE, OnSize)
4509 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
4510 MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
4511 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
4512 NOTIFY_HANDLER(m_nTabID, TCN_SELCHANGE, OnTabChanged)
4513 NOTIFY_ID_HANDLER(m_nTabID, OnTabNotification)
4514 #ifndef _WIN32_WCE
4515 NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnTabGetDispInfo)
4516 #endif // !_WIN32_WCE
4517 FORWARD_NOTIFICATIONS()
4518 ALT_MSG_MAP(1) // tab control
4519 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnTabLButtonDown)
4520 MESSAGE_HANDLER(WM_LBUTTONUP, OnTabLButtonUp)
4521 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnTabCaptureChanged)
4522 MESSAGE_HANDLER(WM_MOUSEMOVE, OnTabMouseMove)
4523 MESSAGE_HANDLER(WM_RBUTTONUP, OnTabRButtonUp)
4524 MESSAGE_HANDLER(WM_SYSKEYDOWN, OnTabSysKeyDown)
4525 END_MSG_MAP()
4526
4527 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
4528 {
4529 T* pT = static_cast<T*>(this);
4530 pT->CreateTabControl();
4531
4532 return 0;
4533 }
4534
4535 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
4536 {
4537 RemoveAllPages();
4538
4539 if(m_bDestroyImageList)
4540 {
4541 CImageList il = m_tab.SetImageList(NULL);
4542 if(il.m_hImageList != NULL)
4543 il.Destroy();
4544 }
4545
4546 if(m_bInternalFont)
4547 {
4548 HFONT hFont = m_tab.GetFont();
4549 m_tab.SetFont(NULL, FALSE);
4550 ::DeleteObject(hFont);
4551 m_bInternalFont = false;
4552 }
4553
4554 return 0;
4555 }
4556
4557 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
4558 {
4559 T* pT = static_cast<T*>(this);
4560 pT->UpdateLayout();
4561 return 0;
4562 }
4563
4564 LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
4565 {
4566 if(m_nActivePage != -1)
4567 ::SetFocus(GetPageHWND(m_nActivePage));
4568 return 0;
4569 }
4570
4571 LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
4572 {
4573 return m_tab.SendMessage(WM_GETFONT);
4574 }
4575
4576 LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
4577 {
4578 if(m_bInternalFont)
4579 {
4580 HFONT hFont = m_tab.GetFont();
4581 m_tab.SetFont(NULL, FALSE);
4582 ::DeleteObject(hFont);
4583 m_bInternalFont = false;
4584 }
4585
4586 m_tab.SendMessage(WM_SETFONT, wParam, lParam);
4587
4588 T* pT = static_cast<T*>(this);
4589 m_cyTabHeight = pT->CalcTabHeight();
4590
4591 if((BOOL)lParam != FALSE)
4592 pT->UpdateLayout();
4593
4594 return 0;
4595 }
4596
4597 LRESULT OnTabChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
4598 {
4599 SetActivePage(m_tab.GetCurSel());
4600 T* pT = static_cast<T*>(this);
4601 pT->OnPageActivated(m_nActivePage);
4602
4603 return 0;
4604 }
4605
4606 LRESULT OnTabNotification(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
4607 {
4608 // nothing to do - this just blocks all tab control
4609 // notifications from being propagated further
4610 return 0;
4611 }
4612
4613 #ifndef _WIN32_WCE
4614 LRESULT OnTabGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
4615 {
4616 LPNMTTDISPINFO pTTDI = (LPNMTTDISPINFO)pnmh;
4617 if(pTTDI->hdr.hwndFrom == m_tab.GetTooltips())
4618 {
4619 T* pT = static_cast<T*>(this);
4620 pT->UpdateTooltipText(pTTDI);
4621 }
4622 else
4623 {
4624 bHandled = FALSE;
4625 }
4626
4627 return 0;
4628 }
4629 #endif // !_WIN32_WCE
4630
4631 // Tab control message handlers
4632 LRESULT OnTabLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
4633 {
4634 if(!m_bNoTabDrag && (m_tab.GetItemCount() > 1))
4635 {
4636 m_bTabCapture = true;
4637 m_tab.SetCapture();
4638
4639 m_ptStartDrag.x = GET_X_LPARAM(lParam);
4640 m_ptStartDrag.y = GET_Y_LPARAM(lParam);
4641 }
4642
4643 bHandled = FALSE;
4644 return 0;
4645 }
4646
4647 LRESULT OnTabLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
4648 {
4649 if(m_bTabCapture)
4650 {
4651 if(m_bTabDrag)
4652 {
4653 TCHITTESTINFO hti = { 0 };
4654 hti.pt.x = GET_X_LPARAM(lParam);
4655 hti.pt.y = GET_Y_LPARAM(lParam);
4656 int nItem = m_tab.HitTest(&hti);
4657 if(nItem != -1)
4658 MovePage(m_nActivePage, nItem);
4659 }
4660
4661 ::ReleaseCapture();
4662 }
4663
4664 bHandled = FALSE;
4665 return 0;
4666 }
4667
4668 LRESULT OnTabCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
4669 {
4670 if(m_bTabCapture)
4671 {
4672 m_bTabCapture = false;
4673
4674 if(m_bTabDrag)
4675 {
4676 m_bTabDrag = false;
4677 T* pT = static_cast<T*>(this);
4678 pT->DrawMoveMark(-1);
4679
4680 #ifndef _WIN32_WCE
4681 m_ilDrag.DragLeave(GetDesktopWindow());
4682 #endif // !_WIN32_WCE
4683 m_ilDrag.EndDrag();
4684
4685 m_ilDrag.Destroy();
4686 m_ilDrag.m_hImageList = NULL;
4687 }
4688 }
4689
4690 bHandled = FALSE;
4691 return 0;
4692 }
4693
4694 LRESULT OnTabMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
4695 {
4696 bHandled = FALSE;
4697
4698 if(m_bTabCapture)
4699 {
4700 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
4701
4702 if(!m_bTabDrag)
4703 {
4704 #ifndef _WIN32_WCE
4705 if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CXDRAG) ||
4706 abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= ::GetSystemMetrics(SM_CYDRAG))
4707 #else // CE specific
4708 if(abs(m_ptStartDrag.x - GET_X_LPARAM(lParam)) >= 4 ||
4709 abs(m_ptStartDrag.y - GET_Y_LPARAM(lParam)) >= 4)
4710 #endif // _WIN32_WCE
4711 {
4712 T* pT = static_cast<T*>(this);
4713 pT->GenerateDragImage(m_nActivePage);
4714
4715 int cxCursor = ::GetSystemMetrics(SM_CXCURSOR);
4716 int cyCursor = ::GetSystemMetrics(SM_CYCURSOR);
4717 m_ilDrag.BeginDrag(0, -(cxCursor / 2), -(cyCursor / 2));
4718 #ifndef _WIN32_WCE
4719 POINT ptEnter = m_ptStartDrag;
4720 m_tab.ClientToScreen(&ptEnter);
4721 m_ilDrag.DragEnter(GetDesktopWindow(), ptEnter);
4722 #endif // !_WIN32_WCE
4723
4724 m_bTabDrag = true;
4725 }
4726 }
4727
4728 if(m_bTabDrag)
4729 {
4730 TCHITTESTINFO hti = { 0 };
4731 hti.pt = pt;
4732 int nItem = m_tab.HitTest(&hti);
4733
4734 T* pT = static_cast<T*>(this);
4735 pT->SetMoveCursor(nItem != -1);
4736
4737 if(m_nInsertItem != nItem)
4738 pT->DrawMoveMark(nItem);
4739
4740 m_ilDrag.DragShowNolock((nItem != -1) ? TRUE : FALSE);
4741 m_tab.ClientToScreen(&pt);
4742 m_ilDrag.DragMove(pt);
4743
4744 bHandled = TRUE;
4745 }
4746 }
4747
4748 return 0;
4749 }
4750
4751 LRESULT OnTabRButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
4752 {
4753 TCHITTESTINFO hti = { 0 };
4754 hti.pt.x = GET_X_LPARAM(lParam);
4755 hti.pt.y = GET_Y_LPARAM(lParam);
4756 int nItem = m_tab.HitTest(&hti);
4757 if(nItem != -1)
4758 {
4759 T* pT = static_cast<T*>(this);
4760 pT->OnContextMenu(nItem, hti.pt);
4761 }
4762
4763 return 0;
4764 }
4765
4766 LRESULT OnTabSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
4767 {
4768 bool bShift = (::GetKeyState(VK_SHIFT) < 0);
4769 if(wParam == VK_F10 && bShift)
4770 {
4771 if(m_nActivePage != -1)
4772 {
4773 RECT rect = { 0 };
4774 m_tab.GetItemRect(m_nActivePage, &rect);
4775 POINT pt = { rect.left, rect.bottom };
4776 T* pT = static_cast<T*>(this);
4777 pT->OnContextMenu(m_nActivePage, pt);
4778 }
4779 }
4780 else
4781 {
4782 bHandled = FALSE;
4783 }
4784
4785 return 0;
4786 }
4787
4788 // Implementation helpers
4789 bool IsValidPageIndex(int nPage) const
4790 {
4791 return (nPage >= 0 && nPage < GetPageCount());
4792 }
4793
4794 bool MovePage(int nMovePage, int nInsertBeforePage)
4795 {
4796 ATLASSERT(IsValidPageIndex(nMovePage));
4797 ATLASSERT(IsValidPageIndex(nInsertBeforePage));
4798
4799 if(!IsValidPageIndex(nMovePage) || !IsValidPageIndex(nInsertBeforePage))
4800 return false;
4801
4802 if(nMovePage == nInsertBeforePage)
4803 return true; // nothing to do
4804
4805 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
4806 LPTSTR lpstrTabText = buff.Allocate(m_cchTabTextLength + 1);
4807 if(lpstrTabText == NULL)
4808 return false;
4809 TCITEMEXTRA tcix = { 0 };
4810 tcix.tciheader.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
4811 tcix.tciheader.pszText = lpstrTabText;
4812 tcix.tciheader.cchTextMax = m_cchTabTextLength + 1;
4813 BOOL bRet = m_tab.GetItem(nMovePage, tcix);
4814 ATLASSERT(bRet != FALSE);
4815 if(bRet == FALSE)
4816 return false;
4817
4818 int nInsertItem = (nInsertBeforePage > nMovePage) ? nInsertBeforePage + 1 : nInsertBeforePage;
4819 int nNewItem = m_tab.InsertItem(nInsertItem, tcix);
4820 ATLASSERT(nNewItem == nInsertItem);
4821 if(nNewItem != nInsertItem)
4822 {
4823 ATLVERIFY(m_tab.DeleteItem(nNewItem));
4824 return false;
4825 }
4826
4827 if(nMovePage > nInsertBeforePage)
4828 ATLVERIFY(m_tab.DeleteItem(nMovePage + 1) != FALSE);
4829 else if(nMovePage < nInsertBeforePage)
4830 ATLVERIFY(m_tab.DeleteItem(nMovePage) != FALSE);
4831
4832 SetActivePage(nInsertBeforePage);
4833 T* pT = static_cast<T*>(this);
4834 pT->OnPageActivated(m_nActivePage);
4835
4836 return true;
4837 }
4838
4839 // Implementation overrideables
4840 bool CreateTabControl()
4841 {
4842 #ifndef _WIN32_WCE
4843 m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_TOOLTIPS, 0, m_nTabID);
4844 #else // CE specific
4845 m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, m_nTabID);
4846 #endif // _WIN32_WCE
4847 ATLASSERT(m_tab.m_hWnd != NULL);
4848 if(m_tab.m_hWnd == NULL)
4849 return false;
4850
4851 m_tab.SetFont(AtlCreateControlFont());
4852 m_bInternalFont = true;
4853
4854 m_tab.SetItemExtra(sizeof(TABVIEWPAGE));
4855
4856 T* pT = static_cast<T*>(this);
4857 m_cyTabHeight = pT->CalcTabHeight();
4858
4859 return true;
4860 }
4861
4862 int CalcTabHeight()
4863 {
4864 int nCount = m_tab.GetItemCount();
4865 TCHAR szText[] = _T("NS");
4866 TCITEMEXTRA tcix = { 0 };
4867 tcix.tciheader.mask = TCIF_TEXT;
4868 tcix.tciheader.pszText = szText;
4869 int nIndex = m_tab.InsertItem(nCount, tcix);
4870
4871 RECT rect = { 0, 0, 1000, 1000 };
4872 m_tab.AdjustRect(FALSE, &rect);
4873
4874 RECT rcWnd = { 0, 0, 1000, rect.top };
4875 ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle());
4876
4877 int nHeight = rcWnd.bottom - rcWnd.top;
4878
4879 m_tab.DeleteItem(nIndex);
4880
4881 return nHeight;
4882 }
4883
4884 void ShowTabControl(bool bShow)
4885 {
4886 m_tab.ShowWindow(bShow ? SW_SHOWNOACTIVATE : SW_HIDE);
4887 T* pT = static_cast<T*>(this);
4888 pT->UpdateLayout();
4889 }
4890
4891 void UpdateLayout()
4892 {
4893 RECT rect = { 0 };
4894 GetClientRect(&rect);
4895
4896 int cyOffset = 0;
4897 if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0))
4898 {
4899 m_tab.SetWindowPos(NULL, 0, 0, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER);
4900 cyOffset = m_cyTabHeight;
4901 }
4902
4903 if(m_nActivePage != -1)
4904 ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, cyOffset, rect.right - rect.left, rect.bottom - rect.top - cyOffset, SWP_NOZORDER);
4905 }
4906
4907 void UpdateMenu()
4908 {
4909 if(m_menu.m_hMenu != NULL)
4910 BuildWindowMenu(m_menu, m_nMenuItemsCount, m_bEmptyMenuItem, m_bWindowsMenuItem, m_bActivePageMenuItem, m_bActiveAsDefaultMenuItem);
4911 }
4912
4913 void UpdateTitleBar()
4914 {
4915 if(!m_wndTitleBar.IsWindow() || m_lpstrTitleBarBase == NULL)
4916 return; // nothing to do
4917
4918 if(m_nActivePage != -1)
4919 {
4920 T* pT = static_cast<T*>(this);
4921 LPCTSTR lpstrTitle = pT->GetPageTitle(m_nActivePage);
4922 LPCTSTR lpstrDivider = pT->GetTitleDividerText();
4923 int cchBuffer = m_cchTitleBarLength + lstrlen(lpstrDivider) + lstrlen(m_lpstrTitleBarBase) + 1;
4924 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
4925 LPTSTR lpstrPageTitle = buff.Allocate(cchBuffer);
4926 ATLASSERT(lpstrPageTitle != NULL);
4927 if(lpstrPageTitle != NULL)
4928 {
4929 pT->ShortenTitle(lpstrTitle, lpstrPageTitle, m_cchTitleBarLength + 1);
4930 SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, lpstrDivider);
4931 SecureHelper::strcat_x(lpstrPageTitle, cchBuffer, m_lpstrTitleBarBase);
4932 }
4933 else
4934 {
4935 lpstrPageTitle = m_lpstrTitleBarBase;
4936 }
4937
4938 m_wndTitleBar.SetWindowText(lpstrPageTitle);
4939 }
4940 else
4941 {
4942 m_wndTitleBar.SetWindowText(m_lpstrTitleBarBase);
4943 }
4944 }
4945
4946 void DrawMoveMark(int nItem)
4947 {
4948 T* pT = static_cast<T*>(this);
4949
4950 if(m_nInsertItem != -1)
4951 {
4952 RECT rect = { 0 };
4953 pT->GetMoveMarkRect(rect);
4954 m_tab.InvalidateRect(&rect);
4955 }
4956
4957 m_nInsertItem = nItem;
4958
4959 if(m_nInsertItem != -1)
4960 {
4961 CClientDC dc(m_tab.m_hWnd);
4962
4963 RECT rect = { 0 };
4964 pT->GetMoveMarkRect(rect);
4965
4966 CPen pen;
4967 pen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOWTEXT));
4968 CBrush brush;
4969 brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT));
4970
4971 HPEN hPenOld = dc.SelectPen(pen);
4972 HBRUSH hBrushOld = dc.SelectBrush(brush);
4973
4974 int x = rect.left;
4975 int y = rect.top;
4976 POINT ptsTop[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y + m_cyMoveMark } };
4977 dc.Polygon(ptsTop, 3);
4978
4979 y = rect.bottom - 1;
4980 POINT ptsBottom[3] = { { x, y }, { x + m_cxMoveMark, y }, { x + (m_cxMoveMark / 2), y - m_cyMoveMark } };
4981 dc.Polygon(ptsBottom, 3);
4982
4983 dc.SelectPen(hPenOld);
4984 dc.SelectBrush(hBrushOld);
4985 }
4986 }
4987
4988 void GetMoveMarkRect(RECT& rect) const
4989 {
4990 m_tab.GetClientRect(&rect);
4991
4992 RECT rcItem = { 0 };
4993 m_tab.GetItemRect(m_nInsertItem, &rcItem);
4994
4995 if(m_nInsertItem <= m_nActivePage)
4996 {
4997 rect.left = rcItem.left - m_cxMoveMark / 2 - 1;
4998 rect.right = rcItem.left + m_cxMoveMark / 2;
4999 }
5000 else
5001 {
5002 rect.left = rcItem.right - m_cxMoveMark / 2 - 1;
5003 rect.right = rcItem.right + m_cxMoveMark / 2;
5004 }
5005 }
5006
5007 void SetMoveCursor(bool bCanMove)
5008 {
5009 ::SetCursor(::LoadCursor(NULL, bCanMove ? IDC_ARROW : IDC_NO));
5010 }
5011
5012 void GenerateDragImage(int nItem)
5013 {
5014 ATLASSERT(IsValidPageIndex(nItem));
5015
5016 #ifndef _WIN32_WCE
5017 RECT rcItem = { 0 };
5018 m_tab.GetItemRect(nItem, &rcItem);
5019 ::InflateRect(&rcItem, 2, 2); // make bigger to cover selected item
5020 #else // CE specific
5021 nItem; // avoid level 4 warning
5022 RECT rcItem = { 0, 0, 40, 20 };
5023 #endif // _WIN32_WCE
5024
5025 ATLASSERT(m_ilDrag.m_hImageList == NULL);
5026 m_ilDrag.Create(rcItem.right - rcItem.left, rcItem.bottom - rcItem.top, ILC_COLORDDB | ILC_MASK, 1, 1);
5027
5028 CClientDC dc(m_hWnd);
5029 CDC dcMem;
5030 dcMem.CreateCompatibleDC(dc);
5031 ATLASSERT(dcMem.m_hDC != NULL);
5032 dcMem.SetViewportOrg(-rcItem.left, -rcItem.top);
5033
5034 CBitmap bmp;
5035 bmp.CreateCompatibleBitmap(dc, rcItem.right - rcItem.left, rcItem.bottom - rcItem.top);
5036 ATLASSERT(bmp.m_hBitmap != NULL);
5037
5038 HBITMAP hBmpOld = dcMem.SelectBitmap(bmp);
5039 #ifndef _WIN32_WCE
5040 m_tab.SendMessage(WM_PRINTCLIENT, (WPARAM)dcMem.m_hDC);
5041 #else // CE specific
5042 dcMem.Rectangle(&rcItem);
5043 #endif // _WIN32_WCE
5044 dcMem.SelectBitmap(hBmpOld);
5045
5046 ATLVERIFY(m_ilDrag.Add(bmp.m_hBitmap, RGB(255, 0, 255)) != -1);
5047 }
5048
5049 void ShortenTitle(LPCTSTR lpstrTitle, LPTSTR lpstrShortTitle, int cchShortTitle)
5050 {
5051 if(lstrlen(lpstrTitle) >= cchShortTitle)
5052 {
5053 LPCTSTR lpstrEllipsis = _T("...");
5054 int cchEllipsis = lstrlen(lpstrEllipsis);
5055 SecureHelper::strncpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle, cchShortTitle - cchEllipsis - 1);
5056 SecureHelper::strcat_x(lpstrShortTitle, cchShortTitle, lpstrEllipsis);
5057 }
5058 else
5059 {
5060 SecureHelper::strcpy_x(lpstrShortTitle, cchShortTitle, lpstrTitle);
5061 }
5062 }
5063
5064 #ifndef _WIN32_WCE
5065 void UpdateTooltipText(LPNMTTDISPINFO pTTDI)
5066 {
5067 ATLASSERT(pTTDI != NULL);
5068 pTTDI->lpszText = (LPTSTR)GetPageTitle((int)pTTDI->hdr.idFrom);
5069 }
5070 #endif // !_WIN32_WCE
5071
5072 // Text for menu items and title bar - override to provide different strings
5073 static LPCTSTR GetEmptyListText()
5074 {
5075 return _T("(Empty)");
5076 }
5077
5078 static LPCTSTR GetWindowsMenuItemText()
5079 {
5080 return _T("&Windows...");
5081 }
5082
5083 static LPCTSTR GetTitleDividerText()
5084 {
5085 return _T(" - ");
5086 }
5087
5088 // Notifications - override to provide different behavior
5089 void OnPageActivated(int nPage)
5090 {
5091 NMHDR nmhdr = { 0 };
5092 nmhdr.hwndFrom = m_hWnd;
5093 nmhdr.idFrom = nPage;
5094 nmhdr.code = TBVN_PAGEACTIVATED;
5095 ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
5096 }
5097
5098 void OnContextMenu(int nPage, POINT pt)
5099 {
5100 m_tab.ClientToScreen(&pt);
5101
5102 TBVCONTEXTMENUINFO cmi = { 0 };
5103 cmi.hdr.hwndFrom = m_hWnd;
5104 cmi.hdr.idFrom = nPage;
5105 cmi.hdr.code = TBVN_CONTEXTMENU;
5106 cmi.pt = pt;
5107 ::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&cmi);
5108 }
5109 };
5110
5111 class CTabView : public CTabViewImpl<CTabView>
5112 {
5113 public:
5114 DECLARE_WND_CLASS_EX(_T("WTL_TabView"), 0, COLOR_APPWORKSPACE)
5115 };
5116
5117 }; // namespace WTL
5118
5119 #endif // __ATLCTRLX_H__
+0
-684
src/third_party/wtl/Include/atlddx.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLDDX_H__
9 #define __ATLDDX_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlddx.h requires atlapp.h to be included first
15 #endif
16
17 #if defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT)
18 #error Cannot use floating point DDX with _ATL_MIN_CRT defined
19 #endif // defined(_ATL_USE_DDX_FLOAT) && defined(_ATL_MIN_CRT)
20
21 #ifdef _ATL_USE_DDX_FLOAT
22 #include <float.h>
23 #endif // _ATL_USE_DDX_FLOAT
24
25
26 ///////////////////////////////////////////////////////////////////////////////
27 // Classes in this file:
28 //
29 // CWinDataExchange<T>
30
31
32 namespace WTL
33 {
34
35 // Constants
36 #define DDX_LOAD FALSE
37 #define DDX_SAVE TRUE
38
39 // DDX map macros
40 #define BEGIN_DDX_MAP(thisClass) \
41 BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) \
42 { \
43 (bSaveAndValidate); \
44 (nCtlID);
45
46 #define DDX_TEXT(nID, var) \
47 if(nCtlID == (UINT)-1 || nCtlID == nID) \
48 { \
49 if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \
50 return FALSE; \
51 }
52
53 #define DDX_TEXT_LEN(nID, var, len) \
54 if(nCtlID == (UINT)-1 || nCtlID == nID) \
55 { \
56 if(!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TRUE, len)) \
57 return FALSE; \
58 }
59
60 #define DDX_INT(nID, var) \
61 if(nCtlID == (UINT)-1 || nCtlID == nID) \
62 { \
63 if(!DDX_Int(nID, var, TRUE, bSaveAndValidate)) \
64 return FALSE; \
65 }
66
67 #define DDX_INT_RANGE(nID, var, min, max) \
68 if(nCtlID == (UINT)-1 || nCtlID == nID) \
69 { \
70 if(!DDX_Int(nID, var, TRUE, bSaveAndValidate, TRUE, min, max)) \
71 return FALSE; \
72 }
73
74 #define DDX_UINT(nID, var) \
75 if(nCtlID == (UINT)-1 || nCtlID == nID) \
76 { \
77 if(!DDX_Int(nID, var, FALSE, bSaveAndValidate)) \
78 return FALSE; \
79 }
80
81 #define DDX_UINT_RANGE(nID, var, min, max) \
82 if(nCtlID == (UINT)-1 || nCtlID == nID) \
83 { \
84 if(!DDX_Int(nID, var, FALSE, bSaveAndValidate, TRUE, min, max)) \
85 return FALSE; \
86 }
87
88 #ifdef _ATL_USE_DDX_FLOAT
89 #define DDX_FLOAT(nID, var) \
90 if(nCtlID == (UINT)-1 || nCtlID == nID) \
91 { \
92 if(!DDX_Float(nID, var, bSaveAndValidate)) \
93 return FALSE; \
94 }
95
96 #define DDX_FLOAT_RANGE(nID, var, min, max) \
97 if(nCtlID == (UINT)-1 || nCtlID == nID) \
98 { \
99 if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max)) \
100 return FALSE; \
101 }
102 #define DDX_FLOAT_P(nID, var, precision) \
103 if(nCtlID == (UINT)-1 || nCtlID == nID) \
104 { \
105 if(!DDX_Float(nID, var, bSaveAndValidate, FALSE, 0, 0, precision)) \
106 return FALSE; \
107 }
108
109 #define DDX_FLOAT_P_RANGE(nID, var, min, max, precision) \
110 if(nCtlID == (UINT)-1 || nCtlID == nID) \
111 { \
112 if(!DDX_Float(nID, var, bSaveAndValidate, TRUE, min, max, precision)) \
113 return FALSE; \
114 }
115 #endif // _ATL_USE_DDX_FLOAT
116
117 #define DDX_CONTROL(nID, obj) \
118 if(nCtlID == (UINT)-1 || nCtlID == nID) \
119 DDX_Control(nID, obj, bSaveAndValidate);
120
121 #define DDX_CONTROL_HANDLE(nID, obj) \
122 if(nCtlID == (UINT)-1 || nCtlID == nID) \
123 DDX_Control_Handle(nID, obj, bSaveAndValidate);
124
125 #define DDX_CHECK(nID, var) \
126 if(nCtlID == (UINT)-1 || nCtlID == nID) \
127 DDX_Check(nID, var, bSaveAndValidate);
128
129 #define DDX_RADIO(nID, var) \
130 if(nCtlID == (UINT)-1 || nCtlID == nID) \
131 DDX_Radio(nID, var, bSaveAndValidate);
132
133 #define END_DDX_MAP() \
134 return TRUE; \
135 }
136
137 // DDX support for Tab, Combo, ListBox and ListView selection index
138 // Note: Specialized versions require atlctrls.h to be included first
139 #if (_MSC_VER >= 1300)
140
141 #define DDX_INDEX(CtrlClass, nID, var) \
142 if(nCtlID == (UINT)-1 || nCtlID == nID) \
143 DDX_Index<CtrlClass>(nID, var, bSaveAndValidate);
144
145 #ifdef __ATLCTRLS_H__
146 #define DDX_TAB_INDEX(nID, var) DDX_INDEX(WTL::CTabCtrl, nID, var)
147 #ifndef WIN32_PLATFORM_WFSP // No COMBOBOX on SmartPhones
148 #define DDX_COMBO_INDEX(nID, var) DDX_INDEX(WTL::CComboBox, nID, var)
149 #endif
150 #define DDX_LISTBOX_INDEX(nID, var) DDX_INDEX(WTL::CListBox, nID, var)
151 #define DDX_LISTVIEW_INDEX(nID, var) DDX_INDEX(WTL::CListViewCtrl, nID, var)
152 #endif // __ATLCTRLS_H__
153
154 #endif // (_MSC_VER >= 1300)
155
156
157 ///////////////////////////////////////////////////////////////////////////////
158 // CWinDataExchange - provides support for DDX
159
160 template <class T>
161 class CWinDataExchange
162 {
163 public:
164 // Data exchange method - override in your derived class
165 BOOL DoDataExchange(BOOL /*bSaveAndValidate*/ = FALSE, UINT /*nCtlID*/ = (UINT)-1)
166 {
167 // this one should never be called, override it in
168 // your derived class by implementing DDX map
169 ATLASSERT(FALSE);
170 return FALSE;
171 }
172
173 // Helpers for validation error reporting
174 enum _XDataType
175 {
176 ddxDataNull = 0,
177 ddxDataText = 1,
178 ddxDataInt = 2,
179 ddxDataFloat = 3,
180 ddxDataDouble = 4
181 };
182
183 struct _XTextData
184 {
185 int nLength;
186 int nMaxLength;
187 };
188
189 struct _XIntData
190 {
191 long nVal;
192 long nMin;
193 long nMax;
194 };
195
196 struct _XFloatData
197 {
198 double nVal;
199 double nMin;
200 double nMax;
201 };
202
203 struct _XData
204 {
205 _XDataType nDataType;
206 union
207 {
208 _XTextData textData;
209 _XIntData intData;
210 _XFloatData floatData;
211 };
212 };
213
214 // Text exchange
215 BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int cbSize, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
216 {
217 T* pT = static_cast<T*>(this);
218 BOOL bSuccess = TRUE;
219
220 if(bSave)
221 {
222 HWND hWndCtrl = pT->GetDlgItem(nID);
223 int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, cbSize / sizeof(TCHAR));
224 if(nRetLen < ::GetWindowTextLength(hWndCtrl))
225 bSuccess = FALSE;
226 }
227 else
228 {
229 ATLASSERT(!bValidate || (lstrlen(lpstrText) <= nLength));
230 bSuccess = pT->SetDlgItemText(nID, lpstrText);
231 }
232
233 if(!bSuccess)
234 {
235 pT->OnDataExchangeError(nID, bSave);
236 }
237 else if(bSave && bValidate) // validation
238 {
239 ATLASSERT(nLength > 0);
240 if(lstrlen(lpstrText) > nLength)
241 {
242 _XData data = { ddxDataText };
243 data.textData.nLength = lstrlen(lpstrText);
244 data.textData.nMaxLength = nLength;
245 pT->OnDataValidateError(nID, bSave, data);
246 bSuccess = FALSE;
247 }
248 }
249 return bSuccess;
250 }
251
252 BOOL DDX_Text(UINT nID, BSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
253 {
254 T* pT = static_cast<T*>(this);
255 BOOL bSuccess = TRUE;
256
257 if(bSave)
258 {
259 bSuccess = pT->GetDlgItemText(nID, bstrText);
260 }
261 else
262 {
263 USES_CONVERSION;
264 LPTSTR lpstrText = OLE2T(bstrText);
265 ATLASSERT(!bValidate || (lstrlen(lpstrText) <= nLength));
266 bSuccess = pT->SetDlgItemText(nID, lpstrText);
267 }
268
269 if(!bSuccess)
270 {
271 pT->OnDataExchangeError(nID, bSave);
272 }
273 else if(bSave && bValidate) // validation
274 {
275 ATLASSERT(nLength > 0);
276 if((int)::SysStringLen(bstrText) > nLength)
277 {
278 _XData data = { ddxDataText };
279 data.textData.nLength = (int)::SysStringLen(bstrText);
280 data.textData.nMaxLength = nLength;
281 pT->OnDataValidateError(nID, bSave, data);
282 bSuccess = FALSE;
283 }
284 }
285 return bSuccess;
286 }
287
288 BOOL DDX_Text(UINT nID, ATL::CComBSTR& bstrText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
289 {
290 T* pT = static_cast<T*>(this);
291 BOOL bSuccess = TRUE;
292
293 if(bSave)
294 {
295 bSuccess = pT->GetDlgItemText(nID, (BSTR&)bstrText);
296 }
297 else
298 {
299 USES_CONVERSION;
300 LPTSTR lpstrText = OLE2T(bstrText);
301 ATLASSERT(!bValidate || (lstrlen(lpstrText) <= nLength));
302 bSuccess = pT->SetDlgItemText(nID, lpstrText);
303 }
304
305 if(!bSuccess)
306 {
307 pT->OnDataExchangeError(nID, bSave);
308 }
309 else if(bSave && bValidate) // validation
310 {
311 ATLASSERT(nLength > 0);
312 if((int)bstrText.Length() > nLength)
313 {
314 _XData data = { ddxDataText };
315 data.textData.nLength = (int)bstrText.Length();
316 data.textData.nMaxLength = nLength;
317 pT->OnDataValidateError(nID, bSave, data);
318 bSuccess = FALSE;
319 }
320 }
321 return bSuccess;
322 }
323
324 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
325 BOOL DDX_Text(UINT nID, _CSTRING_NS::CString& strText, int /*cbSize*/, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0)
326 {
327 T* pT = static_cast<T*>(this);
328 BOOL bSuccess = TRUE;
329
330 if(bSave)
331 {
332 HWND hWndCtrl = pT->GetDlgItem(nID);
333 int nLen = ::GetWindowTextLength(hWndCtrl);
334 int nRetLen = -1;
335 LPTSTR lpstr = strText.GetBufferSetLength(nLen);
336 if(lpstr != NULL)
337 {
338 nRetLen = ::GetWindowText(hWndCtrl, lpstr, nLen + 1);
339 strText.ReleaseBuffer();
340 }
341 if(nRetLen < nLen)
342 bSuccess = FALSE;
343 }
344 else
345 {
346 bSuccess = pT->SetDlgItemText(nID, strText);
347 }
348
349 if(!bSuccess)
350 {
351 pT->OnDataExchangeError(nID, bSave);
352 }
353 else if(bSave && bValidate) // validation
354 {
355 ATLASSERT(nLength > 0);
356 if(strText.GetLength() > nLength)
357 {
358 _XData data = { ddxDataText };
359 data.textData.nLength = strText.GetLength();
360 data.textData.nMaxLength = nLength;
361 pT->OnDataValidateError(nID, bSave, data);
362 bSuccess = FALSE;
363 }
364 }
365 return bSuccess;
366 }
367 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
368
369 // Numeric exchange
370 template <class Type>
371 BOOL DDX_Int(UINT nID, Type& nVal, BOOL bSigned, BOOL bSave, BOOL bValidate = FALSE, Type nMin = 0, Type nMax = 0)
372 {
373 T* pT = static_cast<T*>(this);
374 BOOL bSuccess = TRUE;
375
376 if(bSave)
377 {
378 nVal = (Type)pT->GetDlgItemInt(nID, &bSuccess, bSigned);
379 }
380 else
381 {
382 ATLASSERT(!bValidate || (nVal >= nMin && nVal <= nMax));
383 bSuccess = pT->SetDlgItemInt(nID, nVal, bSigned);
384 }
385
386 if(!bSuccess)
387 {
388 pT->OnDataExchangeError(nID, bSave);
389 }
390 else if(bSave && bValidate) // validation
391 {
392 ATLASSERT(nMin != nMax);
393 if(nVal < nMin || nVal > nMax)
394 {
395 _XData data = { ddxDataInt };
396 data.intData.nVal = (long)nVal;
397 data.intData.nMin = (long)nMin;
398 data.intData.nMax = (long)nMax;
399 pT->OnDataValidateError(nID, bSave, data);
400 bSuccess = FALSE;
401 }
402 }
403 return bSuccess;
404 }
405
406 // Float exchange
407 #ifdef _ATL_USE_DDX_FLOAT
408 static BOOL _AtlSimpleFloatParse(LPCTSTR lpszText, double& d)
409 {
410 ATLASSERT(lpszText != NULL);
411 while (*lpszText == _T(' ') || *lpszText == _T('\t'))
412 lpszText++;
413
414 TCHAR chFirst = lpszText[0];
415 d = _tcstod(lpszText, (LPTSTR*)&lpszText);
416 if (d == 0.0 && chFirst != _T('0'))
417 return FALSE; // could not convert
418 while (*lpszText == _T(' ') || *lpszText == _T('\t'))
419 lpszText++;
420
421 if (*lpszText != _T('\0'))
422 return FALSE; // not terminated properly
423
424 return TRUE;
425 }
426
427 BOOL DDX_Float(UINT nID, float& nVal, BOOL bSave, BOOL bValidate = FALSE, float nMin = 0.F, float nMax = 0.F, int nPrecision = FLT_DIG)
428 {
429 T* pT = static_cast<T*>(this);
430 BOOL bSuccess = TRUE;
431 const int cchBuff = 32;
432 TCHAR szBuff[cchBuff] = { 0 };
433
434 if(bSave)
435 {
436 pT->GetDlgItemText(nID, szBuff, cchBuff);
437 double d = 0;
438 if(_AtlSimpleFloatParse(szBuff, d))
439 nVal = (float)d;
440 else
441 bSuccess = FALSE;
442 }
443 else
444 {
445 ATLASSERT(!bValidate || (nVal >= nMin && nVal <= nMax));
446 SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal);
447 bSuccess = pT->SetDlgItemText(nID, szBuff);
448 }
449
450 if(!bSuccess)
451 {
452 pT->OnDataExchangeError(nID, bSave);
453 }
454 else if(bSave && bValidate) // validation
455 {
456 ATLASSERT(nMin != nMax);
457 if(nVal < nMin || nVal > nMax)
458 {
459 _XData data = { ddxDataFloat };
460 data.floatData.nVal = (double)nVal;
461 data.floatData.nMin = (double)nMin;
462 data.floatData.nMax = (double)nMax;
463 pT->OnDataValidateError(nID, bSave, data);
464 bSuccess = FALSE;
465 }
466 }
467 return bSuccess;
468 }
469
470 BOOL DDX_Float(UINT nID, double& nVal, BOOL bSave, BOOL bValidate = FALSE, double nMin = 0., double nMax = 0., int nPrecision = DBL_DIG)
471 {
472 T* pT = static_cast<T*>(this);
473 BOOL bSuccess = TRUE;
474 const int cchBuff = 32;
475 TCHAR szBuff[cchBuff] = { 0 };
476
477 if(bSave)
478 {
479 pT->GetDlgItemText(nID, szBuff, cchBuff);
480 double d = 0;
481 if(_AtlSimpleFloatParse(szBuff, d))
482 nVal = d;
483 else
484 bSuccess = FALSE;
485 }
486 else
487 {
488 ATLASSERT(!bValidate || (nVal >= nMin && nVal <= nMax));
489 SecureHelper::sprintf_x(szBuff, cchBuff, _T("%.*g"), nPrecision, nVal);
490 bSuccess = pT->SetDlgItemText(nID, szBuff);
491 }
492
493 if(!bSuccess)
494 {
495 pT->OnDataExchangeError(nID, bSave);
496 }
497 else if(bSave && bValidate) // validation
498 {
499 ATLASSERT(nMin != nMax);
500 if(nVal < nMin || nVal > nMax)
501 {
502 _XData data = { ddxDataFloat };
503 data.floatData.nVal = nVal;
504 data.floatData.nMin = nMin;
505 data.floatData.nMax = nMax;
506 pT->OnDataValidateError(nID, bSave, data);
507 bSuccess = FALSE;
508 }
509 }
510 return bSuccess;
511 }
512 #endif // _ATL_USE_DDX_FLOAT
513
514 // Full control subclassing (for CWindowImpl derived controls)
515 template <class TControl>
516 void DDX_Control(UINT nID, TControl& ctrl, BOOL bSave)
517 {
518 if(!bSave && ctrl.m_hWnd == NULL)
519 {
520 T* pT = static_cast<T*>(this);
521 ctrl.SubclassWindow(pT->GetDlgItem(nID));
522 }
523 }
524
525 // Simple control attaching (for HWND wrapper controls)
526 template <class TControl>
527 void DDX_Control_Handle(UINT nID, TControl& ctrl, BOOL bSave)
528 {
529 if(!bSave && ctrl.m_hWnd == NULL)
530 {
531 T* pT = static_cast<T*>(this);
532 ctrl = pT->GetDlgItem(nID);
533 }
534 }
535
536 // Control state
537 void DDX_Check(UINT nID, int& nValue, BOOL bSave)
538 {
539 T* pT = static_cast<T*>(this);
540 HWND hWndCtrl = pT->GetDlgItem(nID);
541 if(bSave)
542 {
543 nValue = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L);
544 ATLASSERT(nValue >= 0 && nValue <= 2);
545 }
546 else
547 {
548 if(nValue < 0 || nValue > 2)
549 {
550 ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - dialog data checkbox value (%d) out of range.\n"), nValue);
551 nValue = 0; // default to off
552 }
553 ::SendMessage(hWndCtrl, BM_SETCHECK, nValue, 0L);
554 }
555 }
556
557 // variant that supports bool (checked/not-checked, no intermediate state)
558 void DDX_Check(UINT nID, bool& bCheck, BOOL bSave)
559 {
560 int nValue = bCheck ? 1 : 0;
561 DDX_Check(nID, nValue, bSave);
562
563 if(bSave)
564 {
565 if(nValue == 2)
566 ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - checkbox state (%d) out of supported range.\n"), nValue);
567 bCheck = (nValue == 1);
568 }
569 }
570
571 void DDX_Radio(UINT nID, int& nValue, BOOL bSave)
572 {
573 T* pT = static_cast<T*>(this);
574 HWND hWndCtrl = pT->GetDlgItem(nID);
575 ATLASSERT(hWndCtrl != NULL);
576
577 // must be first in a group of auto radio buttons
578 ATLASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP);
579 ATLASSERT(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON);
580
581 if(bSave)
582 nValue = -1; // value if none found
583
584 // walk all children in group
585 int nButton = 0;
586 do
587 {
588 if(::SendMessage(hWndCtrl, WM_GETDLGCODE, 0, 0L) & DLGC_RADIOBUTTON)
589 {
590 // control in group is a radio button
591 if(bSave)
592 {
593 if(::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L) != 0)
594 {
595 ATLASSERT(nValue == -1); // only set once
596 nValue = nButton;
597 }
598 }
599 else
600 {
601 // select button
602 ::SendMessage(hWndCtrl, BM_SETCHECK, (nButton == nValue), 0L);
603 }
604 nButton++;
605 }
606 else
607 {
608 ATLTRACE2(atlTraceUI, 0, _T("ATL: Warning - skipping non-radio button in group.\n"));
609 }
610 hWndCtrl = ::GetWindow(hWndCtrl, GW_HWNDNEXT);
611 }
612 while (hWndCtrl != NULL && !(GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP));
613 }
614
615 // DDX support for Tab, Combo, ListBox and ListView selection index
616 #if (_MSC_VER >= 1300)
617 template <class TCtrl>
618 INT _getSel(TCtrl& tCtrl)
619 {
620 return tCtrl.GetCurSel();
621 }
622
623 template <class TCtrl>
624 void _setSel(TCtrl& tCtrl, INT iSel)
625 {
626 if(iSel < 0)
627 tCtrl.SetCurSel(-1);
628 else
629 tCtrl.SetCurSel(iSel);
630 }
631
632 #ifdef __ATLCTRLS_H__
633 // ListViewCtrl specialization
634 template <>
635 INT _getSel(WTL::CListViewCtrl& tCtrl)
636 {
637 return tCtrl.GetSelectedIndex();
638 }
639
640 template <>
641 void _setSel(WTL::CListViewCtrl& tCtrl, INT iSel)
642 {
643 if(iSel < 0)
644 tCtrl.SelectItem(-1);
645 else
646 tCtrl.SelectItem(iSel);
647 }
648 #endif // __ATLCTRLS_H__
649
650 template <class TCtrl>
651 void DDX_Index(UINT nID, INT& nVal, BOOL bSave)
652 {
653 T* pT = static_cast<T*>(this);
654 TCtrl ctrl(pT->GetDlgItem(nID));
655
656 if(bSave)
657 nVal = _getSel(ctrl);
658 else
659 _setSel(ctrl, nVal);
660 }
661 #endif // (_MSC_VER >= 1300)
662
663 // Overrideables
664 void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/)
665 {
666 // Override to display an error message
667 ::MessageBeep((UINT)-1);
668 T* pT = static_cast<T*>(this);
669 ::SetFocus(pT->GetDlgItem(nCtrlID));
670 }
671
672 void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/)
673 {
674 // Override to display an error message
675 ::MessageBeep((UINT)-1);
676 T* pT = static_cast<T*>(this);
677 ::SetFocus(pT->GetDlgItem(nCtrlID));
678 }
679 };
680
681 }; // namespace WTL
682
683 #endif // __ATLDDX_H__
+0
-6507
src/third_party/wtl/Include/atldlgs.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLDLGS_H__
9 #define __ATLDLGS_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atldlgs.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLWIN_H__
18 #error atldlgs.h requires atlwin.h to be included first
19 #endif
20
21 #include <commdlg.h>
22 #include <shlobj.h>
23
24 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
25 #include <shobjidl.h>
26 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
27
28
29 ///////////////////////////////////////////////////////////////////////////////
30 // Classes in this file:
31 //
32 // CFileDialogImpl<T>
33 // CFileDialog
34 // CFileDialogEx
35 // CMultiFileDialogImpl<T>
36 // CMultiFileDialog
37 // CShellFileDialogImpl<T>
38 // CShellFileOpenDialogImpl<T>
39 // CShellFileOpenDialog
40 // CShellFileSaveDialogImpl<T>
41 // CShellFileSaveDialog
42 // CFolderDialogImpl<T>
43 // CFolderDialog
44 // CFontDialogImpl<T>
45 // CFontDialog
46 // CRichEditFontDialogImpl<T>
47 // CRichEditFontDialog
48 // CColorDialogImpl<T>
49 // CColorDialog
50 // CPrintDialogImpl<T>
51 // CPrintDialog
52 // CPrintDialogExImpl<T>
53 // CPrintDialogEx
54 // CPageSetupDialogImpl<T>
55 // CPageSetupDialog
56 // CFindReplaceDialogImpl<T>
57 // CFindReplaceDialog
58 //
59 // CDialogBaseUnits
60 // CMemDlgTemplate
61 // CIndirectDialogImpl<T, TDlgTemplate, TBase>
62 //
63 // CPropertySheetWindow
64 // CPropertySheetImpl<T, TBase>
65 // CPropertySheet
66 // CPropertyPageWindow
67 // CPropertyPageImpl<T, TBase>
68 // CPropertyPage<t_wDlgTemplateID>
69 // CAxPropertyPageImpl<T, TBase>
70 // CAxPropertyPage<t_wDlgTemplateID>
71 //
72 // CWizard97SheetWindow
73 // CWizard97SheetImpl<T, TBase>
74 // CWizard97Sheet
75 // CWizard97PageWindow
76 // CWizard97PageImpl<T, TBase>
77 // CWizard97ExteriorPageImpl<T, TBase>
78 // CWizard97InteriorPageImpl<T, TBase>
79 //
80 // CAeroWizardFrameWindow
81 // CAeroWizardFrameImpl<T, TBase>
82 // CAeroWizardFrame
83 // CAeroWizardPageWindow
84 // CAeroWizardPageImpl<T, TBase>
85 // CAeroWizardPage<t_wDlgTemplateID>
86 // CAeroWizardAxPageImpl<T, TBase>
87 // CAeroWizardAxPage<t_wDlgTemplateID>
88 //
89 // CTaskDialogConfig
90 // CTaskDialogImpl<T>
91 // CTaskDialog
92 //
93 // Global functions:
94 // AtlTaskDialog()
95
96
97 namespace WTL
98 {
99
100 ///////////////////////////////////////////////////////////////////////////////
101 // CFileDialogImpl - used for File Open or File Save As
102
103 // compatibility with the old (vc6.0) headers
104 #if (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
105 #ifndef CDSIZEOF_STRUCT
106 #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
107 #endif
108 #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
109 #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
110 #ifdef UNICODE
111 #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400W
112 #else
113 #define OPENFILENAME_SIZE_VERSION_400 OPENFILENAME_SIZE_VERSION_400A
114 #endif // !UNICODE
115 #endif // (_WIN32_WINNT >= 0x0500) && !defined(OPENFILENAME_SIZE_VERSION_400)
116
117 #if !defined(_WIN32_WCE) && !defined(CDN_INCLUDEITEM)
118 #define CDN_INCLUDEITEM (CDN_FIRST - 0x0007)
119 #endif
120
121 template <class T>
122 class ATL_NO_VTABLE CFileDialogImpl : public ATL::CDialogImplBase
123 {
124 public:
125 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
126 OPENFILENAMEEX m_ofn;
127 #else
128 OPENFILENAME m_ofn;
129 #endif
130 BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save
131 TCHAR m_szFileTitle[_MAX_FNAME]; // contains file title after return
132 TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return
133
134 CFileDialogImpl(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
135 LPCTSTR lpszDefExt = NULL,
136 LPCTSTR lpszFileName = NULL,
137 DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
138 LPCTSTR lpszFilter = NULL,
139 HWND hWndParent = NULL)
140 {
141 memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
142 m_szFileName[0] = _T('\0');
143 m_szFileTitle[0] = _T('\0');
144
145 m_bOpenFileDialog = bOpenFileDialog;
146
147 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
148 m_ofn.lStructSize = bOpenFileDialog ? sizeof(m_ofn) : sizeof(OPENFILENAME);
149 #else
150 m_ofn.lStructSize = sizeof(m_ofn);
151 #endif
152
153 #if (_WIN32_WINNT >= 0x0500)
154 // adjust struct size if running on older version of Windows
155 if(AtlIsOldWindows())
156 {
157 ATLASSERT(sizeof(m_ofn) > OPENFILENAME_SIZE_VERSION_400); // must be
158 m_ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
159 }
160 #endif // (_WIN32_WINNT >= 0x0500)
161 m_ofn.lpstrFile = m_szFileName;
162 m_ofn.nMaxFile = _MAX_PATH;
163 m_ofn.lpstrDefExt = lpszDefExt;
164 m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
165 m_ofn.nMaxFileTitle = _MAX_FNAME;
166 #ifndef _WIN32_WCE
167 m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING;
168 #else // CE specific
169 m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK;
170 #endif // !_WIN32_WCE
171 m_ofn.lpstrFilter = lpszFilter;
172 m_ofn.hInstance = ModuleHelper::GetResourceInstance();
173 m_ofn.lpfnHook = (LPOFNHOOKPROC)T::StartDialogProc;
174 m_ofn.hwndOwner = hWndParent;
175
176 // setup initial file name
177 if(lpszFileName != NULL)
178 SecureHelper::strncpy_x(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);
179 }
180
181 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
182 {
183 ATLASSERT((m_ofn.Flags & OFN_ENABLEHOOK) != 0);
184 ATLASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
185
186 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
187
188 if(m_ofn.hwndOwner == NULL) // set only if not specified before
189 m_ofn.hwndOwner = hWndParent;
190
191 ATLASSERT(m_hWnd == NULL);
192
193 #if (_ATL_VER >= 0x0800)
194 // Allocate the thunk structure here, where we can fail gracefully.
195 BOOL bRetTh = m_thunk.Init(NULL, NULL);
196 if(bRetTh == FALSE)
197 {
198 ::SetLastError(ERROR_OUTOFMEMORY);
199 return -1;
200 }
201 #endif // (_ATL_VER >= 0x0800)
202
203 ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBase*)this);
204
205 BOOL bRet;
206 if(m_bOpenFileDialog)
207 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
208 bRet = ::GetOpenFileNameEx(&m_ofn);
209 else
210 bRet = ::GetSaveFileName((LPOPENFILENAME)&m_ofn);
211 #else
212 bRet = ::GetOpenFileName(&m_ofn);
213 else
214 bRet = ::GetSaveFileName(&m_ofn);
215 #endif
216
217 m_hWnd = NULL;
218
219 return bRet ? IDOK : IDCANCEL;
220 }
221
222 // Attributes
223 ATL::CWindow GetFileDialogWindow() const
224 {
225 ATLASSERT(::IsWindow(m_hWnd));
226 return ATL::CWindow(GetParent());
227 }
228
229 int GetFilePath(LPTSTR lpstrFilePath, int nLength) const
230 {
231 ATLASSERT(::IsWindow(m_hWnd));
232 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
233
234 return (int)GetFileDialogWindow().SendMessage(CDM_GETFILEPATH, nLength, (LPARAM)lpstrFilePath);
235 }
236
237 int GetFolderIDList(LPVOID lpBuff, int nLength) const
238 {
239 ATLASSERT(::IsWindow(m_hWnd));
240 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
241
242 return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERIDLIST, nLength, (LPARAM)lpBuff);
243 }
244
245 int GetFolderPath(LPTSTR lpstrFolderPath, int nLength) const
246 {
247 ATLASSERT(::IsWindow(m_hWnd));
248 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
249
250 return (int)GetFileDialogWindow().SendMessage(CDM_GETFOLDERPATH, nLength, (LPARAM)lpstrFolderPath);
251 }
252
253 int GetSpec(LPTSTR lpstrSpec, int nLength) const
254 {
255 ATLASSERT(::IsWindow(m_hWnd));
256 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
257
258 return (int)GetFileDialogWindow().SendMessage(CDM_GETSPEC, nLength, (LPARAM)lpstrSpec);
259 }
260
261 void SetControlText(int nCtrlID, LPCTSTR lpstrText)
262 {
263 ATLASSERT(::IsWindow(m_hWnd));
264 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
265
266 GetFileDialogWindow().SendMessage(CDM_SETCONTROLTEXT, nCtrlID, (LPARAM)lpstrText);
267 }
268
269 void SetDefExt(LPCTSTR lpstrExt)
270 {
271 ATLASSERT(::IsWindow(m_hWnd));
272 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
273
274 GetFileDialogWindow().SendMessage(CDM_SETDEFEXT, 0, (LPARAM)lpstrExt);
275 }
276
277 BOOL GetReadOnlyPref() const // return TRUE if readonly checked
278 {
279 return ((m_ofn.Flags & OFN_READONLY) != 0) ? TRUE : FALSE;
280 }
281
282 // Operations
283 void HideControl(int nCtrlID)
284 {
285 ATLASSERT(::IsWindow(m_hWnd));
286 ATLASSERT((m_ofn.Flags & OFN_EXPLORER) != 0);
287
288 GetFileDialogWindow().SendMessage(CDM_HIDECONTROL, nCtrlID);
289 }
290
291 // Special override for common dialogs
292 BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
293 {
294 ATLASSERT(::IsWindow(m_hWnd));
295 GetFileDialogWindow().SendMessage(WM_COMMAND, MAKEWPARAM(IDCANCEL, 0));
296 return TRUE;
297 }
298
299 // Message map and handlers
300 BEGIN_MSG_MAP(CFileDialogImpl)
301 NOTIFY_CODE_HANDLER(CDN_FILEOK, _OnFileOK)
302 NOTIFY_CODE_HANDLER(CDN_FOLDERCHANGE, _OnFolderChange)
303 NOTIFY_CODE_HANDLER(CDN_HELP, _OnHelp)
304 NOTIFY_CODE_HANDLER(CDN_INITDONE, _OnInitDone)
305 NOTIFY_CODE_HANDLER(CDN_SELCHANGE, _OnSelChange)
306 NOTIFY_CODE_HANDLER(CDN_SHAREVIOLATION, _OnShareViolation)
307 NOTIFY_CODE_HANDLER(CDN_TYPECHANGE, _OnTypeChange)
308 #ifndef _WIN32_WCE
309 NOTIFY_CODE_HANDLER(CDN_INCLUDEITEM, _OnIncludeItem)
310 #endif // !_WIN32_WCE
311 END_MSG_MAP()
312
313 LRESULT _OnFileOK(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
314 {
315 ATLASSERT(::IsWindow(m_hWnd));
316 T* pT = static_cast<T*>(this);
317 return !pT->OnFileOK((LPOFNOTIFY)pnmh);
318 }
319
320 LRESULT _OnFolderChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
321 {
322 ATLASSERT(::IsWindow(m_hWnd));
323 T* pT = static_cast<T*>(this);
324 pT->OnFolderChange((LPOFNOTIFY)pnmh);
325 return 0;
326 }
327
328 LRESULT _OnHelp(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
329 {
330 ATLASSERT(::IsWindow(m_hWnd));
331 T* pT = static_cast<T*>(this);
332 pT->OnHelp((LPOFNOTIFY)pnmh);
333 return 0;
334 }
335
336 LRESULT _OnInitDone(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
337 {
338 ATLASSERT(::IsWindow(m_hWnd));
339 T* pT = static_cast<T*>(this);
340 pT->OnInitDone((LPOFNOTIFY)pnmh);
341 return 0;
342 }
343
344 LRESULT _OnSelChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
345 {
346 ATLASSERT(::IsWindow(m_hWnd));
347 T* pT = static_cast<T*>(this);
348 pT->OnSelChange((LPOFNOTIFY)pnmh);
349 return 0;
350 }
351
352 LRESULT _OnShareViolation(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
353 {
354 ATLASSERT(::IsWindow(m_hWnd));
355 T* pT = static_cast<T*>(this);
356 return pT->OnShareViolation((LPOFNOTIFY)pnmh);
357 }
358
359 LRESULT _OnTypeChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
360 {
361 ATLASSERT(::IsWindow(m_hWnd));
362 T* pT = static_cast<T*>(this);
363 pT->OnTypeChange((LPOFNOTIFY)pnmh);
364 return 0;
365 }
366
367 #ifndef _WIN32_WCE
368 LRESULT _OnIncludeItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
369 {
370 ATLASSERT(::IsWindow(m_hWnd));
371 T* pT = static_cast<T*>(this);
372 return pT->OnIncludeItem((LPOFNOTIFYEX)pnmh);
373 }
374 #endif // !_WIN32_WCE
375
376 // Overrideables
377 BOOL OnFileOK(LPOFNOTIFY /*lpon*/)
378 {
379 return TRUE;
380 }
381
382 void OnFolderChange(LPOFNOTIFY /*lpon*/)
383 {
384 }
385
386 void OnHelp(LPOFNOTIFY /*lpon*/)
387 {
388 }
389
390 void OnInitDone(LPOFNOTIFY /*lpon*/)
391 {
392 }
393
394 void OnSelChange(LPOFNOTIFY /*lpon*/)
395 {
396 }
397
398 int OnShareViolation(LPOFNOTIFY /*lpon*/)
399 {
400 return 0;
401 }
402
403 void OnTypeChange(LPOFNOTIFY /*lpon*/)
404 {
405 }
406
407 #ifndef _WIN32_WCE
408 BOOL OnIncludeItem(LPOFNOTIFYEX /*lponex*/)
409 {
410 return TRUE; // include item
411 }
412 #endif // !_WIN32_WCE
413 };
414
415 class CFileDialog : public CFileDialogImpl<CFileDialog>
416 {
417 public:
418 CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
419 LPCTSTR lpszDefExt = NULL,
420 LPCTSTR lpszFileName = NULL,
421 DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
422 LPCTSTR lpszFilter = NULL,
423 HWND hWndParent = NULL)
424 : CFileDialogImpl<CFileDialog>(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
425 { }
426
427 // override base class map and references to handlers
428 DECLARE_EMPTY_MSG_MAP()
429 };
430
431 #if defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
432 class CFileDialogEx : public CFileDialogImpl<CFileDialogEx>
433 {
434 public:
435 CFileDialogEx( // Supports only FileOpen
436 LPCTSTR lpszDefExt = NULL,
437 LPCTSTR lpszFileName = NULL,
438 DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
439 OFN_EXFLAG ExFlags = OFN_EXFLAG_THUMBNAILVIEW,
440 OFN_SORTORDER dwSortOrder = OFN_SORTORDER_AUTO,
441 LPCTSTR lpszFilter = NULL,
442 HWND hWndParent = NULL)
443 : CFileDialogImpl<CFileDialogEx>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
444 {
445 m_ofn.ExFlags = ExFlags;
446 m_ofn.dwSortOrder = dwSortOrder;
447 }
448
449 // override base class map and references to handlers
450 DECLARE_EMPTY_MSG_MAP()
451 };
452 #endif // defined(__AYGSHELL_H__) && (_WIN32_WCE >= 0x0501)
453
454
455 ///////////////////////////////////////////////////////////////////////////////
456 // Multi File Dialog - Multi-select File Open dialog
457
458 #ifndef _WIN32_WCE
459
460 // The class dynamically resizes the buffer as the file selection changes
461 // (as described in Knowledge Base article 131462). It also expands selected
462 // shortcut files to take into account the full path of the target file.
463 // Note that this doesn't work on Win9x for the old style dialogs, as well as
464 // on NT for non-Unicode builds.
465
466 #ifndef _WTL_FIXED_OFN_BUFFER_LENGTH
467 #define _WTL_FIXED_OFN_BUFFER_LENGTH 0x10000
468 #endif
469
470 template <class T>
471 class ATL_NO_VTABLE CMultiFileDialogImpl : public CFileDialogImpl< T >
472 {
473 public:
474 mutable LPCTSTR m_pNextFile;
475 #ifndef _UNICODE
476 bool m_bIsNT;
477 #endif
478
479 CMultiFileDialogImpl(
480 LPCTSTR lpszDefExt = NULL,
481 LPCTSTR lpszFileName = NULL,
482 DWORD dwFlags = OFN_HIDEREADONLY,
483 LPCTSTR lpszFilter = NULL,
484 HWND hWndParent = NULL)
485 : CFileDialogImpl<T>(TRUE, lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent),
486 m_pNextFile(NULL)
487 {
488 m_ofn.Flags |= OFN_ALLOWMULTISELECT; // Force multiple selection mode
489
490 #ifndef _UNICODE
491 #ifdef _versionhelpers_H_INCLUDED_
492 OSVERSIONINFOEX ovi = { sizeof(OSVERSIONINFOEX) };
493 ovi.dwPlatformId = VER_PLATFORM_WIN32_NT;
494 DWORDLONG const dwlConditionMask = ::VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL);
495 m_bIsNT = (::VerifyVersionInfo(&ovi, VER_PLATFORMID, dwlConditionMask) != FALSE);
496 #else // !_versionhelpers_H_INCLUDED_
497 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
498 ::GetVersionEx(&ovi);
499 m_bIsNT = (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT);
500 #endif // _versionhelpers_H_INCLUDED_
501 if (m_bIsNT)
502 {
503 // On NT platforms, GetOpenFileNameA thunks to GetOpenFileNameW and there
504 // is absolutely nothing we can do except to start off with a large buffer.
505 ATLVERIFY(ResizeFilenameBuffer(_WTL_FIXED_OFN_BUFFER_LENGTH));
506 }
507 #endif
508 }
509
510 ~CMultiFileDialogImpl()
511 {
512 if (m_ofn.lpstrFile != m_szFileName) // Free the buffer if we allocated it
513 delete[] m_ofn.lpstrFile;
514 }
515
516 // Operations
517 // Get the directory that the files were chosen from.
518 // The function returns the number of characters copied, not including the terminating zero.
519 // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
520 // If the function fails, the return value is zero.
521 int GetDirectory(LPTSTR pBuffer, int nBufLen) const
522 {
523 if (m_ofn.lpstrFile == NULL)
524 return 0;
525
526 LPCTSTR pStr = m_ofn.lpstrFile;
527 int nLength = lstrlen(pStr);
528 if (pStr[nLength + 1] == 0)
529 {
530 // The OFN buffer contains a single item so extract its path.
531 LPCTSTR pSep = MinCrtHelper::_strrchr(pStr, _T('\\'));
532 if (pSep != NULL)
533 nLength = (int)(DWORD_PTR)(pSep - pStr);
534 }
535
536 int nRet = 0;
537 if (pBuffer == NULL) // If the buffer is NULL, return the required length
538 {
539 nRet = nLength + 1;
540 }
541 else if (nBufLen > nLength)
542 {
543 SecureHelper::strncpy_x(pBuffer, nBufLen, pStr, nLength);
544 nRet = nLength;
545 }
546
547 return nRet;
548 }
549
550 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
551 bool GetDirectory(_CSTRING_NS::CString& strDir) const
552 {
553 bool bRet = false;
554
555 int nLength = GetDirectory(NULL, 0);
556 if (nLength > 0)
557 {
558 bRet = (GetDirectory(strDir.GetBuffer(nLength), nLength) > 0);
559 strDir.ReleaseBuffer(nLength - 1);
560 }
561
562 return bRet;
563 }
564 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
565
566 // Get the first filename as a pointer into the buffer.
567 LPCTSTR GetFirstFileName() const
568 {
569 if (m_ofn.lpstrFile == NULL)
570 return NULL;
571
572 m_pNextFile = NULL; // Reset internal buffer pointer
573
574 LPCTSTR pStr = m_ofn.lpstrFile;
575 int nLength = lstrlen(pStr);
576 if (pStr[nLength + 1] != 0)
577 {
578 // Multiple items were selected. The first string is the directory,
579 // so skip forwards to the second string.
580 pStr += nLength + 1;
581
582 // Set up m_pNext so it points to the second item (or null).
583 m_pNextFile = pStr;
584 GetNextFileName();
585 }
586 else
587 {
588 // A single item was selected. Skip forward past the path.
589 LPCTSTR pSep = MinCrtHelper::_strrchr(pStr, _T('\\'));
590 if (pSep != NULL)
591 pStr = pSep + 1;
592 }
593
594 return pStr;
595 }
596
597 // Get the next filename as a pointer into the buffer.
598 LPCTSTR GetNextFileName() const
599 {
600 if (m_pNextFile == NULL)
601 return NULL;
602
603 LPCTSTR pStr = m_pNextFile;
604 // Set "m_pNextFile" to point to the next file name, or null if we
605 // have reached the last file in the list.
606 int nLength = lstrlen(pStr);
607 m_pNextFile = (pStr[nLength + 1] != 0) ? &pStr[nLength + 1] : NULL;
608
609 return pStr;
610 }
611
612 // Get the first filename as a full path.
613 // The function returns the number of characters copied, not including the terminating zero.
614 // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
615 // If the function fails, the return value is zero.
616 int GetFirstPathName(LPTSTR pBuffer, int nBufLen) const
617 {
618 LPCTSTR pStr = GetFirstFileName();
619 int nLengthDir = GetDirectory(NULL, 0);
620 if((pStr == NULL) || (nLengthDir == 0))
621 return 0;
622
623 // Figure out the required length.
624 int nLengthTotal = nLengthDir + lstrlen(pStr);
625
626 int nRet = 0;
627 if(pBuffer == NULL) // If the buffer is NULL, return the required length
628 {
629 nRet = nLengthTotal + 1;
630 }
631 else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
632 {
633 GetDirectory(pBuffer, nBufLen);
634 SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
635 SecureHelper::strcat_x(pBuffer, nBufLen, pStr);
636 nRet = nLengthTotal;
637 }
638
639 return nRet;
640 }
641
642 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
643 bool GetFirstPathName(_CSTRING_NS::CString& strPath) const
644 {
645 bool bRet = false;
646
647 int nLength = GetFirstPathName(NULL, 0);
648 if (nLength > 0)
649 {
650 bRet = (GetFirstPathName(strPath.GetBuffer(nLength), nLength) > 0);
651 strPath.ReleaseBuffer(nLength - 1);
652 }
653
654 return bRet;
655 }
656 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
657
658 // Get the next filename as a full path.
659 // The function returns the number of characters copied, not including the terminating zero.
660 // If the buffer is NULL, the function returns the required size, in characters, including the terminating zero.
661 // If the function fails, the return value is zero.
662 // The internal position marker is moved forward only if the function succeeds and the buffer was large enough.
663 int GetNextPathName(LPTSTR pBuffer, int nBufLen) const
664 {
665 if (m_pNextFile == NULL)
666 return 0;
667
668 int nRet = 0;
669 LPCTSTR pStr = m_pNextFile;
670 // Does the filename contain a backslash?
671 if (MinCrtHelper::_strrchr(pStr, _T('\\')) != NULL)
672 {
673 // Yes, so we'll assume it's a full path.
674 int nLength = lstrlen(pStr);
675
676 if (pBuffer == NULL) // If the buffer is NULL, return the required length
677 {
678 nRet = nLength + 1;
679 }
680 else if (nBufLen > nLength) // The buffer is big enough, so go ahead and copy the filename
681 {
682 SecureHelper::strcpy_x(pBuffer, nBufLen, GetNextFileName());
683 nRet = nBufLen;
684 }
685 }
686 else
687 {
688 // The filename is relative, so construct the full path.
689 int nLengthDir = GetDirectory(NULL, 0);
690 if (nLengthDir > 0)
691 {
692 // Calculate the required space.
693 int nLengthTotal = nLengthDir + lstrlen(pStr);
694
695 if(pBuffer == NULL) // If the buffer is NULL, return the required length
696 {
697 nRet = nLengthTotal + 1;
698 }
699 else if (nBufLen > nLengthTotal) // If the buffer is big enough, go ahead and construct the path
700 {
701 GetDirectory(pBuffer, nBufLen);
702 SecureHelper::strcat_x(pBuffer, nBufLen, _T("\\"));
703 SecureHelper::strcat_x(pBuffer, nBufLen, GetNextFileName());
704 nRet = nLengthTotal;
705 }
706 }
707 }
708
709 return nRet;
710 }
711
712 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
713 bool GetNextPathName(_CSTRING_NS::CString& strPath) const
714 {
715 bool bRet = false;
716
717 int nLength = GetNextPathName(NULL, 0);
718 if (nLength > 0)
719 {
720 bRet = (GetNextPathName(strPath.GetBuffer(nLength), nLength) > 0);
721 strPath.ReleaseBuffer(nLength - 1);
722 }
723
724 return bRet;
725 }
726 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
727
728 // Implementation
729 bool ResizeFilenameBuffer(DWORD dwLength)
730 {
731 if (dwLength > m_ofn.nMaxFile)
732 {
733 // Free the old buffer.
734 if (m_ofn.lpstrFile != m_szFileName)
735 {
736 delete[] m_ofn.lpstrFile;
737 m_ofn.lpstrFile = NULL;
738 m_ofn.nMaxFile = 0;
739 }
740
741 // Allocate the new buffer.
742 LPTSTR lpstrBuff = NULL;
743 ATLTRY(lpstrBuff = new TCHAR[dwLength]);
744 if (lpstrBuff != NULL)
745 {
746 m_ofn.lpstrFile = lpstrBuff;
747 m_ofn.lpstrFile[0] = 0;
748 m_ofn.nMaxFile = dwLength;
749 }
750 }
751
752 return (m_ofn.lpstrFile != NULL);
753 }
754
755 void OnSelChange(LPOFNOTIFY /*lpon*/)
756 {
757 #ifndef _UNICODE
758 // There is no point resizing the buffer in ANSI builds running on NT.
759 if (m_bIsNT)
760 return;
761 #endif
762
763 // Get the buffer length required to hold the spec.
764 int nLength = GetSpec(NULL, 0);
765 if (nLength <= 1)
766 return; // no files are selected, presumably
767
768 // Add room for the directory, and an extra terminating zero.
769 nLength += GetFolderPath(NULL, 0) + 1;
770
771 if (!ResizeFilenameBuffer(nLength))
772 {
773 ATLASSERT(FALSE);
774 return;
775 }
776
777 // If we are not following links then our work is done.
778 if ((m_ofn.Flags & OFN_NODEREFERENCELINKS) != 0)
779 return;
780
781 // Get the file spec, which is the text in the edit control.
782 if (GetSpec(m_ofn.lpstrFile, m_ofn.nMaxFile) <= 0)
783 return;
784
785 // Get the ID-list of the current folder.
786 int nBytes = GetFolderIDList(NULL, 0);
787 #ifdef STRICT_TYPED_ITEMIDS
788 CTempBuffer<ITEMIDLIST_RELATIVE> idlist;
789 #else
790 CTempBuffer<ITEMIDLIST> idlist;
791 #endif
792 idlist.AllocateBytes(nBytes);
793 if ((nBytes <= 0) || (GetFolderIDList(idlist, nBytes) <= 0))
794 return;
795
796 // First bind to the desktop folder, then to the current folder.
797 ATL::CComPtr<IShellFolder> pDesktop, pFolder;
798 if (FAILED(::SHGetDesktopFolder(&pDesktop)))
799 return;
800 if (FAILED(pDesktop->BindToObject(idlist, NULL, IID_IShellFolder, (void**)&pFolder)))
801 return;
802
803 // Work through the file spec, looking for quoted filenames. If we find a shortcut file, then
804 // we need to add enough extra buffer space to hold its target path.
805 DWORD nExtraChars = 0;
806 bool bInsideQuotes = false;
807 LPCTSTR pAnchor = m_ofn.lpstrFile;
808 LPCTSTR pChar = m_ofn.lpstrFile;
809 for ( ; *pChar; ++pChar)
810 {
811 // Look for quotation marks.
812 if (*pChar == _T('\"'))
813 {
814 // We are either entering or leaving a passage of quoted text.
815 bInsideQuotes = !bInsideQuotes;
816
817 // Is it an opening or closing quote?
818 if (bInsideQuotes)
819 {
820 // We found an opening quote, so set "pAnchor" to the following character.
821 pAnchor = pChar + 1;
822 }
823 else // closing quote
824 {
825 // Each quoted entity should be shorter than MAX_PATH.
826 if (pChar - pAnchor >= MAX_PATH)
827 return;
828
829 // Get the ID-list and attributes of the file.
830 USES_CONVERSION;
831 int nFileNameLength = (int)(DWORD_PTR)(pChar - pAnchor);
832 TCHAR szFileName[MAX_PATH] = { 0 };
833 SecureHelper::strncpy_x(szFileName, MAX_PATH, pAnchor, nFileNameLength);
834 #ifdef STRICT_TYPED_ITEMIDS
835 PIDLIST_RELATIVE pidl = NULL;
836 #else
837 LPITEMIDLIST pidl = NULL;
838 #endif
839 DWORD dwAttrib = SFGAO_LINK;
840 if (SUCCEEDED(pFolder->ParseDisplayName(NULL, NULL, T2W(szFileName), NULL, &pidl, &dwAttrib)))
841 {
842 // Is it a shortcut file?
843 if (dwAttrib & SFGAO_LINK)
844 {
845 // Bind to its IShellLink interface.
846 ATL::CComPtr<IShellLink> pLink;
847 if (SUCCEEDED(pFolder->BindToObject(pidl, NULL, IID_IShellLink, (void**)&pLink)))
848 {
849 // Get the shortcut's target path.
850 TCHAR szPath[MAX_PATH] = { 0 };
851 if (SUCCEEDED(pLink->GetPath(szPath, MAX_PATH, NULL, 0)))
852 {
853 // If the target path is longer than the shortcut name, then add on the number
854 // of extra characters that are required.
855 int nNewLength = lstrlen(szPath);
856 if (nNewLength > nFileNameLength)
857 nExtraChars += nNewLength - nFileNameLength;
858 }
859 }
860 }
861
862 // Free the ID-list returned by ParseDisplayName.
863 ::CoTaskMemFree(pidl);
864 }
865 }
866 }
867 }
868
869 // If we need more space for shortcut targets, then reallocate.
870 if (nExtraChars > 0)
871 ATLVERIFY(ResizeFilenameBuffer(m_ofn.nMaxFile + nExtraChars));
872 }
873 };
874
875 class CMultiFileDialog : public CMultiFileDialogImpl<CMultiFileDialog>
876 {
877 public:
878 CMultiFileDialog(
879 LPCTSTR lpszDefExt = NULL,
880 LPCTSTR lpszFileName = NULL,
881 DWORD dwFlags = OFN_HIDEREADONLY,
882 LPCTSTR lpszFilter = NULL,
883 HWND hWndParent = NULL)
884 : CMultiFileDialogImpl<CMultiFileDialog>(lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
885 { }
886
887 BEGIN_MSG_MAP(CMultiFileDialog)
888 CHAIN_MSG_MAP(CMultiFileDialogImpl<CMultiFileDialog>)
889 END_MSG_MAP()
890 };
891
892 #endif // !_WIN32_WCE
893
894
895 ///////////////////////////////////////////////////////////////////////////////
896 // Shell File Dialog - new Shell File Open and Save dialogs in Vista
897
898 // Note: Use GetPtr() to access dialog interface methods.
899 // Example:
900 // CShellFileOpenDialog dlg;
901 // dlg.GetPtr()->SetTitle(L"MyFileOpenDialog");
902
903 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
904
905 ///////////////////////////////////////////////////////////////////////////////
906 // CShellFileDialogImpl - base class for CShellFileOpenDialogImpl and CShellFileSaveDialogImpl
907
908 template <class T>
909 class ATL_NO_VTABLE CShellFileDialogImpl : public IFileDialogEvents
910 {
911 public:
912 // Operations
913 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
914 {
915 INT_PTR nRet = -1;
916
917 T* pT = static_cast<T*>(this);
918 if(pT->m_spFileDlg == NULL)
919 {
920 ATLASSERT(FALSE);
921 return nRet;
922 }
923
924 DWORD dwCookie = 0;
925 pT->_Advise(dwCookie);
926
927 HRESULT hRet = pT->m_spFileDlg->Show(hWndParent);
928 if(SUCCEEDED(hRet))
929 nRet = IDOK;
930 else if(hRet == HRESULT_FROM_WIN32(ERROR_CANCELLED))
931 nRet = IDCANCEL;
932 else
933 ATLASSERT(FALSE); // error
934
935 pT->_Unadvise(dwCookie);
936
937 return nRet;
938 }
939
940 bool IsNull() const
941 {
942 const T* pT = static_cast<const T*>(this);
943 return (pT->m_spFileDlg == NULL);
944 }
945
946 // Operations - get file path after dialog returns
947 HRESULT GetFilePath(LPWSTR lpstrFilePath, int cchLength)
948 {
949 T* pT = static_cast<T*>(this);
950 ATLASSERT(pT->m_spFileDlg != NULL);
951
952 ATL::CComPtr<IShellItem> spItem;
953 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
954
955 if(SUCCEEDED(hRet))
956 hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, lpstrFilePath, cchLength);
957
958 return hRet;
959 }
960
961 HRESULT GetFileTitle(LPWSTR lpstrFileTitle, int cchLength)
962 {
963 T* pT = static_cast<T*>(this);
964 ATLASSERT(pT->m_spFileDlg != NULL);
965
966 ATL::CComPtr<IShellItem> spItem;
967 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
968
969 if(SUCCEEDED(hRet))
970 hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, lpstrFileTitle, cchLength);
971
972 return hRet;
973 }
974
975 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
976 HRESULT GetFilePath(_CSTRING_NS::CString& strFilePath)
977 {
978 T* pT = static_cast<T*>(this);
979 ATLASSERT(pT->m_spFileDlg != NULL);
980
981 ATL::CComPtr<IShellItem> spItem;
982 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
983
984 if(SUCCEEDED(hRet))
985 hRet = GetFileNameFromShellItem(spItem, SIGDN_FILESYSPATH, strFilePath);
986
987 return hRet;
988 }
989
990 HRESULT GetFileTitle(_CSTRING_NS::CString& strFileTitle)
991 {
992 T* pT = static_cast<T*>(this);
993 ATLASSERT(pT->m_spFileDlg != NULL);
994
995 ATL::CComPtr<IShellItem> spItem;
996 HRESULT hRet = pT->m_spFileDlg->GetResult(&spItem);
997
998 if(SUCCEEDED(hRet))
999 hRet = GetFileNameFromShellItem(spItem, SIGDN_NORMALDISPLAY, strFileTitle);
1000
1001 return hRet;
1002 }
1003 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1004
1005 // Helpers for IShellItem
1006 static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, LPWSTR lpstr, int cchLength)
1007 {
1008 ATLASSERT(pShellItem != NULL);
1009
1010 LPWSTR lpstrName = NULL;
1011 HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
1012
1013 if(SUCCEEDED(hRet))
1014 {
1015 if(lstrlenW(lpstrName) < cchLength)
1016 {
1017 SecureHelper::strcpyW_x(lpstr, cchLength, lpstrName);
1018 }
1019 else
1020 {
1021 ATLASSERT(FALSE);
1022 hRet = DISP_E_BUFFERTOOSMALL;
1023 }
1024
1025 ::CoTaskMemFree(lpstrName);
1026 }
1027
1028 return hRet;
1029 }
1030
1031 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1032 static HRESULT GetFileNameFromShellItem(IShellItem* pShellItem, SIGDN type, _CSTRING_NS::CString& str)
1033 {
1034 ATLASSERT(pShellItem != NULL);
1035
1036 LPWSTR lpstrName = NULL;
1037 HRESULT hRet = pShellItem->GetDisplayName(type, &lpstrName);
1038
1039 if(SUCCEEDED(hRet))
1040 {
1041 str = lpstrName;
1042 ::CoTaskMemFree(lpstrName);
1043 }
1044
1045 return hRet;
1046 }
1047 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
1048
1049 // Implementation
1050 void _Advise(DWORD& dwCookie)
1051 {
1052 T* pT = static_cast<T*>(this);
1053 ATLASSERT(pT->m_spFileDlg != NULL);
1054 HRESULT hRet = pT->m_spFileDlg->Advise((IFileDialogEvents*)this, &dwCookie);
1055 ATLVERIFY(SUCCEEDED(hRet));
1056 }
1057
1058 void _Unadvise(DWORD dwCookie)
1059 {
1060 T* pT = static_cast<T*>(this);
1061 ATLASSERT(pT->m_spFileDlg != NULL);
1062 HRESULT hRet = pT->m_spFileDlg->Unadvise(dwCookie);
1063 ATLVERIFY(SUCCEEDED(hRet));
1064 }
1065
1066 void _Init(LPCWSTR lpszFileName, DWORD dwOptions, LPCWSTR lpszDefExt, const COMDLG_FILTERSPEC* arrFilterSpec, UINT uFilterSpecCount)
1067 {
1068 T* pT = static_cast<T*>(this);
1069 ATLASSERT(pT->m_spFileDlg != NULL);
1070
1071 HRESULT hRet = E_FAIL;
1072
1073 if(lpszFileName != NULL)
1074 {
1075 hRet = pT->m_spFileDlg->SetFileName(lpszFileName);
1076 ATLASSERT(SUCCEEDED(hRet));
1077 }
1078
1079 hRet = pT->m_spFileDlg->SetOptions(dwOptions);
1080 ATLASSERT(SUCCEEDED(hRet));
1081
1082 if(lpszDefExt != NULL)
1083 {
1084 hRet = pT->m_spFileDlg->SetDefaultExtension(lpszDefExt);
1085 ATLASSERT(SUCCEEDED(hRet));
1086 }
1087
1088 if(arrFilterSpec != NULL && uFilterSpecCount != 0U)
1089 {
1090 hRet = pT->m_spFileDlg->SetFileTypes(uFilterSpecCount, arrFilterSpec);
1091 ATLASSERT(SUCCEEDED(hRet));
1092 }
1093 }
1094
1095 // Implementation - IUnknown interface
1096 STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
1097 {
1098 if(ppvObject == NULL)
1099 return E_POINTER;
1100
1101 T* pT = static_cast<T*>(this);
1102 if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IFileDialogEvents))
1103 {
1104 *ppvObject = (IFileDialogEvents*)pT;
1105 // AddRef() not needed
1106 return S_OK;
1107 }
1108
1109 return E_NOINTERFACE;
1110 }
1111
1112 virtual ULONG STDMETHODCALLTYPE AddRef()
1113 {
1114 return 1;
1115 }
1116
1117 virtual ULONG STDMETHODCALLTYPE Release()
1118 {
1119 return 1;
1120 }
1121
1122 // Implementation - IFileDialogEvents interface
1123 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFileOk(IFileDialog* pfd)
1124 {
1125 T* pT = static_cast<T*>(this);
1126 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1127 pfd; // avoid level 4 warning
1128 return pT->OnFileOk();
1129 }
1130
1131 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChanging(IFileDialog* pfd, IShellItem* psiFolder)
1132 {
1133 T* pT = static_cast<T*>(this);
1134 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1135 pfd; // avoid level 4 warning
1136 return pT->OnFolderChanging(psiFolder);
1137 }
1138
1139 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnFolderChange(IFileDialog* pfd)
1140 {
1141 T* pT = static_cast<T*>(this);
1142 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1143 pfd; // avoid level 4 warning
1144 return pT->OnFolderChange();
1145 }
1146
1147 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnSelectionChange(IFileDialog* pfd)
1148 {
1149 T* pT = static_cast<T*>(this);
1150 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1151 pfd; // avoid level 4 warning
1152 return pT->OnSelectionChange();
1153 }
1154
1155 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnShareViolation(IFileDialog* pfd, IShellItem* psi, FDE_SHAREVIOLATION_RESPONSE* pResponse)
1156 {
1157 T* pT = static_cast<T*>(this);
1158 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1159 pfd; // avoid level 4 warning
1160 return pT->OnShareViolation(psi, pResponse);
1161 }
1162
1163 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnTypeChange(IFileDialog* pfd)
1164 {
1165 T* pT = static_cast<T*>(this);
1166 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1167 pfd; // avoid level 4 warning
1168 return pT->OnTypeChange();
1169 }
1170
1171 virtual HRESULT STDMETHODCALLTYPE IFileDialogEvents::OnOverwrite(IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse)
1172 {
1173 T* pT = static_cast<T*>(this);
1174 ATLASSERT(pT->m_spFileDlg.IsEqualObject(pfd));
1175 pfd; // avoid level 4 warning
1176 return pT->OnOverwrite(psi, pResponse);
1177 }
1178
1179 // Overrideables - Event handlers
1180 HRESULT OnFileOk()
1181 {
1182 return E_NOTIMPL;
1183 }
1184
1185 HRESULT OnFolderChanging(IShellItem* /*psiFolder*/)
1186 {
1187 return E_NOTIMPL;
1188 }
1189
1190 HRESULT OnFolderChange()
1191 {
1192 return E_NOTIMPL;
1193 }
1194
1195 HRESULT OnSelectionChange()
1196 {
1197 return E_NOTIMPL;
1198 }
1199
1200 HRESULT OnShareViolation(IShellItem* /*psi*/, FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/)
1201 {
1202 return E_NOTIMPL;
1203 }
1204
1205 HRESULT OnTypeChange()
1206 {
1207 return E_NOTIMPL;
1208 }
1209
1210 HRESULT OnOverwrite(IShellItem* /*psi*/, FDE_OVERWRITE_RESPONSE* /*pResponse*/)
1211 {
1212 return E_NOTIMPL;
1213 }
1214 };
1215
1216
1217 ///////////////////////////////////////////////////////////////////////////////
1218 // CShellFileOpenDialogImpl - implements new Shell File Open dialog
1219
1220 template <class T>
1221 class ATL_NO_VTABLE CShellFileOpenDialogImpl : public CShellFileDialogImpl< T >
1222 {
1223 public:
1224 ATL::CComPtr<IFileOpenDialog> m_spFileDlg;
1225
1226 CShellFileOpenDialogImpl(LPCWSTR lpszFileName = NULL,
1227 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
1228 LPCWSTR lpszDefExt = NULL,
1229 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1230 UINT uFilterSpecCount = 0U)
1231 {
1232 HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileOpenDialog);
1233
1234 if(SUCCEEDED(hRet))
1235 _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
1236 }
1237
1238 IFileOpenDialog* GetPtr()
1239 {
1240 return m_spFileDlg;
1241 }
1242 };
1243
1244
1245 ///////////////////////////////////////////////////////////////////////////////
1246 // CShellFileOpenDialog - new Shell File Open dialog without events
1247
1248 class CShellFileOpenDialog : public CShellFileOpenDialogImpl<CShellFileOpenDialog>
1249 {
1250 public:
1251 CShellFileOpenDialog(LPCWSTR lpszFileName = NULL,
1252 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST,
1253 LPCWSTR lpszDefExt = NULL,
1254 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1255 UINT uFilterSpecCount = 0U) : CShellFileOpenDialogImpl<CShellFileOpenDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
1256 { }
1257
1258 // Implementation (remove _Advise/_Unadvise code using template magic)
1259 void _Advise(DWORD& /*dwCookie*/)
1260 { }
1261
1262 void _Unadvise(DWORD /*dwCookie*/)
1263 { }
1264 };
1265
1266
1267 ///////////////////////////////////////////////////////////////////////////////
1268 // CShellFileSaveDialogImpl - implements new Shell File Save dialog
1269
1270 template <class T>
1271 class ATL_NO_VTABLE CShellFileSaveDialogImpl : public CShellFileDialogImpl< T >
1272 {
1273 public:
1274 ATL::CComPtr<IFileSaveDialog> m_spFileDlg;
1275
1276 CShellFileSaveDialogImpl(LPCWSTR lpszFileName = NULL,
1277 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
1278 LPCWSTR lpszDefExt = NULL,
1279 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1280 UINT uFilterSpecCount = 0U)
1281 {
1282 HRESULT hRet = m_spFileDlg.CoCreateInstance(CLSID_FileSaveDialog);
1283
1284 if(SUCCEEDED(hRet))
1285 _Init(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount);
1286 }
1287
1288 IFileSaveDialog* GetPtr()
1289 {
1290 return m_spFileDlg;
1291 }
1292 };
1293
1294
1295 ///////////////////////////////////////////////////////////////////////////////
1296 // CShellFileSaveDialog - new Shell File Save dialog without events
1297
1298 class CShellFileSaveDialog : public CShellFileSaveDialogImpl<CShellFileSaveDialog>
1299 {
1300 public:
1301 CShellFileSaveDialog(LPCWSTR lpszFileName = NULL,
1302 DWORD dwOptions = FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
1303 LPCWSTR lpszDefExt = NULL,
1304 const COMDLG_FILTERSPEC* arrFilterSpec = NULL,
1305 UINT uFilterSpecCount = 0U) : CShellFileSaveDialogImpl<CShellFileSaveDialog>(lpszFileName, dwOptions, lpszDefExt, arrFilterSpec, uFilterSpecCount)
1306 { }
1307
1308 // Implementation (remove _Advise/_Unadvise code using template magic)
1309 void _Advise(DWORD& /*dwCookie*/)
1310 { }
1311
1312 void _Unadvise(DWORD /*dwCookie*/)
1313 { }
1314 };
1315
1316 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
1317
1318
1319 ///////////////////////////////////////////////////////////////////////////////
1320 // CFolderDialogImpl - used for browsing for a folder
1321
1322 #ifndef _WIN32_WCE
1323
1324 template <class T>
1325 class ATL_NO_VTABLE CFolderDialogImpl
1326 {
1327 public:
1328 BROWSEINFO m_bi;
1329 LPCTSTR m_lpstrInitialFolder;
1330 LPCITEMIDLIST m_pidlInitialSelection;
1331 bool m_bExpandInitialSelection;
1332 TCHAR m_szFolderDisplayName[MAX_PATH];
1333 TCHAR m_szFolderPath[MAX_PATH];
1334 #ifdef STRICT_TYPED_ITEMIDS
1335 PIDLIST_ABSOLUTE m_pidlSelected;
1336 #else
1337 LPITEMIDLIST m_pidlSelected;
1338 #endif
1339 HWND m_hWnd; // used only in the callback function
1340
1341 // Constructor
1342 CFolderDialogImpl(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS) :
1343 m_lpstrInitialFolder(NULL), m_pidlInitialSelection(NULL), m_bExpandInitialSelection(false), m_pidlSelected(NULL), m_hWnd(NULL)
1344 {
1345 memset(&m_bi, 0, sizeof(m_bi)); // initialize structure to 0/NULL
1346
1347 m_bi.hwndOwner = hWndParent;
1348 m_bi.pidlRoot = NULL;
1349 m_bi.pszDisplayName = m_szFolderDisplayName;
1350 m_bi.lpszTitle = lpstrTitle;
1351 m_bi.ulFlags = uFlags;
1352 m_bi.lpfn = BrowseCallbackProc;
1353 m_bi.lParam = (LPARAM)static_cast<T*>(this);
1354
1355 m_szFolderPath[0] = 0;
1356 m_szFolderDisplayName[0] = 0;
1357 }
1358
1359 ~CFolderDialogImpl()
1360 {
1361 ::CoTaskMemFree(m_pidlSelected);
1362 }
1363
1364 // Operations
1365 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1366 {
1367 if(m_bi.hwndOwner == NULL) // set only if not specified before
1368 m_bi.hwndOwner = hWndParent;
1369
1370 // Clear out any previous results
1371 m_szFolderPath[0] = 0;
1372 m_szFolderDisplayName[0] = 0;
1373 ::CoTaskMemFree(m_pidlSelected);
1374
1375 INT_PTR nRet = IDCANCEL;
1376 m_pidlSelected = ::SHBrowseForFolder(&m_bi);
1377
1378 if(m_pidlSelected != NULL)
1379 {
1380 nRet = IDOK;
1381
1382 // If BIF_RETURNONLYFSDIRS is set, we try to get the filesystem path.
1383 // Otherwise, the caller must handle the ID-list directly.
1384 if((m_bi.ulFlags & BIF_RETURNONLYFSDIRS) != 0)
1385 {
1386 if(::SHGetPathFromIDList(m_pidlSelected, m_szFolderPath) == FALSE)
1387 nRet = IDCANCEL;
1388 }
1389 }
1390
1391 return nRet;
1392 }
1393
1394 // Methods to call before DoModal
1395 void SetInitialFolder(LPCTSTR lpstrInitialFolder, bool bExpand = true)
1396 {
1397 // lpstrInitialFolder may be a file if BIF_BROWSEINCLUDEFILES is specified
1398 m_lpstrInitialFolder = lpstrInitialFolder;
1399 m_bExpandInitialSelection = bExpand;
1400 }
1401
1402 void SetInitialSelection(LPCITEMIDLIST pidl, bool bExpand = true)
1403 {
1404 m_pidlInitialSelection = pidl;
1405 m_bExpandInitialSelection = bExpand;
1406 }
1407
1408 #ifdef STRICT_TYPED_ITEMIDS
1409 void SetRootFolder(PCIDLIST_ABSOLUTE pidl)
1410 #else
1411 void SetRootFolder(LPCITEMIDLIST pidl)
1412 #endif
1413 {
1414 m_bi.pidlRoot = pidl;
1415 }
1416
1417 // Methods to call after DoModal
1418 LPITEMIDLIST GetSelectedItem(bool bDetach = false)
1419 {
1420 LPITEMIDLIST pidl = m_pidlSelected;
1421 if(bDetach)
1422 m_pidlSelected = NULL;
1423
1424 return pidl;
1425 }
1426
1427 LPCTSTR GetFolderPath() const
1428 {
1429 return m_szFolderPath;
1430 }
1431
1432 LPCTSTR GetFolderDisplayName() const
1433 {
1434 return m_szFolderDisplayName;
1435 }
1436
1437 int GetFolderImageIndex() const
1438 {
1439 return m_bi.iImage;
1440 }
1441
1442 // Callback function and overrideables
1443 static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
1444 {
1445 #ifndef BFFM_VALIDATEFAILED
1446 #ifdef UNICODE
1447 const int BFFM_VALIDATEFAILED = 4;
1448 #else
1449 const int BFFM_VALIDATEFAILED = 3;
1450 #endif
1451 #endif // !BFFM_VALIDATEFAILED
1452 #ifndef BFFM_IUNKNOWN
1453 const int BFFM_IUNKNOWN = 5;
1454 #endif // !BFFM_IUNKNOWN
1455 #ifndef BIF_NEWDIALOGSTYLE
1456 const UINT BIF_NEWDIALOGSTYLE = 0x0040;
1457 #endif // !BIF_NEWDIALOGSTYLE
1458
1459 int nRet = 0;
1460 T* pT = (T*)lpData;
1461 bool bClear = false;
1462 if(pT->m_hWnd == NULL)
1463 {
1464 pT->m_hWnd = hWnd;
1465 bClear = true;
1466 }
1467 else
1468 {
1469 ATLASSERT(pT->m_hWnd == hWnd);
1470 }
1471
1472 switch(uMsg)
1473 {
1474 case BFFM_INITIALIZED:
1475 // Set initial selection
1476 // Note that m_pidlInitialSelection, if set, takes precedence over m_lpstrInitialFolder
1477 if(pT->m_pidlInitialSelection != NULL)
1478 pT->SetSelection(pT->m_pidlInitialSelection);
1479 else if(pT->m_lpstrInitialFolder != NULL)
1480 pT->SetSelection(pT->m_lpstrInitialFolder);
1481
1482 // Expand initial selection if appropriate
1483 if(pT->m_bExpandInitialSelection && ((pT->m_bi.ulFlags & BIF_NEWDIALOGSTYLE) != 0))
1484 {
1485 if(pT->m_pidlInitialSelection != NULL)
1486 pT->SetExpanded(pT->m_pidlInitialSelection);
1487 else if(pT->m_lpstrInitialFolder != NULL)
1488 pT->SetExpanded(pT->m_lpstrInitialFolder);
1489 }
1490 pT->OnInitialized();
1491 break;
1492 case BFFM_SELCHANGED:
1493 pT->OnSelChanged((LPITEMIDLIST)lParam);
1494 break;
1495 case BFFM_VALIDATEFAILED:
1496 nRet = pT->OnValidateFailed((LPCTSTR)lParam);
1497 break;
1498 case BFFM_IUNKNOWN:
1499 pT->OnIUnknown((IUnknown*)lParam);
1500 break;
1501 default:
1502 ATLTRACE2(atlTraceUI, 0, _T("Unknown message received in CFolderDialogImpl::BrowseCallbackProc\n"));
1503 break;
1504 }
1505
1506 if(bClear)
1507 pT->m_hWnd = NULL;
1508 return nRet;
1509 }
1510
1511 void OnInitialized()
1512 {
1513 }
1514
1515 void OnSelChanged(LPITEMIDLIST /*pItemIDList*/)
1516 {
1517 }
1518
1519 int OnValidateFailed(LPCTSTR /*lpstrFolderPath*/)
1520 {
1521 return 1; // 1=continue, 0=EndDialog
1522 }
1523
1524 void OnIUnknown(IUnknown* /*pUnknown*/)
1525 {
1526 }
1527
1528 // Commands - valid to call only from handlers
1529 void EnableOK(BOOL bEnable)
1530 {
1531 ATLASSERT(m_hWnd != NULL);
1532 ::SendMessage(m_hWnd, BFFM_ENABLEOK, 0, bEnable);
1533 }
1534
1535 void SetSelection(LPCITEMIDLIST pItemIDList)
1536 {
1537 ATLASSERT(m_hWnd != NULL);
1538 ::SendMessage(m_hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pItemIDList);
1539 }
1540
1541 void SetSelection(LPCTSTR lpstrFolderPath)
1542 {
1543 ATLASSERT(m_hWnd != NULL);
1544 ::SendMessage(m_hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpstrFolderPath);
1545 }
1546
1547 void SetStatusText(LPCTSTR lpstrText)
1548 {
1549 ATLASSERT(m_hWnd != NULL);
1550 ::SendMessage(m_hWnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)lpstrText);
1551 }
1552
1553 void SetOKText(LPCTSTR lpstrOKText)
1554 {
1555 #ifndef BFFM_SETOKTEXT
1556 const UINT BFFM_SETOKTEXT = WM_USER + 105;
1557 #endif
1558 ATLASSERT(m_hWnd != NULL);
1559 USES_CONVERSION;
1560 LPCWSTR lpstr = T2CW(lpstrOKText);
1561 ::SendMessage(m_hWnd, BFFM_SETOKTEXT, 0, (LPARAM)lpstr);
1562 }
1563
1564 void SetExpanded(LPCITEMIDLIST pItemIDList)
1565 {
1566 #ifndef BFFM_SETEXPANDED
1567 const UINT BFFM_SETEXPANDED = WM_USER + 106;
1568 #endif
1569 ATLASSERT(m_hWnd != NULL);
1570 ::SendMessage(m_hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pItemIDList);
1571 }
1572
1573 void SetExpanded(LPCTSTR lpstrFolderPath)
1574 {
1575 #ifndef BFFM_SETEXPANDED
1576 const UINT BFFM_SETEXPANDED = WM_USER + 106;
1577 #endif
1578 ATLASSERT(m_hWnd != NULL);
1579 USES_CONVERSION;
1580 LPCWSTR lpstr = T2CW(lpstrFolderPath);
1581 ::SendMessage(m_hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)lpstr);
1582 }
1583 };
1584
1585 class CFolderDialog : public CFolderDialogImpl<CFolderDialog>
1586 {
1587 public:
1588 CFolderDialog(HWND hWndParent = NULL, LPCTSTR lpstrTitle = NULL, UINT uFlags = BIF_RETURNONLYFSDIRS)
1589 : CFolderDialogImpl<CFolderDialog>(hWndParent, lpstrTitle, uFlags)
1590 { }
1591 };
1592
1593 #endif // !_WIN32_WCE
1594
1595
1596 ///////////////////////////////////////////////////////////////////////////////
1597 // CCommonDialogImplBase - base class for common dialog classes
1598
1599 class ATL_NO_VTABLE CCommonDialogImplBase : public ATL::CWindowImplBase
1600 {
1601 public:
1602 static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1603 {
1604 if(uMsg != WM_INITDIALOG)
1605 return 0;
1606 CCommonDialogImplBase* pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
1607 ATLASSERT(pT != NULL);
1608 ATLASSERT(pT->m_hWnd == NULL);
1609 ATLASSERT(::IsWindow(hWnd));
1610 // subclass dialog's window
1611 if(!pT->SubclassWindow(hWnd))
1612 {
1613 ATLTRACE2(atlTraceUI, 0, _T("Subclassing a common dialog failed\n"));
1614 return 0;
1615 }
1616 // check message map for WM_INITDIALOG handler
1617 LRESULT lRes = 0;
1618 if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
1619 return 0;
1620 return lRes;
1621 }
1622
1623 // Special override for common dialogs
1624 BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
1625 {
1626 ATLASSERT(::IsWindow(m_hWnd));
1627 SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
1628 return TRUE;
1629 }
1630
1631 // Implementation - try to override these, to prevent errors
1632 HWND Create(HWND, ATL::_U_RECT, LPCTSTR, DWORD, DWORD, ATL::_U_MENUorID, ATOM, LPVOID)
1633 {
1634 ATLASSERT(FALSE); // should not be called
1635 return NULL;
1636 }
1637
1638 static LRESULT CALLBACK StartWindowProc(HWND /*hWnd*/, UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/)
1639 {
1640 ATLASSERT(FALSE); // should not be called
1641 return 0;
1642 }
1643 };
1644
1645
1646 ///////////////////////////////////////////////////////////////////////////////
1647 // CFontDialogImpl - font selection dialog
1648
1649 #ifndef _WIN32_WCE
1650
1651 template <class T>
1652 class ATL_NO_VTABLE CFontDialogImpl : public CCommonDialogImplBase
1653 {
1654 public:
1655 enum { _cchStyleName = 64 };
1656
1657 CHOOSEFONT m_cf;
1658 TCHAR m_szStyleName[_cchStyleName]; // contains style name after return
1659 LOGFONT m_lf; // default LOGFONT to store the info
1660
1661 // Constructors
1662 CFontDialogImpl(LPLOGFONT lplfInitial = NULL,
1663 DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
1664 HDC hDCPrinter = NULL,
1665 HWND hWndParent = NULL)
1666 {
1667 memset(&m_cf, 0, sizeof(m_cf));
1668 memset(&m_lf, 0, sizeof(m_lf));
1669 memset(&m_szStyleName, 0, sizeof(m_szStyleName));
1670
1671 m_cf.lStructSize = sizeof(m_cf);
1672 m_cf.hwndOwner = hWndParent;
1673 m_cf.rgbColors = RGB(0, 0, 0);
1674 m_cf.lpszStyle = (LPTSTR)&m_szStyleName;
1675 m_cf.Flags = dwFlags | CF_ENABLEHOOK;
1676 m_cf.lpfnHook = (LPCFHOOKPROC)T::HookProc;
1677
1678 if(lplfInitial != NULL)
1679 {
1680 m_cf.lpLogFont = lplfInitial;
1681 m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1682 m_lf = *lplfInitial;
1683 }
1684 else
1685 {
1686 m_cf.lpLogFont = &m_lf;
1687 }
1688
1689 if(hDCPrinter != NULL)
1690 {
1691 m_cf.hDC = hDCPrinter;
1692 m_cf.Flags |= CF_PRINTERFONTS;
1693 }
1694 }
1695
1696 // Operations
1697 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
1698 {
1699 ATLASSERT((m_cf.Flags & CF_ENABLEHOOK) != 0);
1700 ATLASSERT(m_cf.lpfnHook != NULL); // can still be a user hook
1701
1702 if(m_cf.hwndOwner == NULL) // set only if not specified before
1703 m_cf.hwndOwner = hWndParent;
1704
1705 ATLASSERT(m_hWnd == NULL);
1706
1707 #if (_ATL_VER >= 0x0800)
1708 // Allocate the thunk structure here, where we can fail gracefully.
1709 BOOL bRetTh = m_thunk.Init(NULL, NULL);
1710 if(bRetTh == FALSE)
1711 {
1712 ::SetLastError(ERROR_OUTOFMEMORY);
1713 return -1;
1714 }
1715 #endif // (_ATL_VER >= 0x0800)
1716
1717 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
1718
1719 BOOL bRet = ::ChooseFont(&m_cf);
1720
1721 m_hWnd = NULL;
1722
1723 if(bRet) // copy logical font from user's initialization buffer (if needed)
1724 SecureHelper::memcpy_x(&m_lf, sizeof(m_lf), m_cf.lpLogFont, sizeof(m_lf));
1725
1726 return bRet ? IDOK : IDCANCEL;
1727 }
1728
1729 // works only when the dialog is dislayed or after
1730 void GetCurrentFont(LPLOGFONT lplf) const
1731 {
1732 ATLASSERT(lplf != NULL);
1733
1734 if(m_hWnd != NULL)
1735 ::SendMessage(m_hWnd, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM)lplf);
1736 else
1737 *lplf = m_lf;
1738 }
1739
1740 // works only when the dialog is dislayed or before
1741 #ifndef _WIN32_WCE
1742 void SetLogFont(LPLOGFONT lplf)
1743 {
1744 ATLASSERT(lplf != NULL);
1745 #ifndef WM_CHOOSEFONT_SETLOGFONT
1746 const UINT WM_CHOOSEFONT_SETLOGFONT = (WM_USER + 101);
1747 #endif
1748 if(m_hWnd != NULL)
1749 {
1750 ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETLOGFONT, 0, (LPARAM)lplf);
1751 }
1752 else
1753 {
1754 m_lf = *lplf;
1755 m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1756 }
1757 }
1758
1759 void SetFlags(DWORD dwFlags)
1760 {
1761 #ifndef WM_CHOOSEFONT_SETFLAGS
1762 const UINT WM_CHOOSEFONT_SETFLAGS = (WM_USER + 102);
1763 #endif
1764 if(m_hWnd != NULL)
1765 {
1766 CHOOSEFONT cf = { sizeof(CHOOSEFONT) };
1767 cf.Flags = dwFlags;
1768 ::SendMessage(m_hWnd, WM_CHOOSEFONT_SETFLAGS, 0, (LPARAM)&cf);
1769 }
1770 else
1771 {
1772 m_cf.Flags = dwFlags;
1773 }
1774 }
1775 #endif // !_WIN32_WCE
1776
1777 // Helpers for parsing information after successful return
1778 LPCTSTR GetFaceName() const // return the face name of the font
1779 {
1780 return (LPCTSTR)m_cf.lpLogFont->lfFaceName;
1781 }
1782
1783 LPCTSTR GetStyleName() const // return the style name of the font
1784 {
1785 return m_cf.lpszStyle;
1786 }
1787
1788 int GetSize() const // return the pt size of the font
1789 {
1790 return m_cf.iPointSize;
1791 }
1792
1793 COLORREF GetColor() const // return the color of the font
1794 {
1795 return m_cf.rgbColors;
1796 }
1797
1798 int GetWeight() const // return the chosen font weight
1799 {
1800 return (int)m_cf.lpLogFont->lfWeight;
1801 }
1802
1803 BOOL IsStrikeOut() const // return TRUE if strikeout
1804 {
1805 return (m_cf.lpLogFont->lfStrikeOut) ? TRUE : FALSE;
1806 }
1807
1808 BOOL IsUnderline() const // return TRUE if underline
1809 {
1810 return (m_cf.lpLogFont->lfUnderline) ? TRUE : FALSE;
1811 }
1812
1813 BOOL IsBold() const // return TRUE if bold font
1814 {
1815 return (m_cf.lpLogFont->lfWeight == FW_BOLD) ? TRUE : FALSE;
1816 }
1817
1818 BOOL IsItalic() const // return TRUE if italic font
1819 {
1820 return m_cf.lpLogFont->lfItalic ? TRUE : FALSE;
1821 }
1822 };
1823
1824 class CFontDialog : public CFontDialogImpl<CFontDialog>
1825 {
1826 public:
1827 CFontDialog(LPLOGFONT lplfInitial = NULL,
1828 DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
1829 HDC hDCPrinter = NULL,
1830 HWND hWndParent = NULL)
1831 : CFontDialogImpl<CFontDialog>(lplfInitial, dwFlags, hDCPrinter, hWndParent)
1832 { }
1833
1834 DECLARE_EMPTY_MSG_MAP()
1835 };
1836
1837 #endif // _WIN32_WCE
1838
1839
1840 ///////////////////////////////////////////////////////////////////////////////
1841 // CRichEditFontDialogImpl - font selection for the Rich Edit ctrl
1842
1843 #if defined(_RICHEDIT_) && !defined(_WIN32_WCE)
1844
1845 template <class T>
1846 class ATL_NO_VTABLE CRichEditFontDialogImpl : public CFontDialogImpl< T >
1847 {
1848 public:
1849 CRichEditFontDialogImpl(const CHARFORMAT& charformat,
1850 DWORD dwFlags = CF_SCREENFONTS,
1851 HDC hDCPrinter = NULL,
1852 HWND hWndParent = NULL)
1853 : CFontDialogImpl< T >(NULL, dwFlags, hDCPrinter, hWndParent)
1854 {
1855 m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;
1856 m_cf.Flags |= FillInLogFont(charformat);
1857 m_cf.lpLogFont = &m_lf;
1858
1859 if((charformat.dwMask & CFM_COLOR) != 0)
1860 m_cf.rgbColors = charformat.crTextColor;
1861 }
1862
1863 void GetCharFormat(CHARFORMAT& cf) const
1864 {
1865 USES_CONVERSION;
1866 cf.dwEffects = 0;
1867 cf.dwMask = 0;
1868 if((m_cf.Flags & CF_NOSTYLESEL) == 0)
1869 {
1870 cf.dwMask |= CFM_BOLD | CFM_ITALIC;
1871 cf.dwEffects |= IsBold() ? CFE_BOLD : 0;
1872 cf.dwEffects |= IsItalic() ? CFE_ITALIC : 0;
1873 }
1874 if((m_cf.Flags & CF_NOSIZESEL) == 0)
1875 {
1876 cf.dwMask |= CFM_SIZE;
1877 // GetSize() returns in tenths of points so mulitply by 2 to get twips
1878 cf.yHeight = GetSize() * 2;
1879 }
1880
1881 if((m_cf.Flags & CF_NOFACESEL) == 0)
1882 {
1883 cf.dwMask |= CFM_FACE;
1884 cf.bPitchAndFamily = m_cf.lpLogFont->lfPitchAndFamily;
1885 #if (_RICHEDIT_VER >= 0x0200)
1886 SecureHelper::strcpy_x(cf.szFaceName, _countof(cf.szFaceName), GetFaceName());
1887 #else // !(_RICHEDIT_VER >= 0x0200)
1888 SecureHelper::strcpyA_x(cf.szFaceName, _countof(cf.szFaceName), T2A((LPTSTR)(LPCTSTR)GetFaceName()));
1889 #endif // !(_RICHEDIT_VER >= 0x0200)
1890 }
1891
1892 if((m_cf.Flags & CF_EFFECTS) != 0)
1893 {
1894 cf.dwMask |= CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
1895 cf.dwEffects |= IsUnderline() ? CFE_UNDERLINE : 0;
1896 cf.dwEffects |= IsStrikeOut() ? CFE_STRIKEOUT : 0;
1897 cf.crTextColor = GetColor();
1898 }
1899 if((m_cf.Flags & CF_NOSCRIPTSEL) == 0)
1900 {
1901 cf.bCharSet = m_cf.lpLogFont->lfCharSet;
1902 cf.dwMask |= CFM_CHARSET;
1903 }
1904 cf.yOffset = 0;
1905 }
1906
1907 DWORD FillInLogFont(const CHARFORMAT& cf)
1908 {
1909 USES_CONVERSION;
1910 DWORD dwFlags = 0;
1911 if((cf.dwMask & CFM_SIZE) != 0)
1912 {
1913 HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
1914 LONG yPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY);
1915 m_lf.lfHeight = -(int)((cf.yHeight * yPerInch) / 1440);
1916 }
1917 else
1918 m_lf.lfHeight = 0;
1919
1920 m_lf.lfWidth = 0;
1921 m_lf.lfEscapement = 0;
1922 m_lf.lfOrientation = 0;
1923
1924 if((cf.dwMask & (CFM_ITALIC | CFM_BOLD)) == (CFM_ITALIC | CFM_BOLD))
1925 {
1926 m_lf.lfWeight = ((cf.dwEffects & CFE_BOLD) != 0) ? FW_BOLD : FW_NORMAL;
1927 m_lf.lfItalic = (BYTE)(((cf.dwEffects & CFE_ITALIC) != 0) ? TRUE : FALSE);
1928 }
1929 else
1930 {
1931 dwFlags |= CF_NOSTYLESEL;
1932 m_lf.lfWeight = FW_DONTCARE;
1933 m_lf.lfItalic = FALSE;
1934 }
1935
1936 if((cf.dwMask & (CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR)) == (CFM_UNDERLINE|CFM_STRIKEOUT|CFM_COLOR))
1937 {
1938 dwFlags |= CF_EFFECTS;
1939 m_lf.lfUnderline = (BYTE)(((cf.dwEffects & CFE_UNDERLINE) != 0) ? TRUE : FALSE);
1940 m_lf.lfStrikeOut = (BYTE)(((cf.dwEffects & CFE_STRIKEOUT) != 0) ? TRUE : FALSE);
1941 }
1942 else
1943 {
1944 m_lf.lfUnderline = (BYTE)FALSE;
1945 m_lf.lfStrikeOut = (BYTE)FALSE;
1946 }
1947
1948 if((cf.dwMask & CFM_CHARSET) != 0)
1949 m_lf.lfCharSet = cf.bCharSet;
1950 else
1951 dwFlags |= CF_NOSCRIPTSEL;
1952 m_lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
1953 m_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1954 m_lf.lfQuality = DEFAULT_QUALITY;
1955 if((cf.dwMask & CFM_FACE) != 0)
1956 {
1957 m_lf.lfPitchAndFamily = cf.bPitchAndFamily;
1958 #if (_RICHEDIT_VER >= 0x0200)
1959 SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), cf.szFaceName);
1960 #else // !(_RICHEDIT_VER >= 0x0200)
1961 SecureHelper::strcpy_x(m_lf.lfFaceName, _countof(m_lf.lfFaceName), A2T((LPSTR)cf.szFaceName));
1962 #endif // !(_RICHEDIT_VER >= 0x0200)
1963 }
1964 else
1965 {
1966 m_lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
1967 m_lf.lfFaceName[0] = (TCHAR)0;
1968 }
1969 return dwFlags;
1970 }
1971 };
1972
1973 class CRichEditFontDialog : public CRichEditFontDialogImpl<CRichEditFontDialog>
1974 {
1975 public:
1976 CRichEditFontDialog(const CHARFORMAT& charformat,
1977 DWORD dwFlags = CF_SCREENFONTS,
1978 HDC hDCPrinter = NULL,
1979 HWND hWndParent = NULL)
1980 : CRichEditFontDialogImpl<CRichEditFontDialog>(charformat, dwFlags, hDCPrinter, hWndParent)
1981 { }
1982
1983 DECLARE_EMPTY_MSG_MAP()
1984 };
1985
1986 #endif // defined(_RICHEDIT_) && !defined(_WIN32_WCE)
1987
1988
1989 ///////////////////////////////////////////////////////////////////////////////
1990 // CColorDialogImpl - color selection
1991
1992 #if !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
1993
1994 #ifdef _WIN32_WCE
1995 #pragma comment(lib, "commdlg.lib")
1996
1997 #ifndef SETRGBSTRING
1998 #define SETRGBSTRING _T("commdlg_SetRGBColor")
1999 #endif
2000
2001 #ifndef COLOROKSTRING
2002 #define COLOROKSTRING _T("commdlg_ColorOK")
2003 #endif
2004 #endif
2005
2006 template <class T>
2007 class ATL_NO_VTABLE CColorDialogImpl : public CCommonDialogImplBase
2008 {
2009 public:
2010 CHOOSECOLOR m_cc;
2011
2012 // Constructor
2013 CColorDialogImpl(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
2014 {
2015 memset(&m_cc, 0, sizeof(m_cc));
2016
2017 m_cc.lStructSize = sizeof(m_cc);
2018 m_cc.lpCustColors = GetCustomColors();
2019 m_cc.hwndOwner = hWndParent;
2020 m_cc.Flags = dwFlags | CC_ENABLEHOOK;
2021 m_cc.lpfnHook = (LPCCHOOKPROC)T::HookProc;
2022
2023 if(clrInit != 0)
2024 {
2025 m_cc.rgbResult = clrInit;
2026 m_cc.Flags |= CC_RGBINIT;
2027 }
2028 }
2029
2030 // Operations
2031 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2032 {
2033 ATLASSERT((m_cc.Flags & CC_ENABLEHOOK) != 0);
2034 ATLASSERT(m_cc.lpfnHook != NULL); // can still be a user hook
2035
2036 if(m_cc.hwndOwner == NULL) // set only if not specified before
2037 m_cc.hwndOwner = hWndParent;
2038
2039 ATLASSERT(m_hWnd == NULL);
2040
2041 #if (_ATL_VER >= 0x0800)
2042 // Allocate the thunk structure here, where we can fail gracefully.
2043 BOOL bRetTh = m_thunk.Init(NULL, NULL);
2044 if(bRetTh == FALSE)
2045 {
2046 ::SetLastError(ERROR_OUTOFMEMORY);
2047 return -1;
2048 }
2049 #endif // (_ATL_VER >= 0x0800)
2050
2051 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2052
2053 BOOL bRet = ::ChooseColor(&m_cc);
2054
2055 m_hWnd = NULL;
2056
2057 return bRet ? IDOK : IDCANCEL;
2058 }
2059
2060 // Set the current color while dialog is displayed
2061 void SetCurrentColor(COLORREF clr)
2062 {
2063 ATLASSERT(::IsWindow(m_hWnd));
2064 SendMessage(_GetSetRGBMessage(), 0, (LPARAM)clr);
2065 }
2066
2067 // Get the selected color after DoModal returns, or in OnColorOK
2068 COLORREF GetColor() const
2069 {
2070 return m_cc.rgbResult;
2071 }
2072
2073 // Special override for the color dialog
2074 static UINT_PTR APIENTRY HookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2075 {
2076 if(uMsg != WM_INITDIALOG && uMsg != _GetColorOKMessage())
2077 return 0;
2078
2079 LPCHOOSECOLOR lpCC = (LPCHOOSECOLOR)lParam;
2080 CCommonDialogImplBase* pT = NULL;
2081
2082 if(uMsg == WM_INITDIALOG)
2083 {
2084 pT = (CCommonDialogImplBase*)ModuleHelper::ExtractCreateWndData();
2085 lpCC->lCustData = (LPARAM)pT;
2086 ATLASSERT(pT != NULL);
2087 ATLASSERT(pT->m_hWnd == NULL);
2088 ATLASSERT(::IsWindow(hWnd));
2089 // subclass dialog's window
2090 if(!pT->SubclassWindow(hWnd))
2091 {
2092 ATLTRACE2(atlTraceUI, 0, _T("Subclassing a Color common dialog failed\n"));
2093 return 0;
2094 }
2095 }
2096 else if(uMsg == _GetColorOKMessage())
2097 {
2098 pT = (CCommonDialogImplBase*)lpCC->lCustData;
2099 ATLASSERT(pT != NULL);
2100 ATLASSERT(::IsWindow(pT->m_hWnd));
2101 }
2102 else
2103 {
2104 ATLASSERT(FALSE);
2105 return 0;
2106 }
2107
2108 // pass to the message map
2109 LRESULT lRes = 0;
2110 if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
2111 return 0;
2112
2113 return lRes;
2114 }
2115
2116 // Helpers
2117 static COLORREF* GetCustomColors()
2118 {
2119 static COLORREF rgbCustomColors[16] =
2120 {
2121 RGB(255, 255, 255), RGB(255, 255, 255),
2122 RGB(255, 255, 255), RGB(255, 255, 255),
2123 RGB(255, 255, 255), RGB(255, 255, 255),
2124 RGB(255, 255, 255), RGB(255, 255, 255),
2125 RGB(255, 255, 255), RGB(255, 255, 255),
2126 RGB(255, 255, 255), RGB(255, 255, 255),
2127 RGB(255, 255, 255), RGB(255, 255, 255),
2128 RGB(255, 255, 255), RGB(255, 255, 255),
2129 };
2130
2131 return rgbCustomColors;
2132 }
2133
2134 static UINT _GetSetRGBMessage()
2135 {
2136 static UINT uSetRGBMessage = 0;
2137 if(uSetRGBMessage == 0)
2138 {
2139 CStaticDataInitCriticalSectionLock lock;
2140 if(FAILED(lock.Lock()))
2141 {
2142 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetSetRGBMessage.\n"));
2143 ATLASSERT(FALSE);
2144 return 0;
2145 }
2146
2147 if(uSetRGBMessage == 0)
2148 uSetRGBMessage = ::RegisterWindowMessage(SETRGBSTRING);
2149
2150 lock.Unlock();
2151 }
2152 ATLASSERT(uSetRGBMessage != 0);
2153 return uSetRGBMessage;
2154 }
2155
2156 static UINT _GetColorOKMessage()
2157 {
2158 static UINT uColorOKMessage = 0;
2159 if(uColorOKMessage == 0)
2160 {
2161 CStaticDataInitCriticalSectionLock lock;
2162 if(FAILED(lock.Lock()))
2163 {
2164 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CColorDialogImpl::_GetColorOKMessage.\n"));
2165 ATLASSERT(FALSE);
2166 return 0;
2167 }
2168
2169 if(uColorOKMessage == 0)
2170 uColorOKMessage = ::RegisterWindowMessage(COLOROKSTRING);
2171
2172 lock.Unlock();
2173 }
2174 ATLASSERT(uColorOKMessage != 0);
2175 return uColorOKMessage;
2176 }
2177
2178 // Message map and handlers
2179 BEGIN_MSG_MAP(CColorDialogImpl)
2180 MESSAGE_HANDLER(_GetColorOKMessage(), _OnColorOK)
2181 END_MSG_MAP()
2182
2183 LRESULT _OnColorOK(UINT, WPARAM, LPARAM, BOOL&)
2184 {
2185 T* pT = static_cast<T*>(this);
2186 return pT->OnColorOK();
2187 }
2188
2189 // Overrideable
2190 BOOL OnColorOK() // validate color
2191 {
2192 return FALSE;
2193 }
2194 };
2195
2196 class CColorDialog : public CColorDialogImpl<CColorDialog>
2197 {
2198 public:
2199 CColorDialog(COLORREF clrInit = 0, DWORD dwFlags = 0, HWND hWndParent = NULL)
2200 : CColorDialogImpl<CColorDialog>(clrInit, dwFlags, hWndParent)
2201 { }
2202
2203 // override base class map and references to handlers
2204 DECLARE_EMPTY_MSG_MAP()
2205 };
2206
2207 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE > 420) && !(defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE > 0x0500)))
2208
2209
2210 ///////////////////////////////////////////////////////////////////////////////
2211 // CPrintDialogImpl - used for Print... and PrintSetup...
2212
2213 #ifndef _WIN32_WCE
2214
2215 // global helper
2216 static inline HDC _AtlCreateDC(HGLOBAL hDevNames, HGLOBAL hDevMode)
2217 {
2218 if(hDevNames == NULL)
2219 return NULL;
2220
2221 LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(hDevNames);
2222 LPDEVMODE lpDevMode = (hDevMode != NULL) ? (LPDEVMODE)::GlobalLock(hDevMode) : NULL;
2223
2224 if(lpDevNames == NULL)
2225 return NULL;
2226
2227 HDC hDC = ::CreateDC((LPCTSTR)lpDevNames + lpDevNames->wDriverOffset,
2228 (LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
2229 (LPCTSTR)lpDevNames + lpDevNames->wOutputOffset,
2230 lpDevMode);
2231
2232 ::GlobalUnlock(hDevNames);
2233 if(hDevMode != NULL)
2234 ::GlobalUnlock(hDevMode);
2235 return hDC;
2236 }
2237
2238 #pragma warning(push)
2239 #pragma warning(disable: 4512) // assignment operator could not be generated
2240
2241 template <class T>
2242 class ATL_NO_VTABLE CPrintDialogImpl : public CCommonDialogImplBase
2243 {
2244 public:
2245 // print dialog parameter block (note this is a reference)
2246 PRINTDLG& m_pd;
2247
2248 // Constructors
2249 CPrintDialogImpl(BOOL bPrintSetupOnly = FALSE, // TRUE for Print Setup, FALSE for Print Dialog
2250 DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
2251 HWND hWndParent = NULL)
2252 : m_pd(m_pdActual)
2253 {
2254 memset(&m_pdActual, 0, sizeof(m_pdActual));
2255
2256 m_pd.lStructSize = sizeof(m_pdActual);
2257 m_pd.hwndOwner = hWndParent;
2258 m_pd.Flags = (dwFlags | PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK);
2259 m_pd.lpfnPrintHook = (LPPRINTHOOKPROC)T::HookProc;
2260 m_pd.lpfnSetupHook = (LPSETUPHOOKPROC)T::HookProc;
2261
2262 if(bPrintSetupOnly)
2263 m_pd.Flags |= PD_PRINTSETUP;
2264 else
2265 m_pd.Flags |= PD_RETURNDC;
2266
2267 m_pd.Flags &= ~PD_RETURNIC; // do not support information context
2268 }
2269
2270 // Operations
2271 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2272 {
2273 ATLASSERT((m_pd.Flags & PD_ENABLEPRINTHOOK) != 0);
2274 ATLASSERT((m_pd.Flags & PD_ENABLESETUPHOOK) != 0);
2275 ATLASSERT(m_pd.lpfnPrintHook != NULL); // can still be a user hook
2276 ATLASSERT(m_pd.lpfnSetupHook != NULL); // can still be a user hook
2277 ATLASSERT((m_pd.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
2278
2279 if(m_pd.hwndOwner == NULL) // set only if not specified before
2280 m_pd.hwndOwner = hWndParent;
2281
2282 ATLASSERT(m_hWnd == NULL);
2283
2284 #if (_ATL_VER >= 0x0800)
2285 // Allocate the thunk structure here, where we can fail gracefully.
2286 BOOL bRetTh = m_thunk.Init(NULL, NULL);
2287 if(bRetTh == FALSE)
2288 {
2289 ::SetLastError(ERROR_OUTOFMEMORY);
2290 return -1;
2291 }
2292 #endif // (_ATL_VER >= 0x0800)
2293
2294 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2295
2296 BOOL bRet = ::PrintDlg(&m_pd);
2297
2298 m_hWnd = NULL;
2299
2300 return bRet ? IDOK : IDCANCEL;
2301 }
2302
2303 // GetDefaults will not display a dialog but will get device defaults
2304 BOOL GetDefaults()
2305 {
2306 m_pd.Flags |= PD_RETURNDEFAULT;
2307 ATLASSERT(m_pd.hDevMode == NULL); // must be NULL
2308 ATLASSERT(m_pd.hDevNames == NULL); // must be NULL
2309
2310 return ::PrintDlg(&m_pd);
2311 }
2312
2313 // Helpers for parsing information after successful return num. copies requested
2314 int GetCopies() const
2315 {
2316 if((m_pd.Flags & PD_USEDEVMODECOPIES) != 0)
2317 {
2318 LPDEVMODE lpDevMode = GetDevMode();
2319 return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
2320 }
2321
2322 return m_pd.nCopies;
2323 }
2324
2325 BOOL PrintCollate() const // TRUE if collate checked
2326 {
2327 return ((m_pd.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
2328 }
2329
2330 BOOL PrintSelection() const // TRUE if printing selection
2331 {
2332 return ((m_pd.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
2333 }
2334
2335 BOOL PrintAll() const // TRUE if printing all pages
2336 {
2337 return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
2338 }
2339
2340 BOOL PrintRange() const // TRUE if printing page range
2341 {
2342 return ((m_pd.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
2343 }
2344
2345 BOOL PrintToFile() const // TRUE if printing to a file
2346 {
2347 return ((m_pd.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
2348 }
2349
2350 int GetFromPage() const // starting page if valid
2351 {
2352 return PrintRange() ? m_pd.nFromPage : -1;
2353 }
2354
2355 int GetToPage() const // ending page if valid
2356 {
2357 return PrintRange() ? m_pd.nToPage : -1;
2358 }
2359
2360 LPDEVMODE GetDevMode() const // return DEVMODE
2361 {
2362 if(m_pd.hDevMode == NULL)
2363 return NULL;
2364
2365 return (LPDEVMODE)::GlobalLock(m_pd.hDevMode);
2366 }
2367
2368 LPCTSTR GetDriverName() const // return driver name
2369 {
2370 if(m_pd.hDevNames == NULL)
2371 return NULL;
2372
2373 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2374 if(lpDev == NULL)
2375 return NULL;
2376
2377 return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2378 }
2379
2380 LPCTSTR GetDeviceName() const // return device name
2381 {
2382 if(m_pd.hDevNames == NULL)
2383 return NULL;
2384
2385 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2386 if(lpDev == NULL)
2387 return NULL;
2388
2389 return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2390 }
2391
2392 LPCTSTR GetPortName() const // return output port name
2393 {
2394 if(m_pd.hDevNames == NULL)
2395 return NULL;
2396
2397 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pd.hDevNames);
2398 if(lpDev == NULL)
2399 return NULL;
2400
2401 return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2402 }
2403
2404 HDC GetPrinterDC() const // return HDC (caller must delete)
2405 {
2406 ATLASSERT((m_pd.Flags & PD_RETURNDC) != 0);
2407 return m_pd.hDC;
2408 }
2409
2410 // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
2411 // This DC is returned, but also stored in m_pd.hDC as though it had been
2412 // returned by CommDlg. It is assumed that any previously obtained DC
2413 // has been/will be deleted by the user. This may be
2414 // used without ever invoking the print/print setup dialogs.
2415 HDC CreatePrinterDC()
2416 {
2417 m_pd.hDC = _AtlCreateDC(m_pd.hDevNames, m_pd.hDevMode);
2418 return m_pd.hDC;
2419 }
2420
2421 // Implementation
2422 PRINTDLG m_pdActual; // the Print/Print Setup need to share this
2423
2424 // The following handle the case of print setup... from the print dialog
2425 CPrintDialogImpl(PRINTDLG& pdInit) : m_pd(pdInit)
2426 { }
2427
2428 BEGIN_MSG_MAP(CPrintDialogImpl)
2429 #ifdef psh1
2430 COMMAND_ID_HANDLER(psh1, OnPrintSetup) // print setup button when print is displayed
2431 #else // !psh1
2432 COMMAND_ID_HANDLER(0x0400, OnPrintSetup) // value from dlgs.h
2433 #endif // !psh1
2434 END_MSG_MAP()
2435
2436 LRESULT OnPrintSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/)
2437 {
2438 T dlgSetup(m_pd);
2439 ModuleHelper::AddCreateWndData(&dlgSetup.m_thunk.cd, (CCommonDialogImplBase*)&dlgSetup);
2440 return DefWindowProc(WM_COMMAND, MAKEWPARAM(wID, wNotifyCode), (LPARAM)hWndCtl);
2441 }
2442 };
2443
2444 class CPrintDialog : public CPrintDialogImpl<CPrintDialog>
2445 {
2446 public:
2447 CPrintDialog(BOOL bPrintSetupOnly = FALSE,
2448 DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION,
2449 HWND hWndParent = NULL)
2450 : CPrintDialogImpl<CPrintDialog>(bPrintSetupOnly, dwFlags, hWndParent)
2451 { }
2452
2453 CPrintDialog(PRINTDLG& pdInit) : CPrintDialogImpl<CPrintDialog>(pdInit)
2454 { }
2455 };
2456
2457 #pragma warning(pop)
2458
2459 #endif // _WIN32_WCE
2460
2461
2462 ///////////////////////////////////////////////////////////////////////////////
2463 // CPrintDialogExImpl - new print dialog for Windows 2000
2464
2465 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
2466
2467 }; // namespace WTL
2468
2469 #include <atlcom.h>
2470
2471 extern "C" const __declspec(selectany) IID IID_IPrintDialogCallback = {0x5852a2c3, 0x6530, 0x11d1, {0xb6, 0xa3, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
2472 extern "C" const __declspec(selectany) IID IID_IPrintDialogServices = {0x509aaeda, 0x5639, 0x11d1, {0xb6, 0xa1, 0x0, 0x0, 0xf8, 0x75, 0x7b, 0xf9}};
2473
2474 namespace WTL
2475 {
2476
2477 template <class T>
2478 class ATL_NO_VTABLE CPrintDialogExImpl :
2479 public ATL::CWindow,
2480 public ATL::CMessageMap,
2481 public IPrintDialogCallback,
2482 public ATL::IObjectWithSiteImpl< T >
2483 {
2484 public:
2485 PRINTDLGEX m_pdex;
2486
2487 // Constructor
2488 CPrintDialogExImpl(DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
2489 HWND hWndParent = NULL)
2490 {
2491 memset(&m_pdex, 0, sizeof(m_pdex));
2492
2493 m_pdex.lStructSize = sizeof(PRINTDLGEX);
2494 m_pdex.hwndOwner = hWndParent;
2495 m_pdex.Flags = dwFlags;
2496 m_pdex.nStartPage = START_PAGE_GENERAL;
2497 // callback object will be set in DoModal
2498
2499 m_pdex.Flags &= ~PD_RETURNIC; // do not support information context
2500 }
2501
2502 // Operations
2503 HRESULT DoModal(HWND hWndParent = ::GetActiveWindow())
2504 {
2505 ATLASSERT(m_hWnd == NULL);
2506 ATLASSERT((m_pdex.Flags & PD_RETURNDEFAULT) == 0); // use GetDefaults for this
2507
2508 if(m_pdex.hwndOwner == NULL) // set only if not specified before
2509 m_pdex.hwndOwner = hWndParent;
2510
2511 T* pT = static_cast<T*>(this);
2512 m_pdex.lpCallback = (IUnknown*)(IPrintDialogCallback*)pT;
2513
2514 HRESULT hResult = ::PrintDlgEx(&m_pdex);
2515
2516 m_hWnd = NULL;
2517
2518 return hResult;
2519 }
2520
2521 BOOL EndDialog(INT_PTR /*nRetCode*/ = 0)
2522 {
2523 ATLASSERT(::IsWindow(m_hWnd));
2524 SendMessage(WM_COMMAND, MAKEWPARAM(IDABORT, 0));
2525 return TRUE;
2526 }
2527
2528 // GetDefaults will not display a dialog but will get device defaults
2529 HRESULT GetDefaults()
2530 {
2531 ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL
2532 ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL
2533
2534 if(m_pdex.hwndOwner == NULL) // set only if not specified before
2535 m_pdex.hwndOwner = ::GetActiveWindow();
2536
2537 m_pdex.Flags |= PD_RETURNDEFAULT;
2538 HRESULT hRet = ::PrintDlgEx(&m_pdex);
2539 m_pdex.Flags &= ~PD_RETURNDEFAULT;
2540
2541 return hRet;
2542 }
2543
2544 // Helpers for parsing information after successful return num. copies requested
2545 int GetCopies() const
2546 {
2547 if((m_pdex.Flags & PD_USEDEVMODECOPIES) != 0)
2548 {
2549 LPDEVMODE lpDevMode = GetDevMode();
2550 return (lpDevMode != NULL) ? lpDevMode->dmCopies : -1;
2551 }
2552
2553 return m_pdex.nCopies;
2554 }
2555
2556 BOOL PrintCollate() const // TRUE if collate checked
2557 {
2558 return ((m_pdex.Flags & PD_COLLATE) != 0) ? TRUE : FALSE;
2559 }
2560
2561 BOOL PrintSelection() const // TRUE if printing selection
2562 {
2563 return ((m_pdex.Flags & PD_SELECTION) != 0) ? TRUE : FALSE;
2564 }
2565
2566 BOOL PrintAll() const // TRUE if printing all pages
2567 {
2568 return (!PrintRange() && !PrintSelection()) ? TRUE : FALSE;
2569 }
2570
2571 BOOL PrintRange() const // TRUE if printing page range
2572 {
2573 return ((m_pdex.Flags & PD_PAGENUMS) != 0) ? TRUE : FALSE;
2574 }
2575
2576 BOOL PrintToFile() const // TRUE if printing to a file
2577 {
2578 return ((m_pdex.Flags & PD_PRINTTOFILE) != 0) ? TRUE : FALSE;
2579 }
2580
2581 LPDEVMODE GetDevMode() const // return DEVMODE
2582 {
2583 if(m_pdex.hDevMode == NULL)
2584 return NULL;
2585
2586 return (LPDEVMODE)::GlobalLock(m_pdex.hDevMode);
2587 }
2588
2589 LPCTSTR GetDriverName() const // return driver name
2590 {
2591 if(m_pdex.hDevNames == NULL)
2592 return NULL;
2593
2594 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2595 if(lpDev == NULL)
2596 return NULL;
2597
2598 return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2599 }
2600
2601 LPCTSTR GetDeviceName() const // return device name
2602 {
2603 if(m_pdex.hDevNames == NULL)
2604 return NULL;
2605
2606 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2607 if(lpDev == NULL)
2608 return NULL;
2609
2610 return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2611 }
2612
2613 LPCTSTR GetPortName() const // return output port name
2614 {
2615 if(m_pdex.hDevNames == NULL)
2616 return NULL;
2617
2618 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_pdex.hDevNames);
2619 if(lpDev == NULL)
2620 return NULL;
2621
2622 return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2623 }
2624
2625 HDC GetPrinterDC() const // return HDC (caller must delete)
2626 {
2627 ATLASSERT((m_pdex.Flags & PD_RETURNDC) != 0);
2628 return m_pdex.hDC;
2629 }
2630
2631 // This helper creates a DC based on the DEVNAMES and DEVMODE structures.
2632 // This DC is returned, but also stored in m_pdex.hDC as though it had been
2633 // returned by CommDlg. It is assumed that any previously obtained DC
2634 // has been/will be deleted by the user. This may be
2635 // used without ever invoking the print/print setup dialogs.
2636 HDC CreatePrinterDC()
2637 {
2638 m_pdex.hDC = _AtlCreateDC(m_pdex.hDevNames, m_pdex.hDevMode);
2639 return m_pdex.hDC;
2640 }
2641
2642 // Implementation - interfaces
2643
2644 // IUnknown
2645 STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject)
2646 {
2647 if(ppvObject == NULL)
2648 return E_POINTER;
2649
2650 T* pT = static_cast<T*>(this);
2651 if(IsEqualGUID(riid, IID_IUnknown) || IsEqualGUID(riid, IID_IPrintDialogCallback))
2652 {
2653 *ppvObject = (IPrintDialogCallback*)pT;
2654 // AddRef() not needed
2655 return S_OK;
2656 }
2657 else if(IsEqualGUID(riid, IID_IObjectWithSite))
2658 {
2659 *ppvObject = (IObjectWithSite*)pT;
2660 // AddRef() not needed
2661 return S_OK;
2662 }
2663
2664 return E_NOINTERFACE;
2665 }
2666
2667 virtual ULONG STDMETHODCALLTYPE AddRef()
2668 {
2669 return 1;
2670 }
2671
2672 virtual ULONG STDMETHODCALLTYPE Release()
2673 {
2674 return 1;
2675 }
2676
2677 // IPrintDialogCallback
2678 STDMETHOD(InitDone)()
2679 {
2680 return S_FALSE;
2681 }
2682
2683 STDMETHOD(SelectionChange)()
2684 {
2685 return S_FALSE;
2686 }
2687
2688 STDMETHOD(HandleMessage)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
2689 {
2690 // set up m_hWnd the first time
2691 if(m_hWnd == NULL)
2692 Attach(hWnd);
2693
2694 // call message map
2695 HRESULT hRet = ProcessWindowMessage(hWnd, uMsg, wParam, lParam, *plResult, 0) ? S_OK : S_FALSE;
2696 if(hRet == S_OK && uMsg == WM_NOTIFY) // return in DWLP_MSGRESULT
2697 ::SetWindowLongPtr(GetParent(), DWLP_MSGRESULT, (LONG_PTR)*plResult);
2698
2699 if(uMsg == WM_INITDIALOG && hRet == S_OK && (BOOL)*plResult != FALSE)
2700 hRet = S_FALSE;
2701
2702 return hRet;
2703 }
2704 };
2705
2706 class CPrintDialogEx : public CPrintDialogExImpl<CPrintDialogEx>
2707 {
2708 public:
2709 CPrintDialogEx(
2710 DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_NOSELECTION | PD_NOCURRENTPAGE,
2711 HWND hWndParent = NULL)
2712 : CPrintDialogExImpl<CPrintDialogEx>(dwFlags, hWndParent)
2713 { }
2714
2715 DECLARE_EMPTY_MSG_MAP()
2716 };
2717
2718 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
2719
2720
2721 ///////////////////////////////////////////////////////////////////////////////
2722 // CPageSetupDialogImpl - Page Setup dialog
2723
2724 #ifndef _WIN32_WCE
2725
2726 template <class T>
2727 class ATL_NO_VTABLE CPageSetupDialogImpl : public CCommonDialogImplBase
2728 {
2729 public:
2730 PAGESETUPDLG m_psd;
2731 ATL::CWndProcThunk m_thunkPaint;
2732
2733 // Constructors
2734 CPageSetupDialogImpl(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
2735 {
2736 memset(&m_psd, 0, sizeof(m_psd));
2737
2738 m_psd.lStructSize = sizeof(m_psd);
2739 m_psd.hwndOwner = hWndParent;
2740 m_psd.Flags = (dwFlags | PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK);
2741 m_psd.lpfnPageSetupHook = (LPPAGESETUPHOOK)T::HookProc;
2742 m_thunkPaint.Init((WNDPROC)T::PaintHookProc, this);
2743 #if (_ATL_VER >= 0x0700)
2744 m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)m_thunkPaint.GetWNDPROC();
2745 #else
2746 m_psd.lpfnPagePaintHook = (LPPAGEPAINTHOOK)&(m_thunkPaint.thunk);
2747 #endif
2748 }
2749
2750 DECLARE_EMPTY_MSG_MAP()
2751
2752 // Attributes
2753 LPDEVMODE GetDevMode() const // return DEVMODE
2754 {
2755 if(m_psd.hDevMode == NULL)
2756 return NULL;
2757
2758 return (LPDEVMODE)::GlobalLock(m_psd.hDevMode);
2759 }
2760
2761 LPCTSTR GetDriverName() const // return driver name
2762 {
2763 if(m_psd.hDevNames == NULL)
2764 return NULL;
2765
2766 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2767 return (LPCTSTR)lpDev + lpDev->wDriverOffset;
2768 }
2769
2770 LPCTSTR GetDeviceName() const // return device name
2771 {
2772 if(m_psd.hDevNames == NULL)
2773 return NULL;
2774
2775 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2776 return (LPCTSTR)lpDev + lpDev->wDeviceOffset;
2777 }
2778
2779 LPCTSTR GetPortName() const // return output port name
2780 {
2781 if(m_psd.hDevNames == NULL)
2782 return NULL;
2783
2784 LPDEVNAMES lpDev = (LPDEVNAMES)::GlobalLock(m_psd.hDevNames);
2785 return (LPCTSTR)lpDev + lpDev->wOutputOffset;
2786 }
2787
2788 HDC CreatePrinterDC()
2789 {
2790 return _AtlCreateDC(m_psd.hDevNames, m_psd.hDevMode);
2791 }
2792
2793 SIZE GetPaperSize() const
2794 {
2795 SIZE size = { m_psd.ptPaperSize.x, m_psd.ptPaperSize.y };
2796 return size;
2797 }
2798
2799 void GetMargins(LPRECT lpRectMargins, LPRECT lpRectMinMargins) const
2800 {
2801 if(lpRectMargins != NULL)
2802 *lpRectMargins = m_psd.rtMargin;
2803 if(lpRectMinMargins != NULL)
2804 *lpRectMinMargins = m_psd.rtMinMargin;
2805 }
2806
2807 // Operations
2808 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
2809 {
2810 ATLASSERT((m_psd.Flags & PSD_ENABLEPAGESETUPHOOK) != 0);
2811 ATLASSERT((m_psd.Flags & PSD_ENABLEPAGEPAINTHOOK) != 0);
2812 ATLASSERT(m_psd.lpfnPageSetupHook != NULL); // can still be a user hook
2813 ATLASSERT(m_psd.lpfnPagePaintHook != NULL); // can still be a user hook
2814
2815 if(m_psd.hwndOwner == NULL) // set only if not specified before
2816 m_psd.hwndOwner = hWndParent;
2817
2818 ATLASSERT(m_hWnd == NULL);
2819
2820 #if (_ATL_VER >= 0x0800)
2821 // Allocate the thunk structure here, where we can fail gracefully.
2822 BOOL bRetTh = m_thunk.Init(NULL, NULL);
2823 if(bRetTh == FALSE)
2824 {
2825 ::SetLastError(ERROR_OUTOFMEMORY);
2826 return -1;
2827 }
2828 #endif // (_ATL_VER >= 0x0800)
2829
2830 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2831
2832 BOOL bRet = ::PageSetupDlg(&m_psd);
2833
2834 m_hWnd = NULL;
2835
2836 return bRet ? IDOK : IDCANCEL;
2837 }
2838
2839 // Implementation
2840 static UINT_PTR CALLBACK PaintHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2841 {
2842 T* pT = (T*)hWnd;
2843 UINT_PTR uRet = 0;
2844 switch(uMsg)
2845 {
2846 case WM_PSD_PAGESETUPDLG:
2847 uRet = pT->PreDrawPage(LOWORD(wParam), HIWORD(wParam), (LPPAGESETUPDLG)lParam);
2848 break;
2849 case WM_PSD_FULLPAGERECT:
2850 case WM_PSD_MINMARGINRECT:
2851 case WM_PSD_MARGINRECT:
2852 case WM_PSD_GREEKTEXTRECT:
2853 case WM_PSD_ENVSTAMPRECT:
2854 case WM_PSD_YAFULLPAGERECT:
2855 uRet = pT->OnDrawPage(uMsg, (HDC)wParam, (LPRECT)lParam);
2856 break;
2857 default:
2858 ATLTRACE2(atlTraceUI, 0, _T("CPageSetupDialogImpl::PaintHookProc - unknown message received\n"));
2859 break;
2860 }
2861 return uRet;
2862 }
2863
2864 // Overridables
2865 UINT_PTR PreDrawPage(WORD /*wPaper*/, WORD /*wFlags*/, LPPAGESETUPDLG /*pPSD*/)
2866 {
2867 // return 1 to prevent any more drawing
2868 return 0;
2869 }
2870
2871 UINT_PTR OnDrawPage(UINT /*uMsg*/, HDC /*hDC*/, LPRECT /*lpRect*/)
2872 {
2873 return 0; // do the default
2874 }
2875 };
2876
2877 class CPageSetupDialog : public CPageSetupDialogImpl<CPageSetupDialog>
2878 {
2879 public:
2880 CPageSetupDialog(DWORD dwFlags = PSD_MARGINS | PSD_INWININIINTLMEASURE, HWND hWndParent = NULL)
2881 : CPageSetupDialogImpl<CPageSetupDialog>(dwFlags, hWndParent)
2882 { }
2883
2884 // override PaintHookProc and references to handlers
2885 static UINT_PTR CALLBACK PaintHookProc(HWND, UINT, WPARAM, LPARAM)
2886 {
2887 return 0;
2888 }
2889 };
2890
2891 #endif // _WIN32_WCE
2892
2893
2894 ///////////////////////////////////////////////////////////////////////////////
2895 // CFindReplaceDialogImpl - Find/FindReplace modeless dialogs
2896
2897 #ifndef _WIN32_WCE
2898
2899 template <class T>
2900 class ATL_NO_VTABLE CFindReplaceDialogImpl : public CCommonDialogImplBase
2901 {
2902 public:
2903 enum { _cchFindReplaceBuffer = 128 };
2904
2905 FINDREPLACE m_fr;
2906 TCHAR m_szFindWhat[_cchFindReplaceBuffer];
2907 TCHAR m_szReplaceWith[_cchFindReplaceBuffer];
2908
2909 // Constructors
2910 CFindReplaceDialogImpl()
2911 {
2912 memset(&m_fr, 0, sizeof(m_fr));
2913 m_szFindWhat[0] = _T('\0');
2914 m_szReplaceWith[0] = _T('\0');
2915
2916 m_fr.lStructSize = sizeof(m_fr);
2917 m_fr.Flags = FR_ENABLEHOOK;
2918 m_fr.lpfnHook = (LPFRHOOKPROC)T::HookProc;
2919 m_fr.lpstrFindWhat = (LPTSTR)m_szFindWhat;
2920 m_fr.wFindWhatLen = _cchFindReplaceBuffer;
2921 m_fr.lpstrReplaceWith = (LPTSTR)m_szReplaceWith;
2922 m_fr.wReplaceWithLen = _cchFindReplaceBuffer;
2923 }
2924
2925 // Note: You must allocate the object on the heap.
2926 // If you do not, you must override OnFinalMessage()
2927 virtual void OnFinalMessage(HWND /*hWnd*/)
2928 {
2929 delete this;
2930 }
2931
2932 HWND Create(BOOL bFindDialogOnly, // TRUE for Find, FALSE for FindReplace
2933 LPCTSTR lpszFindWhat,
2934 LPCTSTR lpszReplaceWith = NULL,
2935 DWORD dwFlags = FR_DOWN,
2936 HWND hWndParent = NULL)
2937 {
2938 ATLASSERT((m_fr.Flags & FR_ENABLEHOOK) != 0);
2939 ATLASSERT(m_fr.lpfnHook != NULL);
2940
2941 m_fr.Flags |= dwFlags;
2942
2943 if(hWndParent == NULL)
2944 m_fr.hwndOwner = ::GetActiveWindow();
2945 else
2946 m_fr.hwndOwner = hWndParent;
2947 ATLASSERT(m_fr.hwndOwner != NULL); // must have an owner for modeless dialog
2948
2949 if(lpszFindWhat != NULL)
2950 SecureHelper::strncpy_x(m_szFindWhat, _countof(m_szFindWhat), lpszFindWhat, _TRUNCATE);
2951
2952 if(lpszReplaceWith != NULL)
2953 SecureHelper::strncpy_x(m_szReplaceWith, _countof(m_szReplaceWith), lpszReplaceWith, _TRUNCATE);
2954
2955 ATLASSERT(m_hWnd == NULL);
2956
2957 #if (_ATL_VER >= 0x0800)
2958 // Allocate the thunk structure here, where we can fail gracefully.
2959 BOOL bRet = m_thunk.Init(NULL, NULL);
2960 if(bRet == FALSE)
2961 {
2962 ::SetLastError(ERROR_OUTOFMEMORY);
2963 return NULL;
2964 }
2965 #endif // (_ATL_VER >= 0x0800)
2966
2967 ModuleHelper::AddCreateWndData(&m_thunk.cd, (CCommonDialogImplBase*)this);
2968
2969 HWND hWnd = NULL;
2970 if(bFindDialogOnly)
2971 hWnd = ::FindText(&m_fr);
2972 else
2973 hWnd = ::ReplaceText(&m_fr);
2974
2975 ATLASSERT(m_hWnd == hWnd);
2976 return hWnd;
2977 }
2978
2979 static const UINT GetFindReplaceMsg()
2980 {
2981 static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
2982 return nMsgFindReplace;
2983 }
2984 // call while handling FINDMSGSTRING registered message
2985 // to retreive the object
2986 static T* PASCAL GetNotifier(LPARAM lParam)
2987 {
2988 ATLASSERT(lParam != NULL);
2989 T* pDlg = (T*)(lParam - offsetof(T, m_fr));
2990 return pDlg;
2991 }
2992
2993 // Operations
2994 // Helpers for parsing information after successful return
2995 LPCTSTR GetFindString() const // get find string
2996 {
2997 return (LPCTSTR)m_fr.lpstrFindWhat;
2998 }
2999
3000 LPCTSTR GetReplaceString() const // get replacement string
3001 {
3002 return (LPCTSTR)m_fr.lpstrReplaceWith;
3003 }
3004
3005 BOOL SearchDown() const // TRUE if search down, FALSE is up
3006 {
3007 return ((m_fr.Flags & FR_DOWN) != 0) ? TRUE : FALSE;
3008 }
3009
3010 BOOL FindNext() const // TRUE if command is find next
3011 {
3012 return ((m_fr.Flags & FR_FINDNEXT) != 0) ? TRUE : FALSE;
3013 }
3014
3015 BOOL MatchCase() const // TRUE if matching case
3016 {
3017 return ((m_fr.Flags & FR_MATCHCASE) != 0) ? TRUE : FALSE;
3018 }
3019
3020 BOOL MatchWholeWord() const // TRUE if matching whole words only
3021 {
3022 return ((m_fr.Flags & FR_WHOLEWORD) != 0) ? TRUE : FALSE;
3023 }
3024
3025 BOOL ReplaceCurrent() const // TRUE if replacing current string
3026 {
3027 return ((m_fr. Flags & FR_REPLACE) != 0) ? TRUE : FALSE;
3028 }
3029
3030 BOOL ReplaceAll() const // TRUE if replacing all occurrences
3031 {
3032 return ((m_fr.Flags & FR_REPLACEALL) != 0) ? TRUE : FALSE;
3033 }
3034
3035 BOOL IsTerminating() const // TRUE if terminating dialog
3036 {
3037 return ((m_fr.Flags & FR_DIALOGTERM) != 0) ? TRUE : FALSE ;
3038 }
3039 };
3040
3041 class CFindReplaceDialog : public CFindReplaceDialogImpl<CFindReplaceDialog>
3042 {
3043 public:
3044 DECLARE_EMPTY_MSG_MAP()
3045 };
3046
3047 #endif // !_WIN32_WCE
3048
3049
3050 /////////////////////////////////////////////////////////////////////////
3051 // CDialogBaseUnits - Dialog Units helper
3052 //
3053
3054 class CDialogBaseUnits
3055 {
3056 public:
3057 SIZE m_sizeUnits;
3058
3059 // Constructors
3060 CDialogBaseUnits()
3061 {
3062 // The base units of the out-dated System Font
3063 LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3064 m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3065 m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3066 }
3067
3068 CDialogBaseUnits(HWND hWnd)
3069 {
3070 if(!InitDialogBaseUnits(hWnd)) {
3071 LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3072 m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3073 m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3074 }
3075 }
3076
3077 CDialogBaseUnits(HFONT hFont, HWND hWnd = NULL)
3078 {
3079 if(!InitDialogBaseUnits(hFont, hWnd)) {
3080 LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3081 m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3082 m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3083 }
3084 }
3085
3086 CDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL)
3087 {
3088 if(!InitDialogBaseUnits(lf, hWnd)) {
3089 LONG nDlgBaseUnits = ::GetDialogBaseUnits();
3090 m_sizeUnits.cx = LOWORD(nDlgBaseUnits);
3091 m_sizeUnits.cy = HIWORD(nDlgBaseUnits);
3092 }
3093 }
3094
3095 // Operations
3096 BOOL InitDialogBaseUnits(HWND hWnd)
3097 {
3098 ATLASSERT(::IsWindow(hWnd));
3099 RECT rc = { 0, 0, 4, 8 };
3100 if(!::MapDialogRect(hWnd, &rc)) return FALSE;
3101 m_sizeUnits.cx = rc.right;
3102 m_sizeUnits.cy = rc.bottom;
3103 return TRUE;
3104 }
3105
3106 BOOL InitDialogBaseUnits(LOGFONT lf, HWND hWnd = NULL)
3107 {
3108 CFont font;
3109 font.CreateFontIndirect(&lf);
3110 if(font.IsNull()) return FALSE;
3111 return InitDialogBaseUnits(font, hWnd);
3112 }
3113
3114 BOOL InitDialogBaseUnits(HFONT hFont, HWND hWnd = NULL)
3115 {
3116 ATLASSERT(hFont != NULL);
3117 CWindowDC dc = hWnd;
3118 TEXTMETRIC tmText = { 0 };
3119 SIZE sizeText = { 0 };
3120 HFONT hFontOld = dc.SelectFont(hFont);
3121 dc.GetTextMetrics(&tmText);
3122 m_sizeUnits.cy = tmText.tmHeight + tmText.tmExternalLeading;
3123 dc.GetTextExtent(_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &sizeText);
3124 m_sizeUnits.cx = (sizeText.cx + 26) / 52;
3125 dc.SelectFont(hFontOld);
3126 return TRUE;
3127 }
3128
3129 SIZE GetDialogBaseUnits() const
3130 {
3131 return m_sizeUnits;
3132 }
3133
3134 INT MapDialogPixelsX(INT x) const
3135 {
3136 return ::MulDiv(x, 4, m_sizeUnits.cx); // Pixels X to DLU
3137 }
3138
3139 INT MapDialogPixelsY(INT y) const
3140 {
3141 return ::MulDiv(y, 8, m_sizeUnits.cy); // Pixels Y to DLU
3142 }
3143
3144 POINT MapDialogPixels(POINT pt) const
3145 {
3146 POINT out = { MapDialogPixelsX(pt.x), MapDialogPixelsY(pt.y) };
3147 return out;
3148 }
3149
3150 SIZE MapDialogPixels(SIZE input) const
3151 {
3152 SIZE out = { MapDialogPixelsX(input.cx), MapDialogPixelsY(input.cy) };
3153 return out;
3154 }
3155
3156 RECT MapDialogPixels(const RECT& input) const
3157 {
3158 RECT out = { MapDialogPixelsX(input.left), MapDialogPixelsY(input.top), MapDialogPixelsX(input.right), MapDialogPixelsY(input.bottom) };
3159 return out;
3160 }
3161
3162 INT MapDialogUnitsX(INT x) const
3163 {
3164 return ::MulDiv(x, m_sizeUnits.cx, 4); // DLU to Pixels X
3165 }
3166
3167 INT MapDialogUnitsY(INT y) const
3168 {
3169 return ::MulDiv(y, m_sizeUnits.cy, 8); // DLU to Pixels Y
3170 }
3171
3172 POINT MapDialogUnits(POINT pt) const
3173 {
3174 POINT out = { MapDialogUnitsX(pt.x), MapDialogUnitsY(pt.y) };
3175 return out;
3176 }
3177
3178 SIZE MapDialogUnits(SIZE input) const
3179 {
3180 SIZE out = { MapDialogUnitsX(input.cx), MapDialogUnitsY(input.cy) };
3181 return out;
3182 }
3183
3184 RECT MapDialogUnits(const RECT& input) const
3185 {
3186 RECT out = { MapDialogUnitsX(input.left), MapDialogUnitsY(input.top), MapDialogUnitsX(input.right), MapDialogUnitsY(input.bottom) };
3187 return out;
3188 }
3189 };
3190
3191
3192 ///////////////////////////////////////////////////////////////////////////////
3193 // CMemDlgTemplate - in-memory dialog template - DLGTEMPLATE or DLGTEMPLATEEX
3194
3195 #if (_ATL_VER >= 0x800)
3196 typedef ATL::_DialogSplitHelper::DLGTEMPLATEEX DLGTEMPLATEEX;
3197 typedef ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX DLGITEMTEMPLATEEX;
3198 #else // (_ATL_VER >= 0x800)
3199 typedef ATL::_DialogSizeHelper::_ATL_DLGTEMPLATEEX DLGTEMPLATEEX;
3200 #pragma pack(push, 4)
3201 struct DLGITEMTEMPLATEEX
3202 {
3203 DWORD helpID;
3204 DWORD exStyle;
3205 DWORD style;
3206 short x;
3207 short y;
3208 short cx;
3209 short cy;
3210 DWORD id;
3211 };
3212 #pragma pack(pop)
3213 #endif // (_ATL_VER >= 0x800)
3214
3215
3216 template <class TWinTraits>
3217 class CMemDlgTemplateT
3218 {
3219 public:
3220 enum StdCtrlType
3221 {
3222 CTRL_BUTTON = 0x0080,
3223 CTRL_EDIT = 0x0081,
3224 CTRL_STATIC = 0x0082,
3225 CTRL_LISTBOX = 0x0083,
3226 CTRL_SCROLLBAR = 0x0084,
3227 CTRL_COMBOBOX = 0x0085
3228 };
3229
3230 HANDLE m_hData;
3231 LPBYTE m_pData;
3232 LPBYTE m_pPtr;
3233 SIZE_T m_cAllocated;
3234
3235 CMemDlgTemplateT() : m_hData(NULL), m_pData(NULL), m_pPtr(NULL), m_cAllocated(0)
3236 { }
3237
3238 ~CMemDlgTemplateT()
3239 {
3240 Reset();
3241 }
3242
3243 bool IsValid() const
3244 {
3245 return (m_pData != NULL);
3246 }
3247
3248 bool IsTemplateEx() const
3249 {
3250 return (IsValid() && ((DLGTEMPLATEEX*)m_pData)->signature == 0xFFFF);
3251 }
3252
3253 LPDLGTEMPLATE GetTemplatePtr()
3254 {
3255 return reinterpret_cast<LPDLGTEMPLATE>(m_pData);
3256 }
3257
3258 DLGTEMPLATEEX* GetTemplateExPtr()
3259 {
3260 return reinterpret_cast<DLGTEMPLATEEX*>(m_pData);
3261 }
3262
3263 void Reset()
3264 {
3265 if (IsValid()) {
3266 #ifndef UNDER_CE
3267 ::GlobalUnlock(m_pData);
3268 #endif
3269 ATLVERIFY(::GlobalFree(m_hData) == NULL);
3270 }
3271
3272 m_hData = NULL;
3273 m_pData = NULL;
3274 m_pPtr = NULL;
3275 m_cAllocated = 0;
3276 }
3277
3278 void Create(bool bDlgEx, LPCTSTR lpszCaption, const RECT& rc, DWORD dwStyle = 0, DWORD dwExStyle = 0,
3279 LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
3280 ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
3281 {
3282 Create(bDlgEx, lpszCaption, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle,
3283 lpstrFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName.m_lpstr, Menu.m_lpstr);
3284 }
3285
3286 void Create(bool bDlgEx, LPCTSTR lpszCaption, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle = 0, DWORD dwExStyle = 0,
3287 LPCTSTR lpstrFontName = NULL, WORD wFontSize = 0, WORD wWeight = 0, BYTE bItalic = 0, BYTE bCharset = 0, DWORD dwHelpID = 0,
3288 ATL::_U_STRINGorID ClassName = 0U, ATL::_U_STRINGorID Menu = 0U)
3289 {
3290 // Should have DS_SETFONT style to set the dialog font name and size
3291 if (lpstrFontName != NULL)
3292 {
3293 dwStyle |= DS_SETFONT;
3294 }
3295 else
3296 {
3297 dwStyle &= ~DS_SETFONT;
3298 }
3299
3300 if (bDlgEx)
3301 {
3302 DLGTEMPLATEEX dlg = {1, 0xFFFF, dwHelpID, dwExStyle, dwStyle, 0, nX, nY, nWidth, nHeight};
3303 AddData(&dlg, sizeof(dlg));
3304 }
3305 else
3306 {
3307 DLGTEMPLATE dlg = {dwStyle, dwExStyle, 0, nX, nY, nWidth, nHeight};
3308 AddData(&dlg, sizeof(dlg));
3309 }
3310
3311 #ifndef _WIN32_WCE
3312 if (Menu.m_lpstr == NULL)
3313 {
3314 WORD menuData = 0;
3315 AddData(&menuData, sizeof(WORD));
3316 }
3317 else if (IS_INTRESOURCE(Menu.m_lpstr))
3318 {
3319 WORD menuData[] = { 0xFFFF, LOWORD(Menu.m_lpstr) };
3320 AddData(menuData, sizeof(menuData));
3321 }
3322 else
3323 {
3324 AddString(Menu.m_lpstr);
3325 }
3326 #else // _WIN32_WCE
3327 // Windows CE doesn't support the addition of menus to a dialog box
3328 ATLASSERT(Menu.m_lpstr == NULL);
3329 Menu.m_lpstr; // avoid level 4 warning
3330 WORD menuData = 0;
3331 AddData(&menuData, sizeof(WORD));
3332 #endif // _WIN32_WCE
3333
3334 if (ClassName.m_lpstr == NULL)
3335 {
3336 WORD classData = 0;
3337 AddData(&classData, sizeof(WORD));
3338 }
3339 else if (IS_INTRESOURCE(ClassName.m_lpstr))
3340 {
3341 WORD classData[] = { 0xFFFF, LOWORD(ClassName.m_lpstr) };
3342 AddData(classData, sizeof(classData));
3343 }
3344 else
3345 {
3346 AddString(ClassName.m_lpstr);
3347 }
3348
3349 // Set dialog caption
3350 AddString(lpszCaption);
3351
3352 if (lpstrFontName != NULL)
3353 {
3354 AddData(&wFontSize, sizeof(wFontSize));
3355
3356 if (bDlgEx)
3357 {
3358 AddData(&wWeight, sizeof(wWeight));
3359 AddData(&bItalic, sizeof(bItalic));
3360 AddData(&bCharset, sizeof(bCharset));
3361 }
3362
3363 AddString(lpstrFontName);
3364 }
3365 }
3366
3367 void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, const RECT& rc, DWORD dwStyle, DWORD dwExStyle,
3368 ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3369 {
3370 AddControl(ClassName.m_lpstr, wId, (short) rc.left, (short) rc.top, (short) (rc.right - rc.left), (short) (rc.bottom - rc.top), dwStyle, dwExStyle,
3371 Text.m_lpstr, pCreationData, nCreationData, dwHelpID);
3372 }
3373
3374 void AddControl(ATL::_U_STRINGorID ClassName, WORD wId, short nX, short nY, short nWidth, short nHeight, DWORD dwStyle, DWORD dwExStyle,
3375 ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3376 {
3377 ATLASSERT(IsValid());
3378
3379 // DWORD align data
3380 const DWORD_PTR dwDwordAlignBits = sizeof(DWORD) - 1;
3381 m_pPtr = (LPBYTE)(((DWORD_PTR)m_pPtr + dwDwordAlignBits) & (~dwDwordAlignBits));
3382
3383 if (IsTemplateEx())
3384 {
3385 DLGTEMPLATEEX* dlg = (DLGTEMPLATEEX*)m_pData;
3386 dlg->cDlgItems++;
3387
3388 DLGITEMTEMPLATEEX item = {dwHelpID, TWinTraits::GetWndExStyle(0) | dwExStyle, TWinTraits::GetWndStyle(0) | dwStyle, nX, nY, nWidth, nHeight, wId};
3389 AddData(&item, sizeof(item));
3390 }
3391 else
3392 {
3393 LPDLGTEMPLATE dlg = (LPDLGTEMPLATE)m_pData;
3394 dlg->cdit++;
3395
3396 DLGITEMTEMPLATE item = {TWinTraits::GetWndStyle(0) | dwStyle, TWinTraits::GetWndExStyle(0) | dwExStyle, nX, nY, nWidth, nHeight, wId};
3397 AddData(&item, sizeof(item));
3398 }
3399
3400 ATLASSERT(ClassName.m_lpstr != NULL);
3401 if (IS_INTRESOURCE(ClassName.m_lpstr))
3402 {
3403 WORD wData[] = { 0xFFFF, LOWORD(ClassName.m_lpstr) };
3404 AddData(wData, sizeof(wData));
3405 }
3406 else
3407 {
3408 AddString(ClassName.m_lpstr);
3409 }
3410
3411 if (Text.m_lpstr == NULL)
3412 {
3413 WORD classData = 0;
3414 AddData(&classData, sizeof(WORD));
3415 }
3416 else if (IS_INTRESOURCE(Text.m_lpstr))
3417 {
3418 WORD wData[] = { 0xFFFF, LOWORD(Text.m_lpstr) };
3419 AddData(wData, sizeof(wData));
3420 }
3421 else
3422 {
3423 AddString(Text.m_lpstr);
3424 }
3425
3426 AddData(&nCreationData, sizeof(nCreationData));
3427
3428 if ((nCreationData != 0))
3429 {
3430 ATLASSERT(pCreationData != NULL);
3431 AddData(pCreationData, nCreationData * sizeof(WORD));
3432 }
3433 }
3434
3435 void AddStdControl(StdCtrlType CtrlType, WORD wId, short nX, short nY, short nWidth, short nHeight,
3436 DWORD dwStyle, DWORD dwExStyle, ATL::_U_STRINGorID Text, const WORD* pCreationData = NULL, WORD nCreationData = 0, DWORD dwHelpID = 0)
3437 {
3438 AddControl(CtrlType, wId, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, Text, pCreationData, nCreationData, dwHelpID);
3439 }
3440
3441 void AddData(LPCVOID pData, size_t nData)
3442 {
3443 ATLASSERT(pData != NULL);
3444
3445 const SIZE_T ALLOCATION_INCREMENT = 1024;
3446
3447 if (m_pData == NULL)
3448 {
3449 m_cAllocated = ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
3450 m_hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, m_cAllocated);
3451 ATLASSERT(m_hData != NULL);
3452 #ifndef UNDER_CE
3453 m_pPtr = m_pData = static_cast<LPBYTE>(::GlobalLock(m_hData));
3454 #else
3455 m_pPtr = m_pData = static_cast<LPBYTE>(m_hData);
3456 #endif
3457 ATLASSERT(m_pData != NULL);
3458 }
3459 else if (((m_pPtr - m_pData) + nData) > m_cAllocated)
3460 {
3461 SIZE_T ptrPos = (m_pPtr - m_pData);
3462 m_cAllocated += ((nData / ALLOCATION_INCREMENT) + 1) * ALLOCATION_INCREMENT;
3463 #ifndef UNDER_CE
3464 ::GlobalUnlock(m_pData);
3465 #endif
3466 m_hData = ::GlobalReAlloc(m_hData, m_cAllocated, GMEM_MOVEABLE | GMEM_ZEROINIT);
3467 ATLASSERT(m_hData != NULL);
3468 #ifndef UNDER_CE
3469 m_pData = static_cast<LPBYTE>(::GlobalLock(m_hData));
3470 #else
3471 m_pData = static_cast<LPBYTE>(m_hData);
3472 #endif
3473 ATLASSERT(m_pData != NULL);
3474 m_pPtr = m_pData + ptrPos;
3475 }
3476
3477 SecureHelper::memcpy_x(m_pPtr, m_cAllocated - (m_pPtr - m_pData), pData, nData);
3478
3479 m_pPtr += nData;
3480 }
3481
3482 void AddString(LPCTSTR lpszStr)
3483 {
3484 if (lpszStr == NULL)
3485 {
3486 WCHAR szEmpty = 0;
3487 AddData(&szEmpty, sizeof(szEmpty));
3488 }
3489 else
3490 {
3491 USES_CONVERSION;
3492 LPCWSTR lpstr = T2CW(lpszStr);
3493 int nSize = lstrlenW(lpstr) + 1;
3494 AddData(lpstr, nSize * sizeof(WCHAR));
3495 }
3496 }
3497 };
3498
3499 typedef CMemDlgTemplateT<ATL::CControlWinTraits> CMemDlgTemplate;
3500
3501
3502 ///////////////////////////////////////////////////////////////////////////////
3503 // Dialog and control macros for indirect dialogs
3504
3505 // for DLGTEMPLATE
3506 #define BEGIN_DIALOG(x, y, width, height) \
3507 void DoInitTemplate() \
3508 { \
3509 bool bExTemplate = false; \
3510 short nX = x, nY = y, nWidth = width, nHeight = height; \
3511 LPCTSTR szCaption = NULL; \
3512 DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
3513 DWORD dwExStyle = 0; \
3514 LPCTSTR szFontName = NULL; \
3515 WORD wFontSize = 0; \
3516 WORD wWeight = 0; \
3517 BYTE bItalic = 0; \
3518 BYTE bCharset = 0; \
3519 DWORD dwHelpID = 0; \
3520 ATL::_U_STRINGorID Menu = 0U; \
3521 ATL::_U_STRINGorID ClassName = 0U;
3522
3523 // for DLGTEMPLATEEX
3524 #define BEGIN_DIALOG_EX(x, y, width, height, helpID) \
3525 void DoInitTemplate() \
3526 { \
3527 bool bExTemplate = true; \
3528 short nX = x, nY = y, nWidth = width, nHeight = height; \
3529 LPCTSTR szCaption = NULL; \
3530 DWORD dwStyle = WS_POPUP | WS_BORDER | WS_SYSMENU; \
3531 DWORD dwExStyle = 0; \
3532 LPCTSTR szFontName = NULL; \
3533 WORD wFontSize = 0; \
3534 WORD wWeight = 0; \
3535 BYTE bItalic = 0; \
3536 BYTE bCharset = 0; \
3537 DWORD dwHelpID = helpID; \
3538 ATL::_U_STRINGorID Menu = 0U; \
3539 ATL::_U_STRINGorID ClassName = 0U;
3540
3541 #define END_DIALOG() \
3542 m_Template.Create(bExTemplate, szCaption, nX, nY, nWidth, nHeight, dwStyle, dwExStyle, szFontName, wFontSize, wWeight, bItalic, bCharset, dwHelpID, ClassName, Menu); \
3543 };
3544
3545 #define DIALOG_CAPTION(caption) \
3546 szCaption = caption;
3547 #define DIALOG_STYLE(style) \
3548 dwStyle = style;
3549 #define DIALOG_EXSTYLE(exStyle) \
3550 dwExStyle = exStyle;
3551 #define DIALOG_FONT(pointSize, typeFace) \
3552 wFontSize = pointSize; \
3553 szFontName = typeFace;
3554 #define DIALOG_FONT_EX(pointsize, typeface, weight, italic, charset) \
3555 ATLASSERT(bExTemplate); \
3556 wFontSize = pointsize; \
3557 szFontName = typeface; \
3558 wWeight = weight; \
3559 bItalic = italic; \
3560 bCharset = charset;
3561 #define DIALOG_MENU(menuName) \
3562 Menu = menuName;
3563 #define DIALOG_CLASS(className) \
3564 ClassName = className;
3565
3566 #define BEGIN_CONTROLS_MAP() \
3567 void DoInitControls() \
3568 {
3569
3570 #define END_CONTROLS_MAP() \
3571 };
3572
3573
3574 #define CONTROL_LTEXT(text, id, x, y, width, height, style, exStyle) \
3575 m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_LEFT | WS_GROUP, exStyle, text, NULL, 0);
3576 #define CONTROL_CTEXT(text, id, x, y, width, height, style, exStyle) \
3577 m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_CENTER | WS_GROUP, exStyle, text, NULL, 0);
3578 #define CONTROL_RTEXT(text, id, x, y, width, height, style, exStyle) \
3579 m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_RIGHT | WS_GROUP, exStyle, text, NULL, 0);
3580 #define CONTROL_PUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
3581 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3582 #define CONTROL_DEFPUSHBUTTON(text, id, x, y, width, height, style, exStyle) \
3583 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_DEFPUSHBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3584 #ifndef _WIN32_WCE
3585 #define CONTROL_PUSHBOX(text, id, x, y, width, height, style, exStyle) \
3586 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_PUSHBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3587 #endif // !_WIN32_WCE
3588 #define CONTROL_STATE3(text, id, x, y, width, height, style, exStyle) \
3589 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
3590 #define CONTROL_AUTO3STATE(text, id, x, y, width, height, style, exStyle) \
3591 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTO3STATE | WS_TABSTOP, exStyle, text, NULL, 0);
3592 #define CONTROL_CHECKBOX(text, id, x, y, width, height, style, exStyle) \
3593 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_CHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3594 #define CONTROL_AUTOCHECKBOX(text, id, x, y, width, height, style, exStyle) \
3595 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTOCHECKBOX | WS_TABSTOP, exStyle, text, NULL, 0);
3596 #define CONTROL_RADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
3597 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_RADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3598 #define CONTROL_AUTORADIOBUTTON(text, id, x, y, width, height, style, exStyle) \
3599 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_AUTORADIOBUTTON | WS_TABSTOP, exStyle, text, NULL, 0);
3600 #define CONTROL_COMBOBOX(id, x, y, width, height, style, exStyle) \
3601 m_Template.AddStdControl(m_Template.CTRL_COMBOBOX, (WORD)id, x, y, width, height, style | CBS_DROPDOWN | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
3602 #define CONTROL_EDITTEXT(id, x, y, width, height, style, exStyle) \
3603 m_Template.AddStdControl(m_Template.CTRL_EDIT, (WORD)id, x, y, width, height, style | ES_LEFT | WS_BORDER | WS_TABSTOP, exStyle, (LPCTSTR)NULL, NULL, 0);
3604 #define CONTROL_GROUPBOX(text, id, x, y, width, height, style, exStyle) \
3605 m_Template.AddStdControl(m_Template.CTRL_BUTTON, (WORD)id, x, y, width, height, style | BS_GROUPBOX, exStyle, text, NULL, 0);
3606 #define CONTROL_LISTBOX(id, x, y, width, height, style, exStyle) \
3607 m_Template.AddStdControl(m_Template.CTRL_LISTBOX, (WORD)id, x, y, width, height, style | LBS_NOTIFY | WS_BORDER, exStyle, (LPCTSTR)NULL, NULL, 0);
3608 #define CONTROL_SCROLLBAR(id, x, y, width, height, style, exStyle) \
3609 m_Template.AddStdControl(m_Template.CTRL_SCROLLBAR, (WORD)id, x, y, width, height, style | SBS_HORZ, exStyle, (LPCTSTR)NULL, NULL, 0);
3610 #define CONTROL_ICON(text, id, x, y, width, height, style, exStyle) \
3611 m_Template.AddStdControl(m_Template.CTRL_STATIC, (WORD)id, x, y, width, height, style | SS_ICON, exStyle, text, NULL, 0);
3612 #define CONTROL_CONTROL(text, id, className, style, x, y, width, height, exStyle) \
3613 m_Template.AddControl(className, (WORD)id, x, y, width, height, style, exStyle, text, NULL, 0);
3614
3615
3616 ///////////////////////////////////////////////////////////////////////////////
3617 // CIndirectDialogImpl - dialogs with template in memory
3618
3619 template <class T, class TDlgTemplate = CMemDlgTemplate, class TBase = ATL::CWindow>
3620 class ATL_NO_VTABLE CIndirectDialogImpl : public ATL::CDialogImpl< T, TBase >
3621 {
3622 public:
3623 enum { IDD = 0 }; // no dialog template resource
3624
3625 TDlgTemplate m_Template;
3626
3627 void CreateTemplate()
3628 {
3629 T* pT = static_cast<T*>(this);
3630 pT->DoInitTemplate();
3631 pT->DoInitControls();
3632 }
3633
3634 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
3635 {
3636 T* pT = static_cast<T*>(this);
3637 ATLASSERT(pT->m_hWnd == NULL);
3638
3639 if(!m_Template.IsValid())
3640 CreateTemplate();
3641
3642 #if (_ATL_VER >= 0x0800)
3643 // Allocate the thunk structure here, where we can fail gracefully.
3644 BOOL bRet = m_thunk.Init(NULL, NULL);
3645 if(bRet == FALSE)
3646 {
3647 ::SetLastError(ERROR_OUTOFMEMORY);
3648 return -1;
3649 }
3650 #endif // (_ATL_VER >= 0x0800)
3651
3652 ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBaseT< TBase >*)pT);
3653
3654 #ifdef _DEBUG
3655 m_bModal = true;
3656 #endif // _DEBUG
3657
3658 return ::DialogBoxIndirectParam(ModuleHelper::GetResourceInstance(), m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
3659 }
3660
3661 HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
3662 {
3663 T* pT = static_cast<T*>(this);
3664 ATLASSERT(pT->m_hWnd == NULL);
3665
3666 if(!m_Template.IsValid())
3667 CreateTemplate();
3668
3669 #if (_ATL_VER >= 0x0800)
3670 // Allocate the thunk structure here, where we can fail gracefully.
3671 BOOL bRet = m_thunk.Init(NULL, NULL);
3672 if(bRet == FALSE)
3673 {
3674 ::SetLastError(ERROR_OUTOFMEMORY);
3675 return NULL;
3676 }
3677 #endif // (_ATL_VER >= 0x0800)
3678
3679 ModuleHelper::AddCreateWndData(&m_thunk.cd, (ATL::CDialogImplBaseT< TBase >*)pT);
3680
3681 #ifdef _DEBUG
3682 m_bModal = false;
3683 #endif // _DEBUG
3684
3685 HWND hWnd = ::CreateDialogIndirectParam(ModuleHelper::GetResourceInstance(), (LPCDLGTEMPLATE)m_Template.GetTemplatePtr(), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
3686 ATLASSERT(m_hWnd == hWnd);
3687
3688 return hWnd;
3689 }
3690
3691 // for CComControl
3692 HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
3693 {
3694 return Create(hWndParent, dwInitParam);
3695 }
3696
3697 void DoInitTemplate()
3698 {
3699 ATLASSERT(FALSE); // MUST be defined in derived class
3700 }
3701
3702 void DoInitControls()
3703 {
3704 ATLASSERT(FALSE); // MUST be defined in derived class
3705 }
3706 };
3707
3708
3709 ///////////////////////////////////////////////////////////////////////////////
3710 // CPropertySheetWindow - client side for a property sheet
3711
3712 class CPropertySheetWindow : public ATL::CWindow
3713 {
3714 public:
3715 // Constructors
3716 CPropertySheetWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
3717 { }
3718
3719 CPropertySheetWindow& operator =(HWND hWnd)
3720 {
3721 m_hWnd = hWnd;
3722 return *this;
3723 }
3724
3725 // Attributes
3726 int GetPageCount() const
3727 {
3728 ATLASSERT(::IsWindow(m_hWnd));
3729 HWND hWndTabCtrl = GetTabControl();
3730 ATLASSERT(hWndTabCtrl != NULL);
3731 return (int)::SendMessage(hWndTabCtrl, TCM_GETITEMCOUNT, 0, 0L);
3732 }
3733
3734 HWND GetActivePage() const
3735 {
3736 ATLASSERT(::IsWindow(m_hWnd));
3737 return (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0L);
3738 }
3739
3740 int GetActiveIndex() const
3741 {
3742 ATLASSERT(::IsWindow(m_hWnd));
3743 HWND hWndTabCtrl = GetTabControl();
3744 ATLASSERT(hWndTabCtrl != NULL);
3745 return (int)::SendMessage(hWndTabCtrl, TCM_GETCURSEL, 0, 0L);
3746 }
3747
3748 BOOL SetActivePage(int nPageIndex)
3749 {
3750 ATLASSERT(::IsWindow(m_hWnd));
3751 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, nPageIndex, 0L);
3752 }
3753
3754 BOOL SetActivePage(HPROPSHEETPAGE hPage)
3755 {
3756 ATLASSERT(::IsWindow(m_hWnd));
3757 ATLASSERT(hPage != NULL);
3758 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSEL, 0, (LPARAM)hPage);
3759 }
3760
3761 BOOL SetActivePageByID(int nPageID)
3762 {
3763 ATLASSERT(::IsWindow(m_hWnd));
3764 return (BOOL)::SendMessage(m_hWnd, PSM_SETCURSELID, 0, nPageID);
3765 }
3766
3767 void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
3768 {
3769 ATLASSERT(::IsWindow(m_hWnd));
3770 ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
3771 ATLASSERT(lpszText != NULL);
3772 ::SendMessage(m_hWnd, PSM_SETTITLE, nStyle, (LPARAM)lpszText);
3773 }
3774
3775 HWND GetTabControl() const
3776 {
3777 ATLASSERT(::IsWindow(m_hWnd));
3778 return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0L);
3779 }
3780
3781 void SetFinishText(LPCTSTR lpszText)
3782 {
3783 ATLASSERT(::IsWindow(m_hWnd));
3784 ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText);
3785 }
3786
3787 void SetWizardButtons(DWORD dwFlags)
3788 {
3789 ATLASSERT(::IsWindow(m_hWnd));
3790 ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags);
3791 }
3792
3793 // Operations
3794 BOOL AddPage(HPROPSHEETPAGE hPage)
3795 {
3796 ATLASSERT(::IsWindow(m_hWnd));
3797 ATLASSERT(hPage != NULL);
3798 return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
3799 }
3800
3801 BOOL AddPage(LPCPROPSHEETPAGE pPage)
3802 {
3803 ATLASSERT(::IsWindow(m_hWnd));
3804 ATLASSERT(pPage != NULL);
3805 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3806 if(hPage == NULL)
3807 return FALSE;
3808 return (BOOL)::SendMessage(m_hWnd, PSM_ADDPAGE, 0, (LPARAM)hPage);
3809 }
3810
3811 #ifndef _WIN32_WCE
3812 BOOL InsertPage(int nNewPageIndex, HPROPSHEETPAGE hPage)
3813 {
3814 ATLASSERT(::IsWindow(m_hWnd));
3815 ATLASSERT(hPage != NULL);
3816 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
3817 }
3818
3819 BOOL InsertPage(int nNewPageIndex, LPCPROPSHEETPAGE pPage)
3820 {
3821 ATLASSERT(::IsWindow(m_hWnd));
3822 ATLASSERT(pPage != NULL);
3823 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3824 if(hPage == NULL)
3825 return FALSE;
3826 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, nNewPageIndex, (LPARAM)hPage);
3827 }
3828
3829 BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, HPROPSHEETPAGE hPage)
3830 {
3831 ATLASSERT(::IsWindow(m_hWnd));
3832 ATLASSERT(hPage != NULL);
3833 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
3834 }
3835
3836 BOOL InsertPage(HPROPSHEETPAGE hPageInsertAfter, LPCPROPSHEETPAGE pPage)
3837 {
3838 ATLASSERT(::IsWindow(m_hWnd));
3839 ATLASSERT(pPage != NULL);
3840 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
3841 if(hPage == NULL)
3842 return FALSE;
3843 return (BOOL)::SendMessage(m_hWnd, PSM_INSERTPAGE, (WPARAM)hPageInsertAfter, (LPARAM)hPage);
3844 }
3845 #endif // !_WIN32_WCE
3846
3847 void RemovePage(int nPageIndex)
3848 {
3849 ATLASSERT(::IsWindow(m_hWnd));
3850 ::SendMessage(m_hWnd, PSM_REMOVEPAGE, nPageIndex, 0L);
3851 }
3852
3853 void RemovePage(HPROPSHEETPAGE hPage)
3854 {
3855 ATLASSERT(::IsWindow(m_hWnd));
3856 ATLASSERT(hPage != NULL);
3857 ::SendMessage(m_hWnd, PSM_REMOVEPAGE, 0, (LPARAM)hPage);
3858 }
3859
3860 BOOL PressButton(int nButton)
3861 {
3862 ATLASSERT(::IsWindow(m_hWnd));
3863 return (BOOL)::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0L);
3864 }
3865
3866 BOOL Apply()
3867 {
3868 ATLASSERT(::IsWindow(m_hWnd));
3869 return (BOOL)::SendMessage(m_hWnd, PSM_APPLY, 0, 0L);
3870 }
3871
3872 void CancelToClose()
3873 {
3874 ATLASSERT(::IsWindow(m_hWnd));
3875 ::SendMessage(m_hWnd, PSM_CANCELTOCLOSE, 0, 0L);
3876 }
3877
3878 void SetModified(HWND hWndPage, BOOL bChanged = TRUE)
3879 {
3880 ATLASSERT(::IsWindow(m_hWnd));
3881 ATLASSERT(::IsWindow(hWndPage));
3882 UINT uMsg = bChanged ? PSM_CHANGED : PSM_UNCHANGED;
3883 ::SendMessage(m_hWnd, uMsg, (WPARAM)hWndPage, 0L);
3884 }
3885
3886 LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
3887 {
3888 ATLASSERT(::IsWindow(m_hWnd));
3889 return ::SendMessage(m_hWnd, PSM_QUERYSIBLINGS, wParam, lParam);
3890 }
3891
3892 void RebootSystem()
3893 {
3894 ATLASSERT(::IsWindow(m_hWnd));
3895 ::SendMessage(m_hWnd, PSM_REBOOTSYSTEM, 0, 0L);
3896 }
3897
3898 void RestartWindows()
3899 {
3900 ATLASSERT(::IsWindow(m_hWnd));
3901 ::SendMessage(m_hWnd, PSM_RESTARTWINDOWS, 0, 0L);
3902 }
3903
3904 BOOL IsDialogMessage(LPMSG lpMsg)
3905 {
3906 ATLASSERT(::IsWindow(m_hWnd));
3907 return (BOOL)::SendMessage(m_hWnd, PSM_ISDIALOGMESSAGE, 0, (LPARAM)lpMsg);
3908 }
3909
3910 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3911 int HwndToIndex(HWND hWnd) const
3912 {
3913 ATLASSERT(::IsWindow(m_hWnd));
3914 return (int)::SendMessage(m_hWnd, PSM_HWNDTOINDEX, (WPARAM)hWnd, 0L);
3915 }
3916
3917 HWND IndexToHwnd(int nIndex) const
3918 {
3919 ATLASSERT(::IsWindow(m_hWnd));
3920 return (HWND)::SendMessage(m_hWnd, PSM_INDEXTOHWND, nIndex, 0L);
3921 }
3922
3923 int PageToIndex(HPROPSHEETPAGE hPage) const
3924 {
3925 ATLASSERT(::IsWindow(m_hWnd));
3926 return (int)::SendMessage(m_hWnd, PSM_PAGETOINDEX, 0, (LPARAM)hPage);
3927 }
3928
3929 HPROPSHEETPAGE IndexToPage(int nIndex) const
3930 {
3931 ATLASSERT(::IsWindow(m_hWnd));
3932 return (HPROPSHEETPAGE)::SendMessage(m_hWnd, PSM_INDEXTOPAGE, nIndex, 0L);
3933 }
3934
3935 int IdToIndex(int nID) const
3936 {
3937 ATLASSERT(::IsWindow(m_hWnd));
3938 return (int)::SendMessage(m_hWnd, PSM_IDTOINDEX, 0, nID);
3939 }
3940
3941 int IndexToId(int nIndex) const
3942 {
3943 ATLASSERT(::IsWindow(m_hWnd));
3944 return (int)::SendMessage(m_hWnd, PSM_INDEXTOID, nIndex, 0L);
3945 }
3946
3947 int GetResult() const
3948 {
3949 ATLASSERT(::IsWindow(m_hWnd));
3950 return (int)::SendMessage(m_hWnd, PSM_GETRESULT, 0, 0L);
3951 }
3952
3953 BOOL RecalcPageSizes()
3954 {
3955 ATLASSERT(::IsWindow(m_hWnd));
3956 return (BOOL)::SendMessage(m_hWnd, PSM_RECALCPAGESIZES, 0, 0L);
3957 }
3958
3959 void SetHeaderTitle(int nIndex, LPCTSTR lpstrHeaderTitle)
3960 {
3961 ATLASSERT(::IsWindow(m_hWnd));
3962 ::SendMessage(m_hWnd, PSM_SETHEADERTITLE, nIndex, (LPARAM)lpstrHeaderTitle);
3963 }
3964
3965 void SetHeaderSubTitle(int nIndex, LPCTSTR lpstrHeaderSubTitle)
3966 {
3967 ATLASSERT(::IsWindow(m_hWnd));
3968 ::SendMessage(m_hWnd, PSM_SETHEADERSUBTITLE, nIndex, (LPARAM)lpstrHeaderSubTitle);
3969 }
3970 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
3971
3972 // Implementation - override to prevent usage
3973 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
3974 {
3975 ATLASSERT(FALSE);
3976 return NULL;
3977 }
3978 };
3979
3980 ///////////////////////////////////////////////////////////////////////////////
3981 // CPropertySheetImpl - implements a property sheet
3982
3983 template <class T, class TBase = CPropertySheetWindow>
3984 class ATL_NO_VTABLE CPropertySheetImpl : public ATL::CWindowImplBaseT< TBase >
3985 {
3986 public:
3987 PROPSHEETHEADER m_psh;
3988 ATL::CSimpleArray<HPROPSHEETPAGE> m_arrPages;
3989
3990 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
3991 #ifndef PROPSHEET_LINK_SIZE
3992 #define PROPSHEET_LINK_SIZE 128
3993 #endif // PROPSHEET_LINK_SIZE
3994 TCHAR m_szLink[PROPSHEET_LINK_SIZE];
3995 static LPCTSTR m_pszTitle;
3996 static LPCTSTR m_pszLink;
3997 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
3998
3999 // Construction/Destruction
4000 CPropertySheetImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
4001 {
4002 memset(&m_psh, 0, sizeof(PROPSHEETHEADER));
4003 m_psh.dwSize = sizeof(PROPSHEETHEADER);
4004 m_psh.dwFlags = PSH_USECALLBACK;
4005 m_psh.hInstance = ModuleHelper::GetResourceInstance();
4006 m_psh.phpage = NULL; // will be set later
4007 m_psh.nPages = 0; // will be set later
4008 m_psh.pszCaption = title.m_lpstr;
4009 m_psh.nStartPage = uStartPage;
4010 m_psh.hwndParent = hWndParent; // if NULL, will be set in DoModal/Create
4011 m_psh.pfnCallback = T::PropSheetCallback;
4012
4013 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
4014 m_psh.dwFlags |= PSH_MAXIMIZE;
4015 m_szLink[0] = 0;
4016 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4017 }
4018
4019 ~CPropertySheetImpl()
4020 {
4021 if(m_arrPages.GetSize() > 0) // sheet never created, destroy all pages
4022 {
4023 for(int i = 0; i < m_arrPages.GetSize(); i++)
4024 ::DestroyPropertySheetPage((HPROPSHEETPAGE)m_arrPages[i]);
4025 }
4026 }
4027
4028 // Callback function and overrideables
4029 static int CALLBACK PropSheetCallback(HWND hWnd, UINT uMsg, LPARAM lParam)
4030 {
4031 lParam; // avoid level 4 warning
4032 int nRet = 0;
4033
4034 if(uMsg == PSCB_INITIALIZED)
4035 {
4036 ATLASSERT(hWnd != NULL);
4037 T* pT = (T*)ModuleHelper::ExtractCreateWndData();
4038 // subclass the sheet window
4039 pT->SubclassWindow(hWnd);
4040 // remove page handles array
4041 pT->_CleanUpPages();
4042
4043 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
4044 m_pszTitle = pT->m_psh.pszCaption;
4045 if(*pT->m_szLink != 0)
4046 m_pszLink = pT->m_szLink;
4047 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific
4048
4049 pT->OnSheetInitialized();
4050 }
4051 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific uMsg
4052 else
4053 {
4054 switch(uMsg)
4055 {
4056 case PSCB_GETVERSION :
4057 nRet = COMCTL32_VERSION;
4058 break;
4059 case PSCB_GETTITLE :
4060 if(m_pszTitle != NULL)
4061 {
4062 lstrcpy((LPTSTR)lParam, m_pszTitle);
4063 m_pszTitle = NULL;
4064 }
4065 break;
4066 case PSCB_GETLINKTEXT:
4067 if(m_pszLink != NULL)
4068 {
4069 lstrcpy((LPTSTR)lParam, m_pszLink);
4070 m_pszLink = NULL;
4071 }
4072 break;
4073 default:
4074 break;
4075 }
4076 }
4077 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4078
4079 return nRet;
4080 }
4081
4082 void OnSheetInitialized()
4083 {
4084 }
4085
4086 // Create method
4087 HWND Create(HWND hWndParent = NULL)
4088 {
4089 ATLASSERT(m_hWnd == NULL);
4090
4091 m_psh.dwFlags |= PSH_MODELESS;
4092 if(m_psh.hwndParent == NULL)
4093 m_psh.hwndParent = hWndParent;
4094 m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
4095 m_psh.nPages = m_arrPages.GetSize();
4096
4097 T* pT = static_cast<T*>(this);
4098
4099 #if (_ATL_VER >= 0x0800)
4100 // Allocate the thunk structure here, where we can fail gracefully.
4101 BOOL bRet = pT->m_thunk.Init(NULL, NULL);
4102 if(bRet == FALSE)
4103 {
4104 ::SetLastError(ERROR_OUTOFMEMORY);
4105 return NULL;
4106 }
4107 #endif // (_ATL_VER >= 0x0800)
4108
4109 ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
4110
4111 HWND hWnd = (HWND)::PropertySheet(&m_psh);
4112 _CleanUpPages(); // ensure clean-up, required if call failed
4113
4114 ATLASSERT(m_hWnd == hWnd);
4115
4116 return hWnd;
4117 }
4118
4119 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
4120 {
4121 ATLASSERT(m_hWnd == NULL);
4122
4123 m_psh.dwFlags &= ~PSH_MODELESS;
4124 if(m_psh.hwndParent == NULL)
4125 m_psh.hwndParent = hWndParent;
4126 m_psh.phpage = (HPROPSHEETPAGE*)m_arrPages.GetData();
4127 m_psh.nPages = m_arrPages.GetSize();
4128
4129 T* pT = static_cast<T*>(this);
4130
4131 #if (_ATL_VER >= 0x0800)
4132 // Allocate the thunk structure here, where we can fail gracefully.
4133 BOOL bRet = pT->m_thunk.Init(NULL, NULL);
4134 if(bRet == FALSE)
4135 {
4136 ::SetLastError(ERROR_OUTOFMEMORY);
4137 return -1;
4138 }
4139 #endif // (_ATL_VER >= 0x0800)
4140
4141 ModuleHelper::AddCreateWndData(&pT->m_thunk.cd, pT);
4142
4143 INT_PTR nRet = ::PropertySheet(&m_psh);
4144 _CleanUpPages(); // ensure clean-up, required if call failed
4145
4146 return nRet;
4147 }
4148
4149 // implementation helper - clean up pages array
4150 void _CleanUpPages()
4151 {
4152 m_psh.nPages = 0;
4153 m_psh.phpage = NULL;
4154 m_arrPages.RemoveAll();
4155 }
4156
4157 // Attributes (extended overrides of client class methods)
4158 // These now can be called before the sheet is created
4159 // Note: Calling these after the sheet is created gives unpredictable results
4160 int GetPageCount() const
4161 {
4162 if(m_hWnd == NULL) // not created yet
4163 return m_arrPages.GetSize();
4164 return TBase::GetPageCount();
4165 }
4166
4167 int GetActiveIndex() const
4168 {
4169 if(m_hWnd == NULL) // not created yet
4170 return m_psh.nStartPage;
4171 return TBase::GetActiveIndex();
4172 }
4173
4174 HPROPSHEETPAGE GetPage(int nPageIndex) const
4175 {
4176 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4177 return (HPROPSHEETPAGE)m_arrPages[nPageIndex];
4178 }
4179
4180 int GetPageIndex(HPROPSHEETPAGE hPage) const
4181 {
4182 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4183 return m_arrPages.Find((HPROPSHEETPAGE&)hPage);
4184 }
4185
4186 BOOL SetActivePage(int nPageIndex)
4187 {
4188 if(m_hWnd == NULL) // not created yet
4189 {
4190 ATLASSERT(nPageIndex >= 0 && nPageIndex < m_arrPages.GetSize());
4191 m_psh.nStartPage = nPageIndex;
4192 return TRUE;
4193 }
4194 return TBase::SetActivePage(nPageIndex);
4195 }
4196
4197 BOOL SetActivePage(HPROPSHEETPAGE hPage)
4198 {
4199 ATLASSERT(hPage != NULL);
4200 if (m_hWnd == NULL) // not created yet
4201 {
4202 int nPageIndex = GetPageIndex(hPage);
4203 if(nPageIndex == -1)
4204 return FALSE;
4205
4206 return SetActivePage(nPageIndex);
4207 }
4208 return TBase::SetActivePage(hPage);
4209
4210 }
4211
4212 void SetTitle(LPCTSTR lpszText, UINT nStyle = 0)
4213 {
4214 ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
4215 ATLASSERT(lpszText != NULL);
4216
4217 if(m_hWnd == NULL)
4218 {
4219 // set internal state
4220 m_psh.pszCaption = lpszText; // must exist until sheet is created
4221 m_psh.dwFlags &= ~PSH_PROPTITLE;
4222 m_psh.dwFlags |= nStyle;
4223 }
4224 else
4225 {
4226 // set external state
4227 TBase::SetTitle(lpszText, nStyle);
4228 }
4229 }
4230
4231 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC specific Link field
4232 void SetLinkText(LPCTSTR lpszText)
4233 {
4234 ATLASSERT(lpszText != NULL);
4235 ATLASSERT(lstrlen(lpszText) < PROPSHEET_LINK_SIZE);
4236 lstrcpy(m_szLink, lpszText);
4237 }
4238 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4239
4240 void SetWizardMode()
4241 {
4242 m_psh.dwFlags |= PSH_WIZARD;
4243 }
4244
4245 void EnableHelp()
4246 {
4247 m_psh.dwFlags |= PSH_HASHELP;
4248 }
4249
4250 // Operations
4251 BOOL AddPage(HPROPSHEETPAGE hPage)
4252 {
4253 ATLASSERT(hPage != NULL);
4254 BOOL bRet = FALSE;
4255 if(m_hWnd != NULL)
4256 bRet = TBase::AddPage(hPage);
4257 else // sheet not created yet, use internal data
4258 bRet = m_arrPages.Add((HPROPSHEETPAGE&)hPage);
4259 return bRet;
4260 }
4261
4262 BOOL AddPage(LPCPROPSHEETPAGE pPage)
4263 {
4264 ATLASSERT(pPage != NULL);
4265 HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(pPage);
4266 if(hPage == NULL)
4267 return FALSE;
4268 BOOL bRet = AddPage(hPage);
4269 if(!bRet)
4270 ::DestroyPropertySheetPage(hPage);
4271 return bRet;
4272 }
4273
4274 BOOL RemovePage(HPROPSHEETPAGE hPage)
4275 {
4276 ATLASSERT(hPage != NULL);
4277 if (m_hWnd == NULL) // not created yet
4278 {
4279 int nPage = GetPageIndex(hPage);
4280 if(nPage == -1)
4281 return FALSE;
4282 return RemovePage(nPage);
4283 }
4284 TBase::RemovePage(hPage);
4285 return TRUE;
4286
4287 }
4288
4289 BOOL RemovePage(int nPageIndex)
4290 {
4291 BOOL bRet = TRUE;
4292 if(m_hWnd != NULL)
4293 TBase::RemovePage(nPageIndex);
4294 else // sheet not created yet, use internal data
4295 bRet = m_arrPages.RemoveAt(nPageIndex);
4296 return bRet;
4297 }
4298
4299 #if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4300 void SetHeader(LPCTSTR szbmHeader)
4301 {
4302 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4303
4304 m_psh.dwFlags &= ~PSH_WIZARD;
4305 m_psh.dwFlags |= (PSH_HEADER | PSH_WIZARD97);
4306 m_psh.pszbmHeader = szbmHeader;
4307 }
4308
4309 void SetHeader(HBITMAP hbmHeader)
4310 {
4311 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4312
4313 m_psh.dwFlags &= ~PSH_WIZARD;
4314 m_psh.dwFlags |= (PSH_HEADER | PSH_USEHBMHEADER | PSH_WIZARD97);
4315 m_psh.hbmHeader = hbmHeader;
4316 }
4317
4318 void SetWatermark(LPCTSTR szbmWatermark, HPALETTE hplWatermark = NULL)
4319 {
4320 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4321
4322 m_psh.dwFlags &= ~PSH_WIZARD;
4323 m_psh.dwFlags |= PSH_WATERMARK | PSH_WIZARD97;
4324 m_psh.pszbmWatermark = szbmWatermark;
4325
4326 if (hplWatermark != NULL)
4327 {
4328 m_psh.dwFlags |= PSH_USEHPLWATERMARK;
4329 m_psh.hplWatermark = hplWatermark;
4330 }
4331 }
4332
4333 void SetWatermark(HBITMAP hbmWatermark, HPALETTE hplWatermark = NULL)
4334 {
4335 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4336
4337 m_psh.dwFlags &= ~PSH_WIZARD;
4338 m_psh.dwFlags |= (PSH_WATERMARK | PSH_USEHBMWATERMARK | PSH_WIZARD97);
4339 m_psh.hbmWatermark = hbmWatermark;
4340
4341 if (hplWatermark != NULL)
4342 {
4343 m_psh.dwFlags |= PSH_USEHPLWATERMARK;
4344 m_psh.hplWatermark = hplWatermark;
4345 }
4346 }
4347
4348 void StretchWatermark(bool bStretchWatermark)
4349 {
4350 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4351 if (bStretchWatermark)
4352 m_psh.dwFlags |= PSH_STRETCHWATERMARK;
4353 else
4354 m_psh.dwFlags &= ~PSH_STRETCHWATERMARK;
4355 }
4356 #endif // (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
4357
4358 // Message map and handlers
4359 BEGIN_MSG_MAP(CPropertySheetImpl)
4360 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
4361 MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
4362 END_MSG_MAP()
4363
4364 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
4365 {
4366 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
4367 if(HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) &&
4368 ((m_psh.dwFlags & PSH_MODELESS) != 0) && (GetActivePage() == NULL))
4369 DestroyWindow();
4370 return lRet;
4371 }
4372
4373 LRESULT OnSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
4374 {
4375 if(((m_psh.dwFlags & PSH_MODELESS) == PSH_MODELESS) && ((wParam & 0xFFF0) == SC_CLOSE))
4376 SendMessage(WM_CLOSE);
4377 else
4378 bHandled = FALSE;
4379 return 0;
4380 }
4381 };
4382
4383 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) // PPC static pointers
4384 template < class T, class TBase >
4385 LPCWSTR CPropertySheetImpl<T,TBase>::m_pszTitle = NULL;
4386 template < class T, class TBase>
4387 LPCWSTR CPropertySheetImpl<T,TBase>::m_pszLink = NULL;
4388 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
4389
4390 // for non-customized sheets
4391 class CPropertySheet : public CPropertySheetImpl<CPropertySheet>
4392 {
4393 public:
4394 CPropertySheet(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
4395 : CPropertySheetImpl<CPropertySheet>(title, uStartPage, hWndParent)
4396 { }
4397 };
4398
4399
4400 ///////////////////////////////////////////////////////////////////////////////
4401 // CPropertyPageWindow - client side for a property page
4402
4403 class CPropertyPageWindow : public ATL::CWindow
4404 {
4405 public:
4406 // Constructors
4407 CPropertyPageWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd)
4408 { }
4409
4410 CPropertyPageWindow& operator =(HWND hWnd)
4411 {
4412 m_hWnd = hWnd;
4413 return *this;
4414 }
4415
4416 // Attributes
4417 CPropertySheetWindow GetPropertySheet() const
4418 {
4419 ATLASSERT(::IsWindow(m_hWnd));
4420 return CPropertySheetWindow(GetParent());
4421 }
4422
4423 // Operations
4424 BOOL Apply()
4425 {
4426 ATLASSERT(::IsWindow(m_hWnd));
4427 ATLASSERT(GetParent() != NULL);
4428 return GetPropertySheet().Apply();
4429 }
4430
4431 void CancelToClose()
4432 {
4433 ATLASSERT(::IsWindow(m_hWnd));
4434 ATLASSERT(GetParent() != NULL);
4435 GetPropertySheet().CancelToClose();
4436 }
4437
4438 void SetModified(BOOL bChanged = TRUE)
4439 {
4440 ATLASSERT(::IsWindow(m_hWnd));
4441 ATLASSERT(GetParent() != NULL);
4442 GetPropertySheet().SetModified(m_hWnd, bChanged);
4443 }
4444
4445 LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
4446 {
4447 ATLASSERT(::IsWindow(m_hWnd));
4448 ATLASSERT(GetParent() != NULL);
4449 return GetPropertySheet().QuerySiblings(wParam, lParam);
4450 }
4451
4452 void RebootSystem()
4453 {
4454 ATLASSERT(::IsWindow(m_hWnd));
4455 ATLASSERT(GetParent() != NULL);
4456 GetPropertySheet().RebootSystem();
4457 }
4458
4459 void RestartWindows()
4460 {
4461 ATLASSERT(::IsWindow(m_hWnd));
4462 ATLASSERT(GetParent() != NULL);
4463 GetPropertySheet().RestartWindows();
4464 }
4465
4466 void SetWizardButtons(DWORD dwFlags)
4467 {
4468 ATLASSERT(::IsWindow(m_hWnd));
4469 ATLASSERT(GetParent() != NULL);
4470 GetPropertySheet().SetWizardButtons(dwFlags);
4471 }
4472
4473 // Implementation - overrides to prevent usage
4474 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
4475 {
4476 ATLASSERT(FALSE);
4477 return NULL;
4478 }
4479 };
4480
4481 ///////////////////////////////////////////////////////////////////////////////
4482 // CPropertyPageImpl - implements a property page
4483
4484 template <class T, class TBase = CPropertyPageWindow>
4485 class ATL_NO_VTABLE CPropertyPageImpl : public ATL::CDialogImplBaseT< TBase >
4486 {
4487 public:
4488 PROPSHEETPAGE m_psp;
4489
4490 operator PROPSHEETPAGE*() { return &m_psp; }
4491
4492 // Construction
4493 CPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL)
4494 {
4495 // initialize PROPSHEETPAGE struct
4496 memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
4497 m_psp.dwSize = sizeof(PROPSHEETPAGE);
4498 m_psp.dwFlags = PSP_USECALLBACK;
4499 m_psp.hInstance = ModuleHelper::GetResourceInstance();
4500 T* pT = static_cast<T*>(this);
4501 m_psp.pszTemplate = MAKEINTRESOURCE(pT->IDD);
4502 m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
4503 m_psp.pfnCallback = T::PropPageCallback;
4504 m_psp.lParam = (LPARAM)pT;
4505
4506 if(title.m_lpstr != NULL)
4507 SetTitle(title);
4508 }
4509
4510 // Callback function and overrideables
4511 static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
4512 {
4513 hWnd; // avoid level 4 warning
4514 ATLASSERT(hWnd == NULL);
4515 T* pT = (T*)ppsp->lParam;
4516 UINT uRet = 0;
4517
4518 switch(uMsg)
4519 {
4520 case PSPCB_CREATE:
4521 {
4522 ATL::CDialogImplBaseT< TBase >* pPage = (ATL::CDialogImplBaseT< TBase >*)pT;
4523 ModuleHelper::AddCreateWndData(&pPage->m_thunk.cd, pPage);
4524 uRet = pT->OnPageCreate() ? 1 : 0;
4525 }
4526 break;
4527 #if (_WIN32_IE >= 0x0500)
4528 case PSPCB_ADDREF:
4529 pT->OnPageAddRef();
4530 break;
4531 #endif // (_WIN32_IE >= 0x0500)
4532 case PSPCB_RELEASE:
4533 pT->OnPageRelease();
4534 break;
4535 default:
4536 break;
4537 }
4538
4539 return uRet;
4540 }
4541
4542 bool OnPageCreate()
4543 {
4544 return true; // true - allow page to be created, false - prevent creation
4545 }
4546
4547 #if (_WIN32_IE >= 0x0500)
4548 void OnPageAddRef()
4549 {
4550 }
4551 #endif // (_WIN32_IE >= 0x0500)
4552
4553 void OnPageRelease()
4554 {
4555 }
4556
4557 // Create method
4558 HPROPSHEETPAGE Create()
4559 {
4560 return ::CreatePropertySheetPage(&m_psp);
4561 }
4562
4563 // Attributes
4564 void SetTitle(ATL::_U_STRINGorID title)
4565 {
4566 m_psp.pszTitle = title.m_lpstr;
4567 m_psp.dwFlags |= PSP_USETITLE;
4568 }
4569
4570 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4571 void SetHeaderTitle(LPCTSTR lpstrHeaderTitle)
4572 {
4573 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4574 m_psp.dwFlags |= PSP_USEHEADERTITLE;
4575 m_psp.pszHeaderTitle = lpstrHeaderTitle;
4576 }
4577
4578 void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle)
4579 {
4580 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
4581 m_psp.dwFlags |= PSP_USEHEADERSUBTITLE;
4582 m_psp.pszHeaderSubTitle = lpstrHeaderSubTitle;
4583 }
4584 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
4585
4586 // Operations
4587 void EnableHelp()
4588 {
4589 m_psp.dwFlags |= PSP_HASHELP;
4590 }
4591
4592 // Message map and handlers
4593 BEGIN_MSG_MAP(CPropertyPageImpl)
4594 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
4595 END_MSG_MAP()
4596
4597 // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
4598 // handlers that return direct values without any restrictions
4599 LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
4600 {
4601 #ifndef _WIN32_WCE
4602 // This notification is sometimes received on Windows CE after the window is already destroyed
4603 ATLASSERT(::IsWindow(m_hWnd));
4604 #endif
4605 NMHDR* pNMHDR = (NMHDR*)lParam;
4606
4607 // don't handle messages not from the page/sheet itself
4608 if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
4609 {
4610 bHandled = FALSE;
4611 return 1;
4612 }
4613 #ifdef _WIN32_WCE
4614 ATLASSERT(::IsWindow(m_hWnd));
4615 #endif
4616
4617 T* pT = static_cast<T*>(this);
4618 LRESULT lResult = 0;
4619 switch(pNMHDR->code)
4620 {
4621 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4622 case PSN_SETACTIVE:
4623 lResult = pT->OnSetActive();
4624 break;
4625 case PSN_KILLACTIVE:
4626 lResult = pT->OnKillActive();
4627 break;
4628 case PSN_APPLY:
4629 lResult = pT->OnApply();
4630 break;
4631 case PSN_RESET:
4632 pT->OnReset();
4633 break;
4634 case PSN_QUERYCANCEL:
4635 lResult = pT->OnQueryCancel();
4636 break;
4637 case PSN_WIZNEXT:
4638 lResult = pT->OnWizardNext();
4639 break;
4640 case PSN_WIZBACK:
4641 lResult = pT->OnWizardBack();
4642 break;
4643 case PSN_WIZFINISH:
4644 lResult = pT->OnWizardFinish();
4645 break;
4646 case PSN_HELP:
4647 pT->OnHelp();
4648 break;
4649 #ifndef _WIN32_WCE
4650 #if (_WIN32_IE >= 0x0400)
4651 case PSN_GETOBJECT:
4652 if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
4653 bHandled = FALSE;
4654 break;
4655 #endif // (_WIN32_IE >= 0x0400)
4656 #if (_WIN32_IE >= 0x0500)
4657 case PSN_TRANSLATEACCELERATOR:
4658 {
4659 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4660 lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam);
4661 }
4662 break;
4663 case PSN_QUERYINITIALFOCUS:
4664 {
4665 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4666 lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
4667 }
4668 break;
4669 #endif // (_WIN32_IE >= 0x0500)
4670 #endif // !_WIN32_WCE
4671
4672 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4673 case PSN_SETACTIVE:
4674 lResult = pT->OnSetActive() ? 0 : -1;
4675 break;
4676 case PSN_KILLACTIVE:
4677 lResult = !pT->OnKillActive();
4678 break;
4679 case PSN_APPLY:
4680 lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
4681 break;
4682 case PSN_RESET:
4683 pT->OnReset();
4684 break;
4685 case PSN_QUERYCANCEL:
4686 lResult = !pT->OnQueryCancel();
4687 break;
4688 case PSN_WIZNEXT:
4689 lResult = pT->OnWizardNext();
4690 break;
4691 case PSN_WIZBACK:
4692 lResult = pT->OnWizardBack();
4693 break;
4694 case PSN_WIZFINISH:
4695 lResult = !pT->OnWizardFinish();
4696 break;
4697 case PSN_HELP:
4698 pT->OnHelp();
4699 break;
4700 #ifndef _WIN32_WCE
4701 #if (_WIN32_IE >= 0x0400)
4702 case PSN_GETOBJECT:
4703 if(!pT->OnGetObject((LPNMOBJECTNOTIFY)lParam))
4704 bHandled = FALSE;
4705 break;
4706 #endif // (_WIN32_IE >= 0x0400)
4707 #if (_WIN32_IE >= 0x0500)
4708 case PSN_TRANSLATEACCELERATOR:
4709 {
4710 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4711 lResult = pT->OnTranslateAccelerator((LPMSG)lpPSHNotify->lParam) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
4712 }
4713 break;
4714 case PSN_QUERYINITIALFOCUS:
4715 {
4716 LPPSHNOTIFY lpPSHNotify = (LPPSHNOTIFY)lParam;
4717 lResult = (LRESULT)pT->OnQueryInitialFocus((HWND)lpPSHNotify->lParam);
4718 }
4719 break;
4720 #endif // (_WIN32_IE >= 0x0500)
4721 #endif // !_WIN32_WCE
4722
4723 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4724 default:
4725 bHandled = FALSE; // not handled
4726 }
4727
4728 return lResult;
4729 }
4730
4731 // Overridables
4732 // NOTE: Define _WTL_NEW_PAGE_NOTIFY_HANDLERS to use new notification
4733 // handlers that return direct values without any restrictions
4734 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
4735 int OnSetActive()
4736 {
4737 // 0 = allow activate
4738 // -1 = go back that was active
4739 // page ID = jump to page
4740 return 0;
4741 }
4742
4743 BOOL OnKillActive()
4744 {
4745 // FALSE = allow deactivate
4746 // TRUE = prevent deactivation
4747 return FALSE;
4748 }
4749
4750 int OnApply()
4751 {
4752 // PSNRET_NOERROR = apply OK
4753 // PSNRET_INVALID = apply not OK, return to this page
4754 // PSNRET_INVALID_NOCHANGEPAGE = apply not OK, don't change focus
4755 return PSNRET_NOERROR;
4756 }
4757
4758 void OnReset()
4759 {
4760 }
4761
4762 BOOL OnQueryCancel()
4763 {
4764 // FALSE = allow cancel
4765 // TRUE = prevent cancel
4766 return FALSE;
4767 }
4768
4769 int OnWizardBack()
4770 {
4771 // 0 = goto previous page
4772 // -1 = prevent page change
4773 // >0 = jump to page by dlg ID
4774 return 0;
4775 }
4776
4777 int OnWizardNext()
4778 {
4779 // 0 = goto next page
4780 // -1 = prevent page change
4781 // >0 = jump to page by dlg ID
4782 return 0;
4783 }
4784
4785 INT_PTR OnWizardFinish()
4786 {
4787 // FALSE = allow finish
4788 // TRUE = prevent finish
4789 // HWND = prevent finish and set focus to HWND (CommCtrl 5.80 only)
4790 return FALSE;
4791 }
4792
4793 void OnHelp()
4794 {
4795 }
4796
4797 #ifndef _WIN32_WCE
4798 #if (_WIN32_IE >= 0x0400)
4799 BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
4800 {
4801 return FALSE; // not processed
4802 }
4803 #endif // (_WIN32_IE >= 0x0400)
4804
4805 #if (_WIN32_IE >= 0x0500)
4806 int OnTranslateAccelerator(LPMSG /*lpMsg*/)
4807 {
4808 // PSNRET_NOERROR - message not handled
4809 // PSNRET_MESSAGEHANDLED - message handled
4810 return PSNRET_NOERROR;
4811 }
4812
4813 HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
4814 {
4815 // NULL = set focus to default control
4816 // HWND = set focus to HWND
4817 return NULL;
4818 }
4819 #endif // (_WIN32_IE >= 0x0500)
4820 #endif // !_WIN32_WCE
4821
4822 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4823 BOOL OnSetActive()
4824 {
4825 return TRUE;
4826 }
4827
4828 BOOL OnKillActive()
4829 {
4830 return TRUE;
4831 }
4832
4833 BOOL OnApply()
4834 {
4835 return TRUE;
4836 }
4837
4838 void OnReset()
4839 {
4840 }
4841
4842 BOOL OnQueryCancel()
4843 {
4844 return TRUE; // ok to cancel
4845 }
4846
4847 int OnWizardBack()
4848 {
4849 // 0 = goto previous page
4850 // -1 = prevent page change
4851 // >0 = jump to page by dlg ID
4852 return 0;
4853 }
4854
4855 int OnWizardNext()
4856 {
4857 // 0 = goto next page
4858 // -1 = prevent page change
4859 // >0 = jump to page by dlg ID
4860 return 0;
4861 }
4862
4863 BOOL OnWizardFinish()
4864 {
4865 return TRUE;
4866 }
4867
4868 void OnHelp()
4869 {
4870 }
4871
4872 #ifndef _WIN32_WCE
4873 #if (_WIN32_IE >= 0x0400)
4874 BOOL OnGetObject(LPNMOBJECTNOTIFY /*lpObjectNotify*/)
4875 {
4876 return FALSE; // not processed
4877 }
4878 #endif // (_WIN32_IE >= 0x0400)
4879
4880 #if (_WIN32_IE >= 0x0500)
4881 BOOL OnTranslateAccelerator(LPMSG /*lpMsg*/)
4882 {
4883 return FALSE; // not translated
4884 }
4885
4886 HWND OnQueryInitialFocus(HWND /*hWndFocus*/)
4887 {
4888 return NULL; // default
4889 }
4890 #endif // (_WIN32_IE >= 0x0500)
4891 #endif // !_WIN32_WCE
4892
4893 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
4894 };
4895
4896 // for non-customized pages
4897 template <WORD t_wDlgTemplateID>
4898 class CPropertyPage : public CPropertyPageImpl<CPropertyPage<t_wDlgTemplateID> >
4899 {
4900 public:
4901 enum { IDD = t_wDlgTemplateID };
4902
4903 CPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<CPropertyPage>(title)
4904 { }
4905
4906 DECLARE_EMPTY_MSG_MAP()
4907 };
4908
4909 ///////////////////////////////////////////////////////////////////////////////
4910 // CAxPropertyPageImpl - property page that hosts ActiveX controls
4911
4912 #ifndef _ATL_NO_HOSTING
4913
4914 // Note: You must #include <atlhost.h> to use these classes
4915
4916 template <class T, class TBase = CPropertyPageWindow>
4917 class ATL_NO_VTABLE CAxPropertyPageImpl : public CPropertyPageImpl< T, TBase >
4918 {
4919 public:
4920 // Data members
4921 HGLOBAL m_hInitData;
4922 HGLOBAL m_hDlgRes;
4923 HGLOBAL m_hDlgResSplit;
4924
4925 // Constructor/destructor
4926 CAxPropertyPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) :
4927 CPropertyPageImpl< T, TBase >(title),
4928 m_hInitData(NULL), m_hDlgRes(NULL), m_hDlgResSplit(NULL)
4929 {
4930 T* pT = static_cast<T*>(this);
4931 pT; // avoid level 4 warning
4932
4933 // initialize ActiveX hosting and modify dialog template
4934 ATL::AtlAxWinInit();
4935
4936 HINSTANCE hInstance = ModuleHelper::GetResourceInstance();
4937 LPCTSTR lpTemplateName = MAKEINTRESOURCE(pT->IDD);
4938 HRSRC hDlg = ::FindResource(hInstance, lpTemplateName, (LPTSTR)RT_DIALOG);
4939 if(hDlg != NULL)
4940 {
4941 HRSRC hDlgInit = ::FindResource(hInstance, lpTemplateName, (LPTSTR)_ATL_RT_DLGINIT);
4942
4943 BYTE* pInitData = NULL;
4944 if(hDlgInit != NULL)
4945 {
4946 m_hInitData = ::LoadResource(hInstance, hDlgInit);
4947 pInitData = (BYTE*)::LockResource(m_hInitData);
4948 }
4949
4950 m_hDlgRes = ::LoadResource(hInstance, hDlg);
4951 DLGTEMPLATE* pDlg = (DLGTEMPLATE*)::LockResource(m_hDlgRes);
4952 LPCDLGTEMPLATE lpDialogTemplate = ATL::_DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
4953 if(lpDialogTemplate != pDlg)
4954 m_hDlgResSplit = GlobalHandle(lpDialogTemplate);
4955
4956 // set up property page to use in-memory dialog template
4957 if(lpDialogTemplate != NULL)
4958 {
4959 m_psp.dwFlags |= PSP_DLGINDIRECT;
4960 m_psp.pResource = lpDialogTemplate;
4961 }
4962 else
4963 {
4964 ATLASSERT(FALSE && _T("CAxPropertyPageImpl - ActiveX initializtion failed!"));
4965 }
4966 }
4967 else
4968 {
4969 ATLASSERT(FALSE && _T("CAxPropertyPageImpl - Cannot find dialog template!"));
4970 }
4971 }
4972
4973 ~CAxPropertyPageImpl()
4974 {
4975 if(m_hInitData != NULL)
4976 {
4977 UnlockResource(m_hInitData);
4978 FreeResource(m_hInitData);
4979 }
4980 if(m_hDlgRes != NULL)
4981 {
4982 UnlockResource(m_hDlgRes);
4983 FreeResource(m_hDlgRes);
4984 }
4985 if(m_hDlgResSplit != NULL)
4986 {
4987 ::GlobalFree(m_hDlgResSplit);
4988 }
4989 }
4990
4991 // Methods
4992 // call this one to handle keyboard message for ActiveX controls
4993 BOOL PreTranslateMessage(LPMSG pMsg)
4994 {
4995 if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
4996 (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
4997 return FALSE;
4998 // find a direct child of the dialog from the window that has focus
4999 HWND hWndCtl = ::GetFocus();
5000 if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
5001 {
5002 do
5003 {
5004 hWndCtl = ::GetParent(hWndCtl);
5005 }
5006 while (::GetParent(hWndCtl) != m_hWnd);
5007 }
5008 // give controls a chance to translate this message
5009 return (BOOL)::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg);
5010 }
5011
5012 // Overridables
5013 #if (_WIN32_IE >= 0x0500)
5014 // new default implementation for ActiveX hosting pages
5015 #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
5016 int OnTranslateAccelerator(LPMSG lpMsg)
5017 {
5018 T* pT = static_cast<T*>(this);
5019 return (pT->PreTranslateMessage(lpMsg) != FALSE) ? PSNRET_MESSAGEHANDLED : PSNRET_NOERROR;
5020 }
5021 #else // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
5022 BOOL OnTranslateAccelerator(LPMSG lpMsg)
5023 {
5024 T* pT = static_cast<T*>(this);
5025 return pT->PreTranslateMessage(lpMsg);
5026 }
5027 #endif // !_WTL_NEW_PAGE_NOTIFY_HANDLERS
5028 #endif // (_WIN32_IE >= 0x0500)
5029
5030 // Support for new stuff in ATL7
5031 #if (_ATL_VER >= 0x0700)
5032 int GetIDD()
5033 {
5034 return( static_cast<T*>(this)->IDD );
5035 }
5036
5037 virtual DLGPROC GetDialogProc()
5038 {
5039 return DialogProc;
5040 }
5041
5042 static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5043 {
5044 CAxPropertyPageImpl< T, TBase >* pThis = (CAxPropertyPageImpl< T, TBase >*)hWnd;
5045 if (uMsg == WM_INITDIALOG)
5046 {
5047 HRESULT hr;
5048 if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD())))
5049 {
5050 ATLASSERT(FALSE);
5051 return FALSE;
5052 }
5053 }
5054 return CPropertyPageImpl< T, TBase >::DialogProc(hWnd, uMsg, wParam, lParam);
5055 }
5056
5057 // ActiveX controls creation
5058 virtual HRESULT CreateActiveXControls(UINT nID)
5059 {
5060 // Load dialog template and InitData
5061 HRSRC hDlgInit = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT);
5062 BYTE* pInitData = NULL;
5063 HGLOBAL hData = NULL;
5064 HRESULT hr = S_OK;
5065 if (hDlgInit != NULL)
5066 {
5067 hData = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlgInit);
5068 if (hData != NULL)
5069 pInitData = (BYTE*) ::LockResource(hData);
5070 }
5071
5072 HRSRC hDlg = ::FindResource(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG);
5073 if (hDlg != NULL)
5074 {
5075 HGLOBAL hResource = ::LoadResource(ATL::_AtlBaseModule.GetResourceInstance(), hDlg);
5076 DLGTEMPLATE* pDlg = NULL;
5077 if (hResource != NULL)
5078 {
5079 pDlg = (DLGTEMPLATE*) ::LockResource(hResource);
5080 if (pDlg != NULL)
5081 {
5082 // Get first control on the template
5083 BOOL bDialogEx = ATL::_DialogSplitHelper::IsDialogEx(pDlg);
5084 WORD nItems = ATL::_DialogSplitHelper::DlgTemplateItemCount(pDlg);
5085
5086 // Get first control on the dialog
5087 DLGITEMTEMPLATE* pItem = ATL::_DialogSplitHelper::FindFirstDlgItem(pDlg);
5088 HWND hWndPrev = GetWindow(GW_CHILD);
5089
5090 // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order)
5091 for (WORD nItem = 0; nItem < nItems; nItem++)
5092 {
5093 DWORD wID = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
5094 if (ATL::_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx))
5095 {
5096 BYTE* pData = NULL;
5097 DWORD dwLen = ATL::_DialogSplitHelper::FindCreateData(wID, pInitData, &pData);
5098 ATL::CComPtr<IStream> spStream;
5099 if (dwLen != 0)
5100 {
5101 HGLOBAL h = GlobalAlloc(GHND, dwLen);
5102 if (h != NULL)
5103 {
5104 BYTE* pBytes = (BYTE*) GlobalLock(h);
5105 BYTE* pSource = pData;
5106 SecureHelper::memcpy_x(pBytes, dwLen, pSource, dwLen);
5107 GlobalUnlock(h);
5108 CreateStreamOnHGlobal(h, TRUE, &spStream);
5109 }
5110 else
5111 {
5112 hr = E_OUTOFMEMORY;
5113 break;
5114 }
5115 }
5116
5117 ATL::CComBSTR bstrLicKey;
5118 hr = ATL::_DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str);
5119 if (SUCCEEDED(hr))
5120 {
5121 ATL::CAxWindow2 wnd;
5122 // Get control caption.
5123 LPWSTR pszClassName =
5124 bDialogEx ?
5125 (LPWSTR)(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) :
5126 (LPWSTR)(pItem + 1);
5127 // Get control rect.
5128 RECT rect = { 0 };
5129 rect.left = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x : pItem->x;
5130 rect.top = bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y : pItem->y;
5131 rect.right = rect.left + (bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx : pItem->cx);
5132 rect.bottom = rect.top + (bDialogEx ? ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy : pItem->cy);
5133
5134 // Convert from dialog units to screen units
5135 MapDialogRect(&rect);
5136
5137 // Create AxWindow with a NULL caption.
5138 wnd.Create(m_hWnd,
5139 &rect,
5140 NULL,
5141 (bDialogEx ?
5142 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style :
5143 pItem->style) | WS_TABSTOP,
5144 bDialogEx ?
5145 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle :
5146 0,
5147 bDialogEx ?
5148 ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id :
5149 pItem->id,
5150 NULL);
5151
5152 if (wnd != NULL)
5153 {
5154 #ifndef _WIN32_WCE
5155 // Set the Help ID
5156 if (bDialogEx && ((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0)
5157 wnd.SetWindowContextHelpId(((ATL::_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID);
5158 #endif // !_WIN32_WCE
5159 // Try to create the ActiveX control.
5160 hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey);
5161 if (FAILED(hr))
5162 break;
5163 // Set the correct tab position.
5164 if (nItem == 0)
5165 hWndPrev = HWND_TOP;
5166 wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
5167 hWndPrev = wnd;
5168 }
5169 else
5170 {
5171 hr = ATL::AtlHresultFromLastError();
5172 }
5173 }
5174 }
5175 else
5176 {
5177 if (nItem != 0)
5178 hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT);
5179 }
5180 pItem = ATL::_DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx);
5181 }
5182 }
5183 else
5184 hr = ATL::AtlHresultFromLastError();
5185 }
5186 else
5187 hr = ATL::AtlHresultFromLastError();
5188 }
5189 return hr;
5190 }
5191
5192 // Event handling support
5193 HRESULT AdviseSinkMap(bool bAdvise)
5194 {
5195 if(!bAdvise && m_hWnd == NULL)
5196 {
5197 // window is gone, controls are already unadvised
5198 ATLTRACE2(atlTraceUI, 0, _T("CAxPropertyPageImpl::AdviseSinkMap called after the window was destroyed\n"));
5199 return S_OK;
5200 }
5201 HRESULT hRet = E_NOTIMPL;
5202 __if_exists(T::_GetSinkMapFinder)
5203 {
5204 T* pT = static_cast<T*>(this);
5205 hRet = AtlAdviseSinkMap(pT, bAdvise);
5206 }
5207 return hRet;
5208 }
5209
5210 // Message map and handlers
5211 typedef CPropertyPageImpl< T, TBase> _baseClass;
5212 BEGIN_MSG_MAP(CAxPropertyPageImpl)
5213 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
5214 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
5215 CHAIN_MSG_MAP(_baseClass)
5216 END_MSG_MAP()
5217
5218 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5219 {
5220 // initialize controls in dialog with DLGINIT resource section
5221 ExecuteDlgInit(static_cast<T*>(this)->IDD);
5222 AdviseSinkMap(true);
5223 bHandled = FALSE;
5224 return 1;
5225 }
5226
5227 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5228 {
5229 AdviseSinkMap(false);
5230 bHandled = FALSE;
5231 return 1;
5232 }
5233 #endif // (_ATL_VER >= 0x0700)
5234 };
5235
5236 // for non-customized pages
5237 template <WORD t_wDlgTemplateID>
5238 class CAxPropertyPage : public CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >
5239 {
5240 public:
5241 enum { IDD = t_wDlgTemplateID };
5242
5243 CAxPropertyPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl<CAxPropertyPage>(title)
5244 { }
5245
5246 #if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
5247 // not empty so we handle accelerators/create controls
5248 BEGIN_MSG_MAP(CAxPropertyPage)
5249 CHAIN_MSG_MAP(CAxPropertyPageImpl<CAxPropertyPage<t_wDlgTemplateID> >)
5250 END_MSG_MAP()
5251 #else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5252 DECLARE_EMPTY_MSG_MAP()
5253 #endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5254 };
5255
5256 #endif // _ATL_NO_HOSTING
5257
5258
5259 ///////////////////////////////////////////////////////////////////////////////
5260 // Wizard97 Support
5261
5262 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5263
5264 // Sample wizard dialog resources:
5265 //
5266 // IDD_WIZ97_INTERIOR_BLANK DIALOG 0, 0, 317, 143
5267 // STYLE DS_SETFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
5268 // CAPTION "Wizard97 Property Page - Interior"
5269 // FONT 8, "MS Shell Dlg"
5270 // BEGIN
5271 // END
5272 //
5273 // IDD_WIZ97_EXTERIOR_BLANK DIALOGEX 0, 0, 317, 193
5274 // STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
5275 // CAPTION "Wizard97 Property Page - Welcome/Complete"
5276 // FONT 8, "MS Shell Dlg", 0, 0, 0x0
5277 // BEGIN
5278 // LTEXT "Welcome to the X Wizard",IDC_WIZ97_EXTERIOR_TITLE,115,8,
5279 // 195,24
5280 // LTEXT "Wizard Explanation\r\n(The height of the static text should be in multiples of 8 dlus)",
5281 // IDC_STATIC,115,40,195,16
5282 // LTEXT "h",IDC_WIZ97_BULLET1,118,64,8,8
5283 // LTEXT "List Item 1 (the h is turned into a bullet)",IDC_STATIC,
5284 // 127,63,122,8
5285 // LTEXT "h",IDC_WIZ97_BULLET2,118,79,8,8
5286 // LTEXT "List Item 2. Keep 7 dlus between paragraphs",IDC_STATIC,
5287 // 127,78,33,8
5288 // CONTROL "&Do not show this Welcome page again",
5289 // IDC_WIZ97_WELCOME_NOTAGAIN,"Button",BS_AUTOCHECKBOX |
5290 // WS_TABSTOP,115,169,138,10
5291 // END
5292 //
5293 // GUIDELINES DESIGNINFO
5294 // BEGIN
5295 // IDD_WIZ97_INTERIOR_BLANK, DIALOG
5296 // BEGIN
5297 // LEFTMARGIN, 7
5298 // RIGHTMARGIN, 310
5299 // VERTGUIDE, 21
5300 // VERTGUIDE, 31
5301 // VERTGUIDE, 286
5302 // VERTGUIDE, 296
5303 // TOPMARGIN, 7
5304 // BOTTOMMARGIN, 136
5305 // HORZGUIDE, 8
5306 // END
5307 //
5308 // IDD_WIZ97_EXTERIOR_BLANK, DIALOG
5309 // BEGIN
5310 // RIGHTMARGIN, 310
5311 // VERTGUIDE, 115
5312 // VERTGUIDE, 118
5313 // VERTGUIDE, 127
5314 // TOPMARGIN, 7
5315 // BOTTOMMARGIN, 186
5316 // HORZGUIDE, 8
5317 // HORZGUIDE, 32
5318 // HORZGUIDE, 40
5319 // HORZGUIDE, 169
5320 // END
5321 // END
5322
5323 ///////////////////////////////////////////////////////////////////////////////
5324 // CWizard97SheetWindow - client side for a Wizard 97 style wizard sheet
5325
5326 class CWizard97SheetWindow : public CPropertySheetWindow
5327 {
5328 public:
5329 // Constructors
5330 CWizard97SheetWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
5331 { }
5332
5333 CWizard97SheetWindow& operator =(HWND hWnd)
5334 {
5335 m_hWnd = hWnd;
5336 return *this;
5337 }
5338
5339 // Operations
5340 HFONT GetExteriorPageTitleFont(void)
5341 {
5342 ATLASSERT(::IsWindow(m_hWnd));
5343 return (HFONT)::SendMessage(m_hWnd, GetMessage_GetExteriorPageTitleFont(), 0, 0L);
5344 }
5345
5346 HFONT GetBulletFont(void)
5347 {
5348 ATLASSERT(::IsWindow(m_hWnd));
5349 return (HFONT)::SendMessage(m_hWnd, GetMessage_GetBulletFont(), 0, 0L);
5350 }
5351
5352 // Helpers
5353 static UINT GetMessage_GetExteriorPageTitleFont()
5354 {
5355 static UINT uGetExteriorPageTitleFont = 0;
5356 if(uGetExteriorPageTitleFont == 0)
5357 {
5358 CStaticDataInitCriticalSectionLock lock;
5359 if(FAILED(lock.Lock()))
5360 {
5361 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont().\n"));
5362 ATLASSERT(FALSE);
5363 return 0;
5364 }
5365
5366 if(uGetExteriorPageTitleFont == 0)
5367 uGetExteriorPageTitleFont = ::RegisterWindowMessage(_T("GetExteriorPageTitleFont_531AF056-B8BE-4c4c-B786-AC608DF0DF12"));
5368
5369 lock.Unlock();
5370 }
5371 ATLASSERT(uGetExteriorPageTitleFont != 0);
5372 return uGetExteriorPageTitleFont;
5373 }
5374
5375 static UINT GetMessage_GetBulletFont()
5376 {
5377 static UINT uGetBulletFont = 0;
5378 if(uGetBulletFont == 0)
5379 {
5380 CStaticDataInitCriticalSectionLock lock;
5381 if(FAILED(lock.Lock()))
5382 {
5383 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CWizard97SheetWindow::GetMessage_GetBulletFont().\n"));
5384 ATLASSERT(FALSE);
5385 return 0;
5386 }
5387
5388 if(uGetBulletFont == 0)
5389 uGetBulletFont = ::RegisterWindowMessage(_T("GetBulletFont_AD347D08-8F65-45ef-982E-6352E8218AD5"));
5390
5391 lock.Unlock();
5392 }
5393 ATLASSERT(uGetBulletFont != 0);
5394 return uGetBulletFont;
5395 }
5396
5397 // Implementation - override to prevent usage
5398 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
5399 {
5400 ATLASSERT(FALSE);
5401 return NULL;
5402 }
5403 };
5404
5405
5406 ///////////////////////////////////////////////////////////////////////////////
5407 // CWizard97SheetImpl - implements a Wizard 97 style wizard sheet
5408
5409 template <class T, class TBase = CWizard97SheetWindow>
5410 class ATL_NO_VTABLE CWizard97SheetImpl : public CPropertySheetImpl< T, TBase >
5411 {
5412 protected:
5413 // Typedefs
5414 typedef CWizard97SheetImpl< T, TBase > thisClass;
5415 typedef CPropertySheetImpl< T, TBase > baseClass;
5416
5417 // Member variables
5418 CFont m_fontExteriorPageTitle; // Welcome and Completion page title font
5419 CFont m_fontBullet; // Bullet font (used on static text 'h' to produce a small bullet)
5420 bool m_bReceivedFirstSizeMessage;
5421
5422 public:
5423 CWizard97SheetImpl(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
5424 baseClass(title, uStartPage, hWndParent),
5425 m_bReceivedFirstSizeMessage(false)
5426 {
5427 m_psh.dwFlags &= ~(PSH_NOCONTEXTHELP);
5428 m_psh.dwFlags &= ~(PSH_WIZARD | PSH_WIZARD_LITE);
5429
5430 m_psh.dwFlags |= (PSH_HASHELP | PSH_WIZARDCONTEXTHELP);
5431 m_psh.dwFlags |= PSH_WIZARD97;
5432
5433 baseClass::SetHeader(headerBitmap.m_lpstr);
5434 baseClass::SetWatermark(watermarkBitmap.m_lpstr);
5435 }
5436
5437 // Overrides from base class
5438 void OnSheetInitialized()
5439 {
5440 T* pT = static_cast<T*>(this);
5441 pT->_InitializeFonts();
5442
5443 // We'd like to center the wizard here, but its too early.
5444 // Instead, we'll do CenterWindow upon our first WM_SIZE message
5445 }
5446
5447 // Initialization
5448 void _InitializeFonts()
5449 {
5450 // Setup the Title and Bullet Font
5451 // (Property pages can send the "get external page title font" and "get bullet font" messages)
5452 // The derived class needs to do the actual SetFont for the dialog items)
5453
5454 CFontHandle fontThisDialog = this->GetFont();
5455 CClientDC dcScreen(NULL);
5456
5457 LOGFONT titleLogFont = {0};
5458 LOGFONT bulletLogFont = {0};
5459 fontThisDialog.GetLogFont(&titleLogFont);
5460 fontThisDialog.GetLogFont(&bulletLogFont);
5461
5462 // The Wizard 97 Spec recommends to do the Title Font
5463 // as Verdana Bold, 12pt.
5464 titleLogFont.lfCharSet = DEFAULT_CHARSET;
5465 titleLogFont.lfWeight = FW_BOLD;
5466 SecureHelper::strcpy_x(titleLogFont.lfFaceName, _countof(titleLogFont.lfFaceName), _T("Verdana Bold"));
5467 INT titleFontPointSize = 12;
5468 titleLogFont.lfHeight = -::MulDiv(titleFontPointSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
5469 m_fontExteriorPageTitle.CreateFontIndirect(&titleLogFont);
5470
5471 // The Wizard 97 Spec recommends to do Bullets by having
5472 // static text of "h" in the Marlett font.
5473 bulletLogFont.lfCharSet = DEFAULT_CHARSET;
5474 bulletLogFont.lfWeight = FW_NORMAL;
5475 SecureHelper::strcpy_x(bulletLogFont.lfFaceName, _countof(bulletLogFont.lfFaceName), _T("Marlett"));
5476 INT bulletFontSize = 8;
5477 bulletLogFont.lfHeight = -::MulDiv(bulletFontSize, dcScreen.GetDeviceCaps(LOGPIXELSY), 72);
5478 m_fontBullet.CreateFontIndirect(&bulletLogFont);
5479 }
5480
5481 // Message Handling
5482 BEGIN_MSG_MAP(thisClass)
5483 MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetExteriorPageTitleFont(), OnGetExteriorPageTitleFont)
5484 MESSAGE_HANDLER(CWizard97SheetWindow::GetMessage_GetBulletFont(), OnGetBulletFont)
5485 MESSAGE_HANDLER(WM_SIZE, OnSize)
5486 CHAIN_MSG_MAP(baseClass)
5487 END_MSG_MAP()
5488
5489 LRESULT OnGetExteriorPageTitleFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
5490 {
5491 return (LRESULT)(HFONT)m_fontExteriorPageTitle;
5492 }
5493
5494 LRESULT OnGetBulletFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
5495 {
5496 return (LRESULT)(HFONT)m_fontBullet;
5497 }
5498
5499 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
5500 {
5501 if(!m_bReceivedFirstSizeMessage)
5502 {
5503 m_bReceivedFirstSizeMessage = true;
5504 this->CenterWindow();
5505 }
5506
5507 bHandled = FALSE;
5508 return 0;
5509 }
5510 };
5511
5512 // for non-customized sheets
5513 class CWizard97Sheet : public CWizard97SheetImpl<CWizard97Sheet>
5514 {
5515 protected:
5516 // Typedefs
5517 typedef CWizard97Sheet thisClass;
5518 typedef CWizard97SheetImpl<CWizard97Sheet> baseClass;
5519
5520 public:
5521 CWizard97Sheet(ATL::_U_STRINGorID title, ATL::_U_STRINGorID headerBitmap, ATL::_U_STRINGorID watermarkBitmap, UINT uStartPage = 0, HWND hWndParent = NULL) :
5522 baseClass(title, headerBitmap, watermarkBitmap, uStartPage, hWndParent)
5523 { }
5524
5525 BEGIN_MSG_MAP(thisClass)
5526 CHAIN_MSG_MAP(baseClass)
5527 END_MSG_MAP()
5528 };
5529
5530
5531 ///////////////////////////////////////////////////////////////////////////////
5532 // CWizard97PageWindow - client side for a Wizard 97 style wizard page
5533
5534 #define WIZARD97_EXTERIOR_CXDLG 317
5535 #define WIZARD97_EXTERIOR_CYDLG 193
5536
5537 #define WIZARD97_INTERIOR_CXDLG 317
5538 #define WIZARD97_INTERIOR_CYDLG 143
5539
5540 class CWizard97PageWindow : public CPropertyPageWindow
5541 {
5542 public:
5543 // Constructors
5544 CWizard97PageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
5545 { }
5546
5547 CWizard97PageWindow& operator =(HWND hWnd)
5548 {
5549 m_hWnd = hWnd;
5550 return *this;
5551 }
5552
5553 // Attributes
5554 CWizard97SheetWindow GetPropertySheet() const
5555 {
5556 ATLASSERT(::IsWindow(m_hWnd));
5557 return CWizard97SheetWindow(GetParent());
5558 }
5559
5560 // Operations
5561 HFONT GetExteriorPageTitleFont(void)
5562 {
5563 ATLASSERT(::IsWindow(m_hWnd));
5564 return GetPropertySheet().GetExteriorPageTitleFont();
5565 }
5566
5567 HFONT GetBulletFont(void)
5568 {
5569 ATLASSERT(::IsWindow(m_hWnd));
5570 return GetPropertySheet().GetBulletFont();
5571 }
5572
5573 // Implementation - overrides to prevent usage
5574 HWND Create(LPCTSTR, HWND, ATL::_U_RECT = NULL, LPCTSTR = NULL, DWORD = 0, DWORD = 0, ATL::_U_MENUorID = 0U, LPVOID = NULL)
5575 {
5576 ATLASSERT(FALSE);
5577 return NULL;
5578 }
5579
5580 };
5581
5582
5583 ///////////////////////////////////////////////////////////////////////////////
5584 // CWizard97PageImpl - implements a Wizard 97 style wizard page
5585
5586 template <class T, class TBase = CWizard97PageWindow>
5587 class ATL_NO_VTABLE CWizard97PageImpl : public CPropertyPageImpl< T, TBase >
5588 {
5589 protected:
5590 // Typedefs
5591 typedef CWizard97PageImpl< T, TBase > thisClass;
5592 typedef CPropertyPageImpl< T, TBase > baseClass;
5593
5594 public:
5595 CWizard97PageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5596 { }
5597
5598 // Message Handling
5599 BEGIN_MSG_MAP(thisClass)
5600 CHAIN_MSG_MAP(baseClass)
5601 END_MSG_MAP()
5602 };
5603
5604
5605 ///////////////////////////////////////////////////////////////////////////////
5606 // CWizard97ExteriorPageImpl - implements a Wizard 97 style exterior wizard page
5607
5608 template <class T, class TBase = CWizard97PageWindow>
5609 class ATL_NO_VTABLE CWizard97ExteriorPageImpl : public CPropertyPageImpl< T, TBase >
5610 {
5611 protected:
5612 // Typedefs
5613 typedef CWizard97ExteriorPageImpl< T, TBase > thisClass;
5614 typedef CPropertyPageImpl< T, TBase > baseClass;
5615
5616 public:
5617 // Constructors
5618 CWizard97ExteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5619 {
5620 m_psp.dwFlags |= PSP_HASHELP;
5621 m_psp.dwFlags |= PSP_HIDEHEADER;
5622 }
5623
5624 // Message Handling
5625 BEGIN_MSG_MAP(thisClass)
5626 CHAIN_MSG_MAP(baseClass)
5627 END_MSG_MAP()
5628 };
5629
5630
5631 ///////////////////////////////////////////////////////////////////////////////
5632 // CWizard97InteriorPageImpl - implements a Wizard 97 style interior wizard page
5633
5634 template <class T, class TBase = CWizard97PageWindow>
5635 class ATL_NO_VTABLE CWizard97InteriorPageImpl : public CPropertyPageImpl< T, TBase >
5636 {
5637 protected:
5638 // Typedefs
5639 typedef CWizard97InteriorPageImpl< T, TBase > thisClass;
5640 typedef CPropertyPageImpl< T, TBase > baseClass;
5641
5642 public:
5643 // Constructors
5644 CWizard97InteriorPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : baseClass(title)
5645 {
5646 m_psp.dwFlags |= PSP_HASHELP;
5647 m_psp.dwFlags &= ~PSP_HIDEHEADER;
5648 m_psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
5649
5650 // Be sure to have the derived class define this in the constructor.
5651 // We'll default it to something obvious in case its forgotten.
5652 baseClass::SetHeaderTitle(_T("Call SetHeaderTitle in Derived Class"));
5653 baseClass::SetHeaderSubTitle(_T("Call SetHeaderSubTitle in the constructor of the Derived Class."));
5654 }
5655
5656 // Message Handling
5657 BEGIN_MSG_MAP(thisClass)
5658 CHAIN_MSG_MAP(baseClass)
5659 END_MSG_MAP()
5660 };
5661
5662 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
5663
5664
5665 ///////////////////////////////////////////////////////////////////////////////
5666 // Aero Wizard support
5667
5668 #if (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
5669
5670 ///////////////////////////////////////////////////////////////////////////////
5671 // CAeroWizardFrameWindow - client side for an Aero Wizard frame window
5672
5673 class CAeroWizardFrameWindow : public CPropertySheetWindow
5674 {
5675 public:
5676 // Constructors
5677 CAeroWizardFrameWindow(HWND hWnd = NULL) : CPropertySheetWindow(hWnd)
5678 { }
5679
5680 CAeroWizardFrameWindow& operator =(HWND hWnd)
5681 {
5682 m_hWnd = hWnd;
5683 return *this;
5684 }
5685
5686 // Operations - new, Aero Wizard only
5687 void SetNextText(LPCWSTR lpszText)
5688 {
5689 ATLASSERT(::IsWindow(m_hWnd));
5690 ::SendMessage(m_hWnd, PSM_SETNEXTTEXT, 0, (LPARAM)lpszText);
5691 }
5692
5693 void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
5694 {
5695 ATLASSERT(::IsWindow(m_hWnd));
5696 ::PostMessage(m_hWnd, PSM_SHOWWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
5697 }
5698
5699 void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
5700 {
5701 ATLASSERT(::IsWindow(m_hWnd));
5702 ::PostMessage(m_hWnd, PSM_ENABLEWIZBUTTONS, (WPARAM)dwStates, (LPARAM)dwButtons);
5703 }
5704
5705 void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
5706 {
5707 ATLASSERT(::IsWindow(m_hWnd));
5708 ::SendMessage(m_hWnd, PSM_SETBUTTONTEXT, (WPARAM)dwButton, (LPARAM)lpszText);
5709 }
5710 };
5711
5712
5713 ///////////////////////////////////////////////////////////////////////////////
5714 // CAeroWizardFrameImpl - implements an Aero Wizard frame
5715
5716 template <class T, class TBase = CAeroWizardFrameWindow>
5717 class ATL_NO_VTABLE CAeroWizardFrameImpl : public CPropertySheetImpl<T, TBase >
5718 {
5719 public:
5720 // Constructor
5721 CAeroWizardFrameImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL) :
5722 CPropertySheetImpl<T, TBase >(title, uStartPage, hWndParent)
5723 {
5724 m_psh.dwFlags |= PSH_WIZARD | PSH_AEROWIZARD;
5725 }
5726
5727 // Operations
5728 void EnableResizing()
5729 {
5730 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5731 m_psh.dwFlags |= PSH_RESIZABLE;
5732 }
5733
5734 void UseHeaderBitmap()
5735 {
5736 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5737 m_psh.dwFlags |= PSH_HEADERBITMAP;
5738 }
5739
5740 void SetNoMargin()
5741 {
5742 ATLASSERT(m_hWnd == NULL); // can't do this after it's created
5743 m_psh.dwFlags |= PSH_NOMARGIN;
5744 }
5745
5746 // Override to prevent use
5747 HWND Create(HWND /*hWndParent*/ = NULL)
5748 {
5749 ATLASSERT(FALSE); // not supported for Aero Wizard
5750 return NULL;
5751 }
5752 };
5753
5754
5755 ///////////////////////////////////////////////////////////////////////////////
5756 // CAeroWizardFrame - for non-customized frames
5757
5758 class CAeroWizardFrame : public CAeroWizardFrameImpl<CAeroWizardFrame>
5759 {
5760 public:
5761 CAeroWizardFrame(ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uStartPage = 0, HWND hWndParent = NULL)
5762 : CAeroWizardFrameImpl<CAeroWizardFrame>(title, uStartPage, hWndParent)
5763 { }
5764
5765 BEGIN_MSG_MAP(CAeroWizardFrame)
5766 MESSAGE_HANDLER(WM_COMMAND, CAeroWizardFrameImpl<CAeroWizardFrame>::OnCommand)
5767 END_MSG_MAP()
5768 };
5769
5770
5771 ///////////////////////////////////////////////////////////////////////////////
5772 // CAeroWizardPageWindow - client side for an Aero Wizard page
5773
5774 class CAeroWizardPageWindow : public CPropertyPageWindow
5775 {
5776 public:
5777 // Constructors
5778 CAeroWizardPageWindow(HWND hWnd = NULL) : CPropertyPageWindow(hWnd)
5779 { }
5780
5781 CAeroWizardPageWindow& operator =(HWND hWnd)
5782 {
5783 m_hWnd = hWnd;
5784 return *this;
5785 }
5786
5787 // Attributes
5788 CAeroWizardFrameWindow GetAeroWizardFrame() const
5789 {
5790 ATLASSERT(::IsWindow(m_hWnd));
5791 // This is not really top-level frame window, but it processes all frame messages
5792 return CAeroWizardFrameWindow(GetParent());
5793 }
5794
5795 // Operations - new, Aero Wizard only
5796 void SetNextText(LPCWSTR lpszText)
5797 {
5798 ATLASSERT(::IsWindow(m_hWnd));
5799 ATLASSERT(GetParent() != NULL);
5800 GetAeroWizardFrame().SetNextText(lpszText);
5801 }
5802
5803 void ShowWizardButtons(DWORD dwButtons, DWORD dwStates)
5804 {
5805 ATLASSERT(::IsWindow(m_hWnd));
5806 ATLASSERT(GetParent() != NULL);
5807 GetAeroWizardFrame().ShowWizardButtons(dwButtons, dwStates);
5808 }
5809
5810 void EnableWizardButtons(DWORD dwButtons, DWORD dwStates)
5811 {
5812 ATLASSERT(::IsWindow(m_hWnd));
5813 ATLASSERT(GetParent() != NULL);
5814 GetAeroWizardFrame().EnableWizardButtons(dwButtons, dwStates);
5815 }
5816
5817 void SetButtonText(DWORD dwButton, LPCWSTR lpszText)
5818 {
5819 ATLASSERT(::IsWindow(m_hWnd));
5820 ATLASSERT(GetParent() != NULL);
5821 GetAeroWizardFrame().SetButtonText(dwButton, lpszText);
5822 }
5823 };
5824
5825
5826 ///////////////////////////////////////////////////////////////////////////////
5827 // CAeroWizardPageImpl - implements an Aero Wizard page
5828
5829 template <class T, class TBase = CAeroWizardPageWindow>
5830 class ATL_NO_VTABLE CAeroWizardPageImpl : public CPropertyPageImpl<T, TBase >
5831 {
5832 public:
5833 CAeroWizardPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CPropertyPageImpl<T, TBase >(title)
5834 { }
5835 };
5836
5837
5838 ///////////////////////////////////////////////////////////////////////////////
5839 // CAeroWizardPage - for non-customized pages
5840
5841 template <WORD t_wDlgTemplateID>
5842 class CAeroWizardPage : public CAeroWizardPageImpl<CAeroWizardPage<t_wDlgTemplateID> >
5843 {
5844 public:
5845 enum { IDD = t_wDlgTemplateID };
5846
5847 CAeroWizardPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardPageImpl<CAeroWizardPage>(title)
5848 { }
5849
5850 DECLARE_EMPTY_MSG_MAP()
5851 };
5852
5853
5854 #ifndef _ATL_NO_HOSTING
5855
5856 // Note: You must #include <atlhost.h> to use these classes
5857
5858 ///////////////////////////////////////////////////////////////////////////////
5859 // CAeroWizardAxPageImpl - Aero Wizard page that hosts ActiveX controls
5860
5861 template <class T, class TBase = CAeroWizardPageWindow>
5862 class ATL_NO_VTABLE CAeroWizardAxPageImpl : public CAxPropertyPageImpl< T, TBase >
5863 {
5864 public:
5865 CAeroWizardAxPageImpl(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAxPropertyPageImpl< T, TBase >(title)
5866 { }
5867 };
5868
5869
5870 ///////////////////////////////////////////////////////////////////////////////
5871 // CAeroWizardAxPage - for non-customized pages
5872
5873 template <WORD t_wDlgTemplateID>
5874 class CAeroWizardAxPage : public CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >
5875 {
5876 public:
5877 enum { IDD = t_wDlgTemplateID };
5878
5879 CAeroWizardAxPage(ATL::_U_STRINGorID title = (LPCTSTR)NULL) : CAeroWizardAxPageImpl<CAeroWizardAxPage>(title)
5880 { }
5881
5882 #if (_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700)
5883 // not empty so we handle accelerators/create controls
5884 BEGIN_MSG_MAP(CAeroWizardAxPage)
5885 CHAIN_MSG_MAP(CAeroWizardAxPageImpl<CAeroWizardAxPage<t_wDlgTemplateID> >)
5886 END_MSG_MAP()
5887 #else // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5888 DECLARE_EMPTY_MSG_MAP()
5889 #endif // !((_WIN32_IE >= 0x0500) || (_ATL_VER >= 0x0700))
5890 };
5891
5892 #endif // _ATL_NO_HOSTING
5893
5894 #endif // (_WIN32_WINNT >= 0x0600) && !defined(_WIN32_WCE)
5895
5896
5897 ///////////////////////////////////////////////////////////////////////////////
5898 // TaskDialog support
5899
5900 #if ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
5901
5902 ///////////////////////////////////////////////////////////////////////////////
5903 // AtlTaskDialog - support for TaskDialog() function
5904
5905 inline int AtlTaskDialog(HWND hWndParent,
5906 ATL::_U_STRINGorID WindowTitle, ATL::_U_STRINGorID MainInstructionText, ATL::_U_STRINGorID ContentText,
5907 TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons = 0U, ATL::_U_STRINGorID Icon = (LPCTSTR)NULL)
5908 {
5909 int nRet = -1;
5910
5911 #ifdef _WTL_TASKDIALOG_DIRECT
5912 USES_CONVERSION;
5913 HRESULT hRet = ::TaskDialog(hWndParent, ModuleHelper::GetResourceInstance(),
5914 IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr),
5915 IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr),
5916 IS_INTRESOURCE(ContentText.m_lpstr) ? (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr),
5917 dwCommonButtons,
5918 IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr),
5919 &nRet);
5920 ATLVERIFY(SUCCEEDED(hRet));
5921 #else
5922 // This allows apps to run on older versions of Windows
5923 typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialog)(HWND hwndParent, HINSTANCE hInstance, PCWSTR pszWindowTitle, PCWSTR pszMainInstruction, PCWSTR pszContent, TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons, PCWSTR pszIcon, int* pnButton);
5924
5925 HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
5926 if(m_hCommCtrlDLL != NULL)
5927 {
5928 PFN_TaskDialog pfnTaskDialog = (PFN_TaskDialog)::GetProcAddress(m_hCommCtrlDLL, "TaskDialog");
5929 if(pfnTaskDialog != NULL)
5930 {
5931 USES_CONVERSION;
5932 HRESULT hRet = pfnTaskDialog(hWndParent, ModuleHelper::GetResourceInstance(),
5933 IS_INTRESOURCE(WindowTitle.m_lpstr) ? (LPCWSTR) WindowTitle.m_lpstr : T2CW(WindowTitle.m_lpstr),
5934 IS_INTRESOURCE(MainInstructionText.m_lpstr) ? (LPCWSTR) MainInstructionText.m_lpstr : T2CW(MainInstructionText.m_lpstr),
5935 IS_INTRESOURCE(ContentText.m_lpstr) ? (LPCWSTR) ContentText.m_lpstr : T2CW(ContentText.m_lpstr),
5936 dwCommonButtons,
5937 IS_INTRESOURCE(Icon.m_lpstr) ? (LPCWSTR) Icon.m_lpstr : T2CW(Icon.m_lpstr),
5938 &nRet);
5939 ATLVERIFY(SUCCEEDED(hRet));
5940 }
5941
5942 ::FreeLibrary(m_hCommCtrlDLL);
5943 }
5944 #endif
5945
5946 return nRet;
5947 }
5948
5949
5950 ///////////////////////////////////////////////////////////////////////////////
5951 // CTaskDialogConfig - TASKDIALOGCONFIG wrapper
5952
5953 class CTaskDialogConfig : public TASKDIALOGCONFIG
5954 {
5955 public:
5956 // Constructor
5957 CTaskDialogConfig()
5958 {
5959 Init();
5960 }
5961
5962 void Init()
5963 {
5964 memset(this, 0, sizeof(TASKDIALOGCONFIG)); // initialize structure to 0/NULL
5965 this->cbSize = sizeof(TASKDIALOGCONFIG);
5966 this->hInstance = ModuleHelper::GetResourceInstance();
5967 }
5968
5969 // Operations - setting values
5970 // common buttons
5971 void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtonsArg)
5972 {
5973 this->dwCommonButtons = dwCommonButtonsArg;
5974 }
5975
5976 // window title text
5977 void SetWindowTitle(UINT nID)
5978 {
5979 this->pszWindowTitle = MAKEINTRESOURCEW(nID);
5980 }
5981
5982 void SetWindowTitle(LPCWSTR lpstrWindowTitle)
5983 {
5984 this->pszWindowTitle = lpstrWindowTitle;
5985 }
5986
5987 // main icon
5988 void SetMainIcon(HICON hIcon)
5989 {
5990 this->dwFlags |= TDF_USE_HICON_MAIN;
5991 this->hMainIcon = hIcon;
5992 }
5993
5994 void SetMainIcon(UINT nID)
5995 {
5996 this->dwFlags &= ~TDF_USE_HICON_MAIN;
5997 this->pszMainIcon = MAKEINTRESOURCEW(nID);
5998 }
5999
6000 void SetMainIcon(LPCWSTR lpstrMainIcon)
6001 {
6002 this->dwFlags &= ~TDF_USE_HICON_MAIN;
6003 this->pszMainIcon = lpstrMainIcon;
6004 }
6005
6006 // main instruction text
6007 void SetMainInstructionText(UINT nID)
6008 {
6009 this->pszMainInstruction = MAKEINTRESOURCEW(nID);
6010 }
6011
6012 void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
6013 {
6014 this->pszMainInstruction = lpstrMainInstruction;
6015 }
6016
6017 // content text
6018 void SetContentText(UINT nID)
6019 {
6020 this->pszContent = MAKEINTRESOURCEW(nID);
6021 }
6022
6023 void SetContentText(LPCWSTR lpstrContent)
6024 {
6025 this->pszContent = lpstrContent;
6026 }
6027
6028 // buttons
6029 void SetButtons(const TASKDIALOG_BUTTON* pButtonsArg, UINT cButtonsArg, int nDefaultButtonArg = 0)
6030 {
6031 this->pButtons = pButtonsArg;
6032 this->cButtons = cButtonsArg;
6033 if(nDefaultButtonArg != 0)
6034 this->nDefaultButton = nDefaultButtonArg;
6035 }
6036
6037 void SetDefaultButton(int nDefaultButtonArg)
6038 {
6039 this->nDefaultButton = nDefaultButtonArg;
6040 }
6041
6042 // radio buttons
6043 void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtonsArg, UINT cRadioButtonsArg, int nDefaultRadioButtonArg = 0)
6044 {
6045 this->pRadioButtons = pRadioButtonsArg;
6046 this->cRadioButtons = cRadioButtonsArg;
6047 if(nDefaultRadioButtonArg != 0)
6048 this->nDefaultRadioButton = nDefaultRadioButtonArg;
6049 }
6050
6051 void SetDefaultRadioButton(int nDefaultRadioButtonArg)
6052 {
6053 this->nDefaultRadioButton = nDefaultRadioButtonArg;
6054 }
6055
6056 // verification text
6057 void SetVerificationText(UINT nID)
6058 {
6059 this->pszVerificationText = MAKEINTRESOURCEW(nID);
6060 }
6061
6062 void SetVerificationText(LPCWSTR lpstrVerificationText)
6063 {
6064 this->pszVerificationText = lpstrVerificationText;
6065 }
6066
6067 // expanded information text
6068 void SetExpandedInformationText(UINT nID)
6069 {
6070 this->pszExpandedInformation = MAKEINTRESOURCEW(nID);
6071 }
6072
6073 void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
6074 {
6075 this->pszExpandedInformation = lpstrExpandedInformation;
6076 }
6077
6078 // expanded control text
6079 void SetExpandedControlText(UINT nID)
6080 {
6081 this->pszExpandedControlText = MAKEINTRESOURCEW(nID);
6082 }
6083
6084 void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
6085 {
6086 this->pszExpandedControlText = lpstrExpandedControlText;
6087 }
6088
6089 // collapsed control text
6090 void SetCollapsedControlText(UINT nID)
6091 {
6092 this->pszCollapsedControlText = MAKEINTRESOURCEW(nID);
6093 }
6094
6095 void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
6096 {
6097 this->pszCollapsedControlText = lpstrCollapsedControlText;
6098 }
6099
6100 // footer icon
6101 void SetFooterIcon(HICON hIcon)
6102 {
6103 this->dwFlags |= TDF_USE_HICON_FOOTER;
6104 this->hFooterIcon = hIcon;
6105 }
6106
6107 void SetFooterIcon(UINT nID)
6108 {
6109 this->dwFlags &= ~TDF_USE_HICON_FOOTER;
6110 this->pszFooterIcon = MAKEINTRESOURCEW(nID);
6111 }
6112
6113 void SetFooterIcon(LPCWSTR lpstrFooterIcon)
6114 {
6115 this->dwFlags &= ~TDF_USE_HICON_FOOTER;
6116 this->pszFooterIcon = lpstrFooterIcon;
6117 }
6118
6119 // footer text
6120 void SetFooterText(UINT nID)
6121 {
6122 this->pszFooter = MAKEINTRESOURCEW(nID);
6123 }
6124
6125 void SetFooterText(LPCWSTR lpstrFooterText)
6126 {
6127 this->pszFooter = lpstrFooterText;
6128 }
6129
6130 // width (in DLUs)
6131 void SetWidth(UINT cxWidthArg)
6132 {
6133 this->cxWidth = cxWidthArg;
6134 }
6135
6136 // modify flags
6137 void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
6138 {
6139 this->dwFlags = (this->dwFlags & ~dwRemove) | dwAdd;
6140 }
6141 };
6142
6143
6144 ///////////////////////////////////////////////////////////////////////////////
6145 // CTaskDialogImpl - implements a Task Dialog
6146
6147 template <class T>
6148 class ATL_NO_VTABLE CTaskDialogImpl
6149 {
6150 public:
6151 CTaskDialogConfig m_tdc;
6152 HWND m_hWnd; // used only in callback functions
6153
6154 // Constructor
6155 CTaskDialogImpl(HWND hWndParent = NULL) : m_hWnd(NULL)
6156 {
6157 m_tdc.hwndParent = hWndParent;
6158 m_tdc.pfCallback = T::TaskDialogCallback;
6159 m_tdc.lpCallbackData = (LONG_PTR)static_cast<T*>(this);
6160 }
6161
6162 // Operations
6163 HRESULT DoModal(HWND hWndParent = ::GetActiveWindow(), int* pnButton = NULL, int* pnRadioButton = NULL, BOOL* pfVerificationFlagChecked = NULL)
6164 {
6165 if(m_tdc.hwndParent == NULL)
6166 m_tdc.hwndParent = hWndParent;
6167
6168 #ifdef _WTL_TASKDIALOG_DIRECT
6169 return ::TaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
6170 #else
6171
6172 // This allows apps to run on older versions of Windows
6173 typedef HRESULT (STDAPICALLTYPE *PFN_TaskDialogIndirect)(const TASKDIALOGCONFIG* pTaskConfig, int* pnButton, int* pnRadioButton, BOOL* pfVerificationFlagChecked);
6174
6175 HRESULT hRet = E_UNEXPECTED;
6176 HMODULE m_hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
6177 if(m_hCommCtrlDLL != NULL)
6178 {
6179 PFN_TaskDialogIndirect pfnTaskDialogIndirect = (PFN_TaskDialogIndirect)::GetProcAddress(m_hCommCtrlDLL, "TaskDialogIndirect");
6180 if(pfnTaskDialogIndirect != NULL)
6181 hRet = pfnTaskDialogIndirect(&m_tdc, pnButton, pnRadioButton, pfVerificationFlagChecked);
6182
6183 ::FreeLibrary(m_hCommCtrlDLL);
6184 }
6185
6186 return hRet;
6187 #endif
6188 }
6189
6190 // Operations - setting values of TASKDIALOGCONFIG
6191 // common buttons
6192 void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
6193 { m_tdc.SetCommonButtons(dwCommonButtons); }
6194 // window title text
6195 void SetWindowTitle(UINT nID)
6196 { m_tdc.SetWindowTitle(nID); }
6197 void SetWindowTitle(LPCWSTR lpstrWindowTitle)
6198 { m_tdc.SetWindowTitle(lpstrWindowTitle); }
6199 // main icon
6200 void SetMainIcon(HICON hIcon)
6201 { m_tdc.SetMainIcon(hIcon); }
6202 void SetMainIcon(UINT nID)
6203 { m_tdc.SetMainIcon(nID); }
6204 void SetMainIcon(LPCWSTR lpstrMainIcon)
6205 { m_tdc.SetMainIcon(lpstrMainIcon); }
6206 // main instruction text
6207 void SetMainInstructionText(UINT nID)
6208 { m_tdc.SetMainInstructionText(nID); }
6209 void SetMainInstructionText(LPCWSTR lpstrMainInstruction)
6210 { m_tdc.SetMainInstructionText(lpstrMainInstruction); }
6211 // content text
6212 void SetContentText(UINT nID)
6213 { m_tdc.SetContentText(nID); }
6214 void SetContentText(LPCWSTR lpstrContent)
6215 { m_tdc.SetContentText(lpstrContent); }
6216 // buttons
6217 void SetButtons(const TASKDIALOG_BUTTON* pButtons, UINT cButtons, int nDefaultButton = 0)
6218 { m_tdc.SetButtons(pButtons, cButtons, nDefaultButton); }
6219 void SetDefaultButton(int nDefaultButton)
6220 { m_tdc.SetDefaultButton(nDefaultButton); }
6221 // radio buttons
6222 void SetRadioButtons(const TASKDIALOG_BUTTON* pRadioButtons, UINT cRadioButtons, int nDefaultRadioButton = 0)
6223 { m_tdc.SetRadioButtons(pRadioButtons, cRadioButtons, nDefaultRadioButton); }
6224 void SetDefaultRadioButton(int nDefaultRadioButton)
6225 { m_tdc.SetDefaultRadioButton(nDefaultRadioButton); }
6226 // verification text
6227 void SetVerificationText(UINT nID)
6228 { m_tdc.SetVerificationText(nID); }
6229 void SetVerificationText(LPCWSTR lpstrVerificationText)
6230 { m_tdc.SetVerificationText(lpstrVerificationText); }
6231 // expanded information text
6232 void SetExpandedInformationText(UINT nID)
6233 { m_tdc.SetExpandedInformationText(nID); }
6234 void SetExpandedInformationText(LPCWSTR lpstrExpandedInformation)
6235 { m_tdc.SetExpandedInformationText(lpstrExpandedInformation); }
6236 // expanded control text
6237 void SetExpandedControlText(UINT nID)
6238 { m_tdc.SetExpandedControlText(nID); }
6239 void SetExpandedControlText(LPCWSTR lpstrExpandedControlText)
6240 { m_tdc.SetExpandedControlText(lpstrExpandedControlText); }
6241 // collapsed control text
6242 void SetCollapsedControlText(UINT nID)
6243 { m_tdc.SetCollapsedControlText(nID); }
6244 void SetCollapsedControlText(LPCWSTR lpstrCollapsedControlText)
6245 { m_tdc.SetCollapsedControlText(lpstrCollapsedControlText); }
6246 // footer icon
6247 void SetFooterIcon(HICON hIcon)
6248 { m_tdc.SetFooterIcon(hIcon); }
6249 void SetFooterIcon(UINT nID)
6250 { m_tdc.SetFooterIcon(nID); }
6251 void SetFooterIcon(LPCWSTR lpstrFooterIcon)
6252 { m_tdc.SetFooterIcon(lpstrFooterIcon); }
6253 // footer text
6254 void SetFooterText(UINT nID)
6255 { m_tdc.SetFooterText(nID); }
6256 void SetFooterText(LPCWSTR lpstrFooterText)
6257 { m_tdc.SetFooterText(lpstrFooterText); }
6258 // width (in DLUs)
6259 void SetWidth(UINT cxWidth)
6260 { m_tdc.SetWidth(cxWidth); }
6261 // modify flags
6262 void ModifyFlags(DWORD dwRemove, DWORD dwAdd)
6263 { m_tdc.ModifyFlags(dwRemove, dwAdd); }
6264
6265 // Implementation
6266 static HRESULT CALLBACK TaskDialogCallback(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData)
6267 {
6268 T* pT = (T*)lpRefData;
6269 ATLASSERT(pT->m_hWnd == NULL || pT->m_hWnd == hWnd);
6270
6271 BOOL bRet = FALSE;
6272 switch(uMsg)
6273 {
6274 case TDN_DIALOG_CONSTRUCTED:
6275 pT->m_hWnd = hWnd;
6276 pT->OnDialogConstructed();
6277 break;
6278 case TDN_CREATED:
6279 pT->OnCreated();
6280 break;
6281 case TDN_BUTTON_CLICKED:
6282 bRet = pT->OnButtonClicked((int)wParam);
6283 break;
6284 case TDN_RADIO_BUTTON_CLICKED:
6285 pT->OnRadioButtonClicked((int)wParam);
6286 break;
6287 case TDN_HYPERLINK_CLICKED:
6288 pT->OnHyperlinkClicked((LPCWSTR)lParam);
6289 break;
6290 case TDN_EXPANDO_BUTTON_CLICKED:
6291 pT->OnExpandoButtonClicked((wParam != 0));
6292 break;
6293 case TDN_VERIFICATION_CLICKED:
6294 pT->OnVerificationClicked((wParam != 0));
6295 break;
6296 case TDN_HELP:
6297 pT->OnHelp();
6298 break;
6299 case TDN_TIMER:
6300 bRet = pT->OnTimer((DWORD)wParam);
6301 break;
6302 case TDN_NAVIGATED:
6303 pT->OnNavigated();
6304 break;
6305 case TDN_DESTROYED:
6306 pT->OnDestroyed();
6307 pT->m_hWnd = NULL;
6308 break;
6309 default:
6310 ATLTRACE2(atlTraceUI, 0, _T("Unknown notification received in CTaskDialogImpl::TaskDialogCallback\n"));
6311 break;
6312 }
6313
6314 return (bRet != FALSE) ? S_OK : S_FALSE;
6315 }
6316
6317 // Overrideables - notification handlers
6318 void OnDialogConstructed()
6319 {
6320 }
6321
6322 void OnCreated()
6323 {
6324 }
6325
6326 BOOL OnButtonClicked(int /*nButton*/)
6327 {
6328 return FALSE; // don't prevent dialog to close
6329 }
6330
6331 void OnRadioButtonClicked(int /*nRadioButton*/)
6332 {
6333 }
6334
6335 void OnHyperlinkClicked(LPCWSTR /*pszHREF*/)
6336 {
6337 }
6338
6339 void OnExpandoButtonClicked(bool /*bExpanded*/)
6340 {
6341 }
6342
6343 void OnVerificationClicked(bool /*bChecked*/)
6344 {
6345 }
6346
6347 void OnHelp()
6348 {
6349 }
6350
6351 BOOL OnTimer(DWORD /*dwTickCount*/)
6352 {
6353 return FALSE; // don't reset counter
6354 }
6355
6356 void OnNavigated()
6357 {
6358 }
6359
6360 void OnDestroyed()
6361 {
6362 }
6363
6364 // Commands - valid to call only from handlers
6365 void NavigatePage(TASKDIALOGCONFIG& tdc)
6366 {
6367 ATLASSERT(m_hWnd != NULL);
6368
6369 tdc.cbSize = sizeof(TASKDIALOGCONFIG);
6370 if(tdc.hwndParent == NULL)
6371 tdc.hwndParent = m_tdc.hwndParent;
6372 tdc.pfCallback = m_tdc.pfCallback;
6373 tdc.lpCallbackData = m_tdc.lpCallbackData;
6374 (TASKDIALOGCONFIG)m_tdc = tdc;
6375
6376 ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&tdc);
6377 }
6378
6379 // modify TASKDIALOGCONFIG values, then call this to update task dialog
6380 void NavigatePage()
6381 {
6382 ATLASSERT(m_hWnd != NULL);
6383 ::SendMessage(m_hWnd, TDM_NAVIGATE_PAGE, 0, (LPARAM)&m_tdc);
6384 }
6385
6386 void ClickButton(int nButton)
6387 {
6388 ATLASSERT(m_hWnd != NULL);
6389 ::SendMessage(m_hWnd, TDM_CLICK_BUTTON, nButton, 0L);
6390 }
6391
6392 void SetMarqueeProgressBar(BOOL bMarquee)
6393 {
6394 ATLASSERT(m_hWnd != NULL);
6395 ::SendMessage(m_hWnd, TDM_SET_MARQUEE_PROGRESS_BAR, bMarquee, 0L);
6396 }
6397
6398 BOOL SetProgressBarState(int nNewState)
6399 {
6400 ATLASSERT(m_hWnd != NULL);
6401 return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_STATE, nNewState, 0L);
6402 }
6403
6404 DWORD SetProgressBarRange(int nMinRange, int nMaxRange)
6405 {
6406 ATLASSERT(m_hWnd != NULL);
6407 return (DWORD)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange));
6408 }
6409
6410 int SetProgressBarPos(int nNewPos)
6411 {
6412 ATLASSERT(m_hWnd != NULL);
6413 return (int)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_POS, nNewPos, 0L);
6414 }
6415
6416 BOOL SetProgressBarMarquee(BOOL bMarquee, UINT uSpeed)
6417 {
6418 ATLASSERT(m_hWnd != NULL);
6419 return (BOOL)::SendMessage(m_hWnd, TDM_SET_PROGRESS_BAR_MARQUEE, bMarquee, uSpeed);
6420 }
6421
6422 void SetElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
6423 {
6424 ATLASSERT(m_hWnd != NULL);
6425 ::SendMessage(m_hWnd, TDM_SET_ELEMENT_TEXT, element, (LPARAM)lpstrText);
6426 }
6427
6428 void ClickRadioButton(int nRadioButton)
6429 {
6430 ATLASSERT(m_hWnd != NULL);
6431 ::SendMessage(m_hWnd, TDM_CLICK_RADIO_BUTTON, nRadioButton, 0L);
6432 }
6433
6434 void EnableButton(int nButton, BOOL bEnable)
6435 {
6436 ATLASSERT(m_hWnd != NULL);
6437 ::SendMessage(m_hWnd, TDM_ENABLE_BUTTON, nButton, bEnable);
6438 }
6439
6440 void EnableRadioButton(int nButton, BOOL bEnable)
6441 {
6442 ATLASSERT(m_hWnd != NULL);
6443 ::SendMessage(m_hWnd, TDM_ENABLE_RADIO_BUTTON, nButton, bEnable);
6444 }
6445
6446 void ClickVerification(BOOL bCheck, BOOL bFocus)
6447 {
6448 ATLASSERT(m_hWnd != NULL);
6449 ::SendMessage(m_hWnd, TDM_CLICK_VERIFICATION, bCheck, bFocus);
6450 }
6451
6452 void UpdateElementText(TASKDIALOG_ELEMENTS element, LPCWSTR lpstrText)
6453 {
6454 ATLASSERT(m_hWnd != NULL);
6455 ::SendMessage(m_hWnd, TDM_UPDATE_ELEMENT_TEXT, element, (LPARAM)lpstrText);
6456 }
6457
6458 void SetButtonElevationRequiredState(int nButton, BOOL bElevation)
6459 {
6460 ATLASSERT(m_hWnd != NULL);
6461 ::SendMessage(m_hWnd, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, nButton, bElevation);
6462 }
6463
6464 void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, HICON hIcon)
6465 {
6466 ATLASSERT(m_hWnd != NULL);
6467 #ifdef _DEBUG
6468 if(element == TDIE_ICON_MAIN)
6469 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) != 0);
6470 else if(element == TDIE_ICON_FOOTER)
6471 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) != 0);
6472 #endif // _DEBUG
6473 ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)hIcon);
6474 }
6475
6476 void UpdateIcon(TASKDIALOG_ICON_ELEMENTS element, LPCWSTR lpstrIcon)
6477 {
6478 ATLASSERT(m_hWnd != NULL);
6479 #ifdef _DEBUG
6480 if(element == TDIE_ICON_MAIN)
6481 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_MAIN) == 0);
6482 else if(element == TDIE_ICON_FOOTER)
6483 ATLASSERT((m_tdc.dwFlags & TDF_USE_HICON_FOOTER) == 0);
6484 #endif // _DEBUG
6485 ::SendMessage(m_hWnd, TDM_UPDATE_ICON, element, (LPARAM)lpstrIcon);
6486 }
6487 };
6488
6489
6490 ///////////////////////////////////////////////////////////////////////////////
6491 // CTaskDialog - for non-customized task dialogs
6492
6493 class CTaskDialog : public CTaskDialogImpl<CTaskDialog>
6494 {
6495 public:
6496 CTaskDialog(HWND hWndParent = NULL) : CTaskDialogImpl<CTaskDialog>(hWndParent)
6497 {
6498 m_tdc.pfCallback = NULL;
6499 }
6500 };
6501
6502 #endif // ((_WIN32_WINNT >= 0x0600) || defined(_WTL_TASKDIALOG)) && !defined(_WIN32_WCE)
6503
6504 }; // namespace WTL
6505
6506 #endif // __ATLDLGS_H__
+0
-505
src/third_party/wtl/Include/atldwm.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLDWM_H__
9 #define __ATLDWM_H__
10
11 #pragma once
12
13 #ifdef _WIN32_WCE
14 #error atldwm.h is not supported on Windows CE
15 #endif
16
17 #ifndef __ATLAPP_H__
18 #error atldwm.h requires atlapp.h to be included first
19 #endif
20
21 #ifndef __ATLWIN_H__
22 #error atldwm.h requires atlwin.h to be included first
23 #endif
24
25 #if (_WIN32_WINNT < 0x0600)
26 #error atldwm.h requires _WIN32_WINNT >= 0x0600
27 #endif
28
29 #ifndef _DWMAPI_H_
30 #include <dwmapi.h>
31 #endif
32 #pragma comment(lib, "dwmapi.lib")
33
34 // Note: To create an application that also runs on older versions of Windows,
35 // use delay load of dwmapi.dll and ensure that no calls to the DWM API are
36 // Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib,
37 // and add dwmapi.dll in the Linker.Input.Delay Loaded DLLs section of the
38 // project properties.
39 #if (_MSC_VER < 1300) && !defined(_WTL_NO_DWMAPI_DELAYLOAD)
40 #pragma comment(lib, "delayimp.lib")
41 #pragma comment(linker, "/delayload:dwmapi.dll")
42 #endif // (_MSC_VER < 1300) && !defined(_WTL_NO_DWMAPI_DELAYLOAD)
43
44 ///////////////////////////////////////////////////////////////////////////////
45 // Classes in this file:
46 //
47 // CDwm
48 // CDwmImpl<T, TBase>
49 // CDwmWindowT<TBase> - CDwmWindow
50 // CDwmThumbnailT<t_bManaged, TBase>
51 // CDwmThumbnail
52 // CDwmThumbnailHandle
53 // CAeroControlImpl
54
55
56 namespace WTL
57 {
58
59 ///////////////////////////////////////////////////////////////////////////////
60 // CDwm - wrapper for DWM handle
61
62 class CDwm
63 {
64 public:
65 // Data members
66 static int m_nIsDwmSupported;
67
68 // Constructor
69 CDwm()
70 {
71 IsDwmSupported();
72 }
73
74 // Dwm support helper
75 static bool IsDwmSupported()
76 {
77 if(m_nIsDwmSupported == -1)
78 {
79 CStaticDataInitCriticalSectionLock lock;
80 if(FAILED(lock.Lock()))
81 {
82 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CDwm::IsDwmSupported.\n"));
83 ATLASSERT(FALSE);
84 return false;
85 }
86
87 if(m_nIsDwmSupported == -1)
88 {
89 HMODULE hDwmDLL = ::LoadLibrary(_T("dwmapi.dll"));
90 m_nIsDwmSupported = (hDwmDLL != NULL) ? 1 : 0;
91 if(hDwmDLL != NULL)
92 ::FreeLibrary(hDwmDLL);
93 }
94
95 lock.Unlock();
96 }
97
98 ATLASSERT(m_nIsDwmSupported != -1);
99 return (m_nIsDwmSupported == 1);
100 }
101
102 // Operations
103 BOOL DwmIsCompositionEnabled() const
104 {
105 if(!IsDwmSupported())
106 return FALSE;
107
108 BOOL bRes = FALSE;
109 return (SUCCEEDED(::DwmIsCompositionEnabled(&bRes)) && bRes) ? TRUE : FALSE;
110 }
111
112 BOOL DwmEnableComposition(UINT fEnable)
113 {
114 if(!IsDwmSupported())
115 return FALSE;
116
117 return SUCCEEDED(::DwmEnableComposition(fEnable)) ? TRUE : FALSE;
118 }
119
120 BOOL DwmEnableMMCSS(BOOL fEnableMMCSS)
121 {
122 if(!IsDwmSupported())
123 return FALSE;
124
125 return SUCCEEDED(::DwmEnableMMCSS(fEnableMMCSS)) ? TRUE : FALSE;
126 }
127
128 HRESULT DwmGetColorizationColor(DWORD* pcrColorization, BOOL* pfOpaqueBlend)
129 {
130 if(!IsDwmSupported())
131 return E_NOTIMPL;
132
133 return ::DwmGetColorizationColor(pcrColorization, pfOpaqueBlend);
134 }
135
136 HRESULT DwmFlush()
137 {
138 if(!IsDwmSupported())
139 return E_NOTIMPL;
140
141 return ::DwmFlush();
142 }
143 };
144
145 __declspec(selectany) int CDwm::m_nIsDwmSupported = -1;
146
147
148 ///////////////////////////////////////////////////////////////////////////////
149 // CDwmImpl - DWM window support
150
151 template <class T, class TBase = CDwm>
152 class CDwmImpl : public TBase
153 {
154 public:
155 HRESULT DwmEnableBlurBehindWindow(const DWM_BLURBEHIND* pBB)
156 {
157 if(!IsDwmSupported())
158 return E_NOTIMPL;
159
160 T* pT = static_cast<T*>(this);
161 ATLASSERT(::IsWindow(pT->m_hWnd));
162 return ::DwmEnableBlurBehindWindow(pT->m_hWnd, pBB);
163 }
164
165 HRESULT DwmExtendFrameIntoClientArea(const MARGINS* pMargins)
166 {
167 if(!IsDwmSupported())
168 return E_NOTIMPL;
169
170 T* pT = static_cast<T*>(this);
171 ATLASSERT(::IsWindow(pT->m_hWnd));
172 return ::DwmExtendFrameIntoClientArea(pT->m_hWnd, pMargins);
173 }
174
175 HRESULT DwmExtendFrameIntoEntireClientArea()
176 {
177 MARGINS margins = { -1 };
178 return DwmExtendFrameIntoClientArea(&margins);
179 }
180
181 HRESULT DwmGetCompositionTimingInfo(DWM_TIMING_INFO* pTimingInfo)
182 {
183 if(!IsDwmSupported())
184 return E_NOTIMPL;
185
186 T* pT = static_cast<T*>(this);
187 ATLASSERT(::IsWindow(pT->m_hWnd));
188 return ::DwmGetCompositionTimingInfo(pT->m_hWnd, pTimingInfo);
189 }
190
191 HRESULT DwmGetWindowAttribute(DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute)
192 {
193 if(!IsDwmSupported())
194 return E_NOTIMPL;
195
196 T* pT = static_cast<T*>(this);
197 ATLASSERT(::IsWindow(pT->m_hWnd));
198 return ::DwmGetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute);
199 }
200
201 HRESULT DwmModifyPreviousDxFrameDuration(INT cRefreshes, BOOL fRelative)
202 {
203 if(!IsDwmSupported())
204 return E_NOTIMPL;
205
206 T* pT = static_cast<T*>(this);
207 ATLASSERT(::IsWindow(pT->m_hWnd));
208 return ::DwmModifyPreviousDxFrameDuration(pT->m_hWnd, cRefreshes, fRelative);
209 }
210
211 HRESULT DwmSetDxFrameDuration(INT cRefreshes)
212 {
213 if(!IsDwmSupported())
214 return E_NOTIMPL;
215
216 T* pT = static_cast<T*>(this);
217 ATLASSERT(::IsWindow(pT->m_hWnd));
218 return ::DwmSetDxFrameDuration(pT->m_hWnd, cRefreshes);
219 }
220
221 HRESULT DwmSetPresentParameters(DWM_PRESENT_PARAMETERS* pPresentParams)
222 {
223 if(!IsDwmSupported())
224 return E_NOTIMPL;
225
226 T* pT = static_cast<T*>(this);
227 ATLASSERT(::IsWindow(pT->m_hWnd));
228 return ::DwmSetPresentParameters(pT->m_hWnd, pPresentParams);
229 }
230
231 HRESULT DwmSetWindowAttribute(DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute)
232 {
233 if(!IsDwmSupported())
234 return E_NOTIMPL;
235
236 T* pT = static_cast<T*>(this);
237 ATLASSERT(::IsWindow(pT->m_hWnd));
238 return ::DwmSetWindowAttribute(pT->m_hWnd, dwAttribute, pvAttribute, cbAttribute);
239 }
240
241 HRESULT DwmAttachMilContent()
242 {
243 if(!IsDwmSupported())
244 return E_NOTIMPL;
245
246 T* pT = static_cast<T*>(this);
247 ATLASSERT(::IsWindow(pT->m_hWnd));
248 return ::DwmAttachMilContent(pT->m_hWnd);
249 }
250
251 HRESULT DwmDetachMilContent()
252 {
253 if(!IsDwmSupported())
254 return E_NOTIMPL;
255
256 T* pT = static_cast<T*>(this);
257 ATLASSERT(::IsWindow(pT->m_hWnd));
258 return ::DwmDetachMilContent(pT->m_hWnd);
259 }
260 };
261
262 template <class TBase>
263 class CDwmWindowT : public TBase, public CDwmImpl<CDwmWindowT< TBase > >
264 {
265 public:
266 CDwmWindowT(HWND hWnd = NULL) : TBase(hWnd)
267 { }
268
269 CDwmWindowT< TBase >& operator =(HWND hWnd)
270 {
271 m_hWnd = hWnd;
272 return *this;
273 }
274 };
275
276 typedef CDwmWindowT<ATL::CWindow> CDwmWindow;
277
278
279 ///////////////////////////////////////////////////////////////////////////////
280 // CDwmThumbnail - provides DWM thumbnail support
281
282 template <bool t_bManaged, class TBase = CDwm>
283 class CDwmThumbnailT : public TBase
284 {
285 public:
286 // Data members
287 HTHUMBNAIL m_hThumbnail;
288
289 // Constructor
290 CDwmThumbnailT(HTHUMBNAIL hThumbnail = NULL) : m_hThumbnail(hThumbnail)
291 { }
292
293 ~CDwmThumbnailT()
294 {
295 if(t_bManaged && (m_hThumbnail != NULL))
296 Unregister();
297 }
298
299 // Operations
300 CDwmThumbnailT<t_bManaged, TBase>& operator =(HTHUMBNAIL hThumbnail)
301 {
302 Attach(hThumbnail);
303 return *this;
304 }
305
306 void Attach(HTHUMBNAIL hThumbnailNew)
307 {
308 if(t_bManaged && m_hThumbnail != NULL && m_hThumbnail != hThumbnailNew)
309 Unregister();
310 m_hThumbnail = hThumbnailNew;
311 }
312
313 HTHUMBNAIL Detach()
314 {
315 HTHUMBNAIL hThumbnail = m_hThumbnail;
316 m_hThumbnail = NULL;
317 return hThumbnail;
318 }
319
320 HRESULT Register(HWND hwndDestination, HWND hwndSource)
321 {
322 ATLASSERT(::IsWindow(hwndDestination));
323 ATLASSERT(::IsWindow(hwndSource));
324 ATLASSERT(m_hThumbnail==NULL);
325
326 if(!IsDwmSupported())
327 return E_NOTIMPL;
328
329 return ::DwmRegisterThumbnail(hwndDestination, hwndSource, &m_hThumbnail);
330 }
331
332 HRESULT Unregister()
333 {
334 if(!IsDwmSupported())
335 return E_NOTIMPL;
336 if(m_hThumbnail == NULL)
337 return S_FALSE;
338
339 HRESULT Hr = ::DwmUnregisterThumbnail(m_hThumbnail);
340 if(SUCCEEDED(Hr))
341 m_hThumbnail = NULL;
342
343 return Hr;
344 }
345
346 operator HTHUMBNAIL() const { return m_hThumbnail; }
347
348 bool IsNull() const { return (m_hThumbnail == NULL); }
349
350 HRESULT UpdateProperties(const DWM_THUMBNAIL_PROPERTIES* ptnProperties)
351 {
352 if(!IsDwmSupported())
353 return E_NOTIMPL;
354
355 ATLASSERT(m_hThumbnail != NULL);
356 return ::DwmUpdateThumbnailProperties(m_hThumbnail, ptnProperties);
357 }
358
359 // Attributes
360 HRESULT QuerySourceSize(PSIZE pSize)
361 {
362 if(!IsDwmSupported())
363 return E_NOTIMPL;
364
365 ATLASSERT(m_hThumbnail != NULL);
366 return ::DwmQueryThumbnailSourceSize(m_hThumbnail, pSize);
367 }
368 };
369
370 typedef CDwmThumbnailT<true, CDwm> CDwmThumbnail;
371 typedef CDwmThumbnailT<false, CDwm> CDwmThumbnailHandle;
372
373
374 #ifdef __ATLTHEME_H__
375
376 ///////////////////////////////////////////////////////////////////////////////
377 // CAeroControlImpl - Base class for controls on Glass
378
379 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
380 class CAeroControlImpl : public CThemeImpl<T>,
381 public CBufferedPaintImpl<T>,
382 public ATL::CWindowImpl<T, TBase, TWinTraits>
383 {
384 public:
385 typedef CThemeImpl<T> _themeClass;
386 typedef CBufferedPaintImpl<T> _baseClass;
387 typedef ATL::CWindowImpl<T, TBase, TWinTraits> _windowClass;
388
389 CAeroControlImpl()
390 {
391 m_PaintParams.dwFlags = BPPF_ERASE;
392 }
393
394 static LPCWSTR GetThemeName()
395 {
396 #ifdef _UNICODE
397 return TBase::GetWndClassName();
398 #else
399 ATLASSERT(!_T("Return UNICODE string of window classname / theme class"));
400 return NULL;
401 #endif // _UNICODE
402 }
403
404 // Message map and handlers
405 BEGIN_MSG_MAP(CAeroControlImpl)
406 MESSAGE_HANDLER(WM_CREATE, OnCreate)
407 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
408 CHAIN_MSG_MAP(_themeClass)
409 CHAIN_MSG_MAP(_baseClass)
410 END_MSG_MAP()
411
412 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
413 {
414 T* pT = static_cast<T*>(this);
415 pT->Init();
416
417 bHandled = FALSE;
418 return 0;
419 }
420
421 LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
422 {
423 if(IsThemingSupported())
424 Invalidate(FALSE);
425
426 bHandled = FALSE;
427 return 0;
428 }
429
430 // Operations
431 BOOL SubclassWindow(HWND hWnd)
432 {
433 ATLASSERT(m_hWnd == NULL);
434 ATLASSERT(::IsWindow(hWnd));
435 BOOL bRet = _windowClass::SubclassWindow(hWnd);
436 if(bRet)
437 {
438 T* pT = static_cast<T*>(this);
439 pT->Init();
440 }
441
442 return bRet;
443 }
444
445 // Implementation
446 LRESULT DefWindowProc()
447 {
448 const ATL::_ATL_MSG* pMsg = m_pCurrentMsg;
449 LRESULT lRes = 0;
450 if(pMsg != NULL)
451 lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
452
453 return lRes;
454 }
455
456 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
457 {
458 T* pT = static_cast<T*>(this);
459 LRESULT lRes = 0;
460 if(::DwmDefWindowProc(pT->m_hWnd, uMsg, wParam, lParam, &lRes) != FALSE)
461 return lRes;
462
463 return _windowClass::DefWindowProc(uMsg, wParam, lParam);
464 }
465
466 void DoBufferedPaint(HDC hDC, RECT& rcPaint)
467 {
468 T* pT = static_cast<T*>(this);
469 HDC hDCPaint = NULL;
470 RECT rcClient = { 0 };
471 GetClientRect(&rcClient);
472 m_BufferedPaint.Begin(hDC, &rcClient, m_dwFormat, &m_PaintParams, &hDCPaint);
473 ATLASSERT(hDCPaint != NULL);
474 pT->DoAeroPaint(hDCPaint, rcClient, rcPaint);
475 m_BufferedPaint.End();
476 }
477
478 void DoPaint(HDC /*hdc*/, RECT& /*rcClient*/)
479 {
480 DefWindowProc();
481 }
482
483 // Overridables
484 void Init()
485 {
486 T* pT = static_cast<T*>(this);
487 pT; // avoid level 4 warning
488 SetThemeClassList(pT->GetThemeName());
489 if(m_lpstrThemeClassList != NULL)
490 OpenThemeData();
491 }
492
493 void DoAeroPaint(HDC hDC, RECT& /*rcClient*/, RECT& rcPaint)
494 {
495 DefWindowProc(WM_PAINT, (WPARAM) hDC, 0L);
496 m_BufferedPaint.MakeOpaque(&rcPaint);
497 }
498 };
499
500 #endif // __ATLTHEME_H__
501
502 }; // namespace WTL
503
504 #endif // __ATLDWM_H__
+0
-1012
src/third_party/wtl/Include/atlfind.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLFIND_H__
9 #define __ATLFIND_H__
10
11 #pragma once
12
13 #ifdef _WIN32_WCE
14 #error atlfind.h is not supported on Windows CE
15 #endif
16
17 #ifndef __ATLCTRLS_H__
18 #error atlfind.h requires atlctrls.h to be included first
19 #endif
20
21 #ifndef __ATLDLGS_H__
22 #error atlfind.h requires atldlgs.h to be included first
23 #endif
24
25 #if !((defined(__ATLMISC_H__) && defined(_WTL_USE_CSTRING)) || defined(__ATLSTR_H__))
26 #error atlfind.h requires CString (either from ATL's atlstr.h or WTL's atlmisc.h with _WTL_USE_CSTRING)
27 #endif
28
29
30 ///////////////////////////////////////////////////////////////////////////////
31 // Classes in this file:
32 //
33 // CEditFindReplaceImplBase<T, TFindReplaceDialog>
34 // CEditFindReplaceImpl<T, TFindReplaceDialog>
35 // CRichEditFindReplaceImpl<T, TFindReplaceDialog>
36
37
38 namespace WTL
39 {
40
41 ///////////////////////////////////////////////////////////////////////////////
42 // CEditFindReplaceImplBase - Base class for mixin classes that
43 // help implement Find/Replace for CEdit or CRichEditCtrl based window classes.
44
45 template <class T, class TFindReplaceDialog = CFindReplaceDialog>
46 class CEditFindReplaceImplBase
47 {
48 protected:
49 // Typedefs
50 typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> thisClass;
51
52 // Data members
53 TFindReplaceDialog* m_pFindReplaceDialog;
54 _CSTRING_NS::CString m_sFindNext, m_sReplaceWith;
55 BOOL m_bFindOnly, m_bFirstSearch, m_bMatchCase, m_bWholeWord, m_bFindDown;
56 LONG m_nInitialSearchPos;
57 HCURSOR m_hOldCursor;
58
59 // Enumerations
60 enum TranslationTextItem
61 {
62 eText_OnReplaceAllMessage = 0,
63 eText_OnReplaceAllTitle = 1,
64 eText_OnTextNotFoundMessage = 2,
65 eText_OnTextNotFoundTitle = 3
66 };
67
68 public:
69 // Constructors
70 CEditFindReplaceImplBase() :
71 m_pFindReplaceDialog(NULL),
72 m_bFindOnly(TRUE),
73 m_bFirstSearch(TRUE),
74 m_bMatchCase(FALSE),
75 m_bWholeWord(FALSE),
76 m_bFindDown(TRUE),
77 m_nInitialSearchPos(0),
78 m_hOldCursor(NULL)
79 {
80 }
81
82 // Message Handlers
83 BEGIN_MSG_MAP(thisClass)
84 ALT_MSG_MAP(1)
85 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
86 MESSAGE_HANDLER(TFindReplaceDialog::GetFindReplaceMsg(), OnFindReplaceCmd)
87 COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind)
88 COMMAND_ID_HANDLER(ID_EDIT_REPEAT, OnEditRepeat)
89 COMMAND_ID_HANDLER(ID_EDIT_REPLACE, OnEditReplace)
90 END_MSG_MAP()
91
92 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
93 {
94 if(m_pFindReplaceDialog != NULL)
95 {
96 m_pFindReplaceDialog->SendMessage(WM_CLOSE);
97 ATLASSERT(m_pFindReplaceDialog == NULL);
98 }
99
100 bHandled = FALSE;
101 return 0;
102 }
103
104 LRESULT OnFindReplaceCmd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
105 {
106 T* pT = static_cast<T*>(this);
107
108 TFindReplaceDialog* pDialog = TFindReplaceDialog::GetNotifier(lParam);
109 if(pDialog == NULL)
110 {
111 ATLASSERT(FALSE);
112 ::MessageBeep(MB_ICONERROR);
113 return 1;
114 }
115 ATLASSERT(pDialog == m_pFindReplaceDialog);
116
117 LPFINDREPLACE findReplace = (LPFINDREPLACE)lParam;
118 if((m_pFindReplaceDialog != NULL) && (findReplace != NULL))
119 {
120 if(pDialog->FindNext())
121 {
122 pT->OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(),
123 pDialog->MatchCase(), pDialog->MatchWholeWord());
124 }
125 else if(pDialog->ReplaceCurrent())
126 {
127 pT->OnReplaceSel(pDialog->GetFindString(),
128 pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(),
129 pDialog->GetReplaceString());
130 }
131 else if(pDialog->ReplaceAll())
132 {
133 pT->OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(),
134 pDialog->MatchCase(), pDialog->MatchWholeWord());
135 }
136 else if(pDialog->IsTerminating())
137 {
138 // Dialog is going away (but hasn't gone away yet)
139 // OnFinalMessage will "delete this"
140 pT->OnTerminatingFindReplaceDialog(m_pFindReplaceDialog);
141 m_pFindReplaceDialog = NULL;
142 }
143 }
144
145 return 0;
146 }
147
148 LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
149 {
150 T* pT = static_cast<T*>(this);
151 pT->FindReplace(TRUE);
152
153 return 0;
154 }
155
156 LRESULT OnEditRepeat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
157 {
158 T* pT = static_cast<T*>(this);
159
160 // If the user is holding down SHIFT when hitting F3, we'll
161 // search in reverse. Otherwise, we'll search forward.
162 // (be sure to have an accelerator mapped to ID_EDIT_REPEAT
163 // for both F3 and Shift+F3)
164 m_bFindDown = !((::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
165
166 if(m_sFindNext.IsEmpty())
167 {
168 pT->FindReplace(TRUE);
169 }
170 else
171 {
172 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
173 pT->TextNotFound(m_sFindNext);
174 }
175
176 return 0;
177 }
178
179 LRESULT OnEditReplace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled)
180 {
181 T* pT = static_cast<T*>(this);
182
183 DWORD style = pT->GetStyle();
184 if((style & ES_READONLY) != ES_READONLY)
185 {
186 pT->FindReplace(FALSE);
187 }
188 else
189 {
190 // Don't allow replace when the edit control is read only
191 bHandled = FALSE;
192 }
193
194 return 0;
195 }
196
197 // Operations (overrideable)
198 TFindReplaceDialog* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace
199 LPCTSTR lpszFindWhat,
200 LPCTSTR lpszReplaceWith = NULL,
201 DWORD dwFlags = FR_DOWN,
202 HWND hWndParent = NULL)
203 {
204 // You can override all of this in a derived class
205
206 TFindReplaceDialog* findReplaceDialog = new TFindReplaceDialog();
207 if(findReplaceDialog == NULL)
208 {
209 ::MessageBeep(MB_ICONHAND);
210 }
211 else
212 {
213 HWND hWndFindReplace = findReplaceDialog->Create(bFindOnly,
214 lpszFindWhat, lpszReplaceWith, dwFlags, hWndParent);
215 if(hWndFindReplace == NULL)
216 {
217 delete findReplaceDialog;
218 findReplaceDialog = NULL;
219 }
220 else
221 {
222 findReplaceDialog->SetActiveWindow();
223 findReplaceDialog->ShowWindow(SW_SHOW);
224 }
225 }
226
227 return findReplaceDialog;
228 }
229
230 void AdjustDialogPosition(HWND hWndDialog)
231 {
232 ATLASSERT((hWndDialog != NULL) && ::IsWindow(hWndDialog));
233
234 T* pT = static_cast<T*>(this);
235 LONG nStartChar = 0, nEndChar = 0;
236 // Send EM_GETSEL so we can use both Edit and RichEdit
237 // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&)
238 ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
239 POINT point = pT->PosFromChar(nStartChar);
240 ::ClientToScreen(pT->GetParent(), &point);
241 CRect rect;
242 ::GetWindowRect(hWndDialog, &rect);
243 if(rect.PtInRect(point))
244 {
245 if(point.y > rect.Height())
246 {
247 rect.OffsetRect(0, point.y - rect.bottom - 20);
248 }
249 else
250 {
251 int nVertExt = GetSystemMetrics(SM_CYSCREEN);
252 if(point.y + rect.Height() < nVertExt)
253 rect.OffsetRect(0, 40 + point.y - rect.top);
254 }
255
256 ::MoveWindow(hWndDialog, rect.left, rect.top, rect.Width(), rect.Height(), TRUE);
257 }
258 }
259
260 DWORD GetFindReplaceDialogFlags(void) const
261 {
262 DWORD dwFlags = 0;
263 if(m_bFindDown)
264 dwFlags |= FR_DOWN;
265 if(m_bMatchCase)
266 dwFlags |= FR_MATCHCASE;
267 if(m_bWholeWord)
268 dwFlags |= FR_WHOLEWORD;
269
270 return dwFlags;
271 }
272
273 void FindReplace(BOOL bFindOnly)
274 {
275 T* pT = static_cast<T*>(this);
276 m_bFirstSearch = TRUE;
277 if(m_pFindReplaceDialog != NULL)
278 {
279 if(m_bFindOnly == bFindOnly)
280 {
281 m_pFindReplaceDialog->SetActiveWindow();
282 m_pFindReplaceDialog->ShowWindow(SW_SHOW);
283 return;
284 }
285 else
286 {
287 m_pFindReplaceDialog->SendMessage(WM_CLOSE);
288 ATLASSERT(m_pFindReplaceDialog == NULL);
289 }
290 }
291
292 ATLASSERT(m_pFindReplaceDialog == NULL);
293
294 _CSTRING_NS::CString findNext;
295 pT->GetSelText(findNext);
296 // if selection is empty or spans multiple lines use old find text
297 if(findNext.IsEmpty() || (findNext.FindOneOf(_T("\n\r")) != -1))
298 findNext = m_sFindNext;
299 _CSTRING_NS::CString replaceWith = m_sReplaceWith;
300 DWORD dwFlags = pT->GetFindReplaceDialogFlags();
301
302 m_pFindReplaceDialog = pT->CreateFindReplaceDialog(bFindOnly,
303 findNext, replaceWith, dwFlags, pT->operator HWND());
304 ATLASSERT(m_pFindReplaceDialog != NULL);
305 if(m_pFindReplaceDialog != NULL)
306 m_bFindOnly = bFindOnly;
307 }
308
309 BOOL SameAsSelected(LPCTSTR lpszCompare, BOOL bMatchCase, BOOL /*bWholeWord*/)
310 {
311 T* pT = static_cast<T*>(this);
312
313 // check length first
314 size_t nLen = lstrlen(lpszCompare);
315 LONG nStartChar = 0, nEndChar = 0;
316 // Send EM_GETSEL so we can use both Edit and RichEdit
317 // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&)
318 ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
319 if(nLen != (size_t)(nEndChar - nStartChar))
320 return FALSE;
321
322 // length is the same, check contents
323 _CSTRING_NS::CString selectedText;
324 pT->GetSelText(selectedText);
325
326 return (bMatchCase && selectedText.Compare(lpszCompare) == 0) ||
327 (!bMatchCase && selectedText.CompareNoCase(lpszCompare) == 0);
328 }
329
330 void TextNotFound(LPCTSTR lpszFind)
331 {
332 T* pT = static_cast<T*>(this);
333 m_bFirstSearch = TRUE;
334 pT->OnTextNotFound(lpszFind);
335 }
336
337 _CSTRING_NS::CString GetTranslationText(enum TranslationTextItem eItem) const
338 {
339 _CSTRING_NS::CString text;
340 switch(eItem)
341 {
342 case eText_OnReplaceAllMessage:
343 text = _T("Replaced %d occurances of \"%s\" with \"%s\"");
344 break;
345 case eText_OnReplaceAllTitle:
346 text = _T("Replace All");
347 break;
348 case eText_OnTextNotFoundMessage:
349 text = _T("Unable to find the text \"%s\"");
350 break;
351 case eText_OnTextNotFoundTitle:
352 text = _T("Text not found");
353 break;
354 }
355
356 return text;
357 }
358
359 // Overrideable Handlers
360 void OnFindNext(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord)
361 {
362 T* pT = static_cast<T*>(this);
363
364 m_sFindNext = lpszFind;
365 m_bMatchCase = bMatchCase;
366 m_bWholeWord = bWholeWord;
367 m_bFindDown = bFindDown;
368
369 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
370 pT->TextNotFound(m_sFindNext);
371 else
372 pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND());
373 }
374
375 void OnReplaceSel(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord, LPCTSTR lpszReplace)
376 {
377 T* pT = static_cast<T*>(this);
378
379 m_sFindNext = lpszFind;
380 m_sReplaceWith = lpszReplace;
381 m_bMatchCase = bMatchCase;
382 m_bWholeWord = bWholeWord;
383 m_bFindDown = bFindDown;
384
385 if(pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord))
386 pT->ReplaceSel(m_sReplaceWith);
387
388 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
389 pT->TextNotFound(m_sFindNext);
390 else
391 pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND());
392 }
393
394 void OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bMatchCase, BOOL bWholeWord)
395 {
396 T* pT = static_cast<T*>(this);
397
398 m_sFindNext = lpszFind;
399 m_sReplaceWith = lpszReplace;
400 m_bMatchCase = bMatchCase;
401 m_bWholeWord = bWholeWord;
402 m_bFindDown = TRUE;
403
404 // no selection or different than what looking for
405 if(!pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord))
406 {
407 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
408 {
409 pT->TextNotFound(m_sFindNext);
410 return;
411 }
412 }
413
414 pT->OnReplaceAllCoreBegin();
415
416 int replaceCount=0;
417 do
418 {
419 ++replaceCount;
420 pT->ReplaceSel(m_sReplaceWith);
421 } while(pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown));
422
423 pT->OnReplaceAllCoreEnd(replaceCount);
424 }
425
426 void OnReplaceAllCoreBegin()
427 {
428 T* pT = static_cast<T*>(this);
429
430 m_hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
431
432 pT->HideSelection(TRUE, FALSE);
433
434 }
435
436 void OnReplaceAllCoreEnd(int replaceCount)
437 {
438 T* pT = static_cast<T*>(this);
439 pT->HideSelection(FALSE, FALSE);
440
441 ::SetCursor(m_hOldCursor);
442
443 _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnReplaceAllMessage);
444 if(message.GetLength() > 0)
445 {
446 _CSTRING_NS::CString formattedMessage;
447 formattedMessage.Format(message, replaceCount, m_sFindNext, m_sReplaceWith);
448 if(m_pFindReplaceDialog != NULL)
449 {
450 m_pFindReplaceDialog->MessageBox(formattedMessage,
451 pT->GetTranslationText(eText_OnReplaceAllTitle),
452 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
453 }
454 else
455 {
456 pT->MessageBox(formattedMessage,
457 pT->GetTranslationText(eText_OnReplaceAllTitle),
458 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
459 }
460 }
461 }
462
463 void OnTextNotFound(LPCTSTR lpszFind)
464 {
465 T* pT = static_cast<T*>(this);
466 _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnTextNotFoundMessage);
467 if(message.GetLength() > 0)
468 {
469 _CSTRING_NS::CString formattedMessage;
470 formattedMessage.Format(message, lpszFind);
471 if(m_pFindReplaceDialog != NULL)
472 {
473 m_pFindReplaceDialog->MessageBox(formattedMessage,
474 pT->GetTranslationText(eText_OnTextNotFoundTitle),
475 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
476 }
477 else
478 {
479 pT->MessageBox(formattedMessage,
480 pT->GetTranslationText(eText_OnTextNotFoundTitle),
481 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
482 }
483 }
484 else
485 {
486 ::MessageBeep(MB_ICONHAND);
487 }
488 }
489
490 void OnTerminatingFindReplaceDialog(TFindReplaceDialog*& /*findReplaceDialog*/)
491 {
492 }
493 };
494
495
496 ///////////////////////////////////////////////////////////////////////////////
497 // CEditFindReplaceImpl - Mixin class for implementing Find/Replace for CEdit
498 // based window classes.
499
500 // Chain to CEditFindReplaceImpl message map. Your class must also derive from CEdit.
501 // Example:
502 // class CMyEdit : public CWindowImpl<CMyEdit, CEdit>,
503 // public CEditFindReplaceImpl<CMyEdit>
504 // {
505 // public:
506 // BEGIN_MSG_MAP(CMyEdit)
507 // // your handlers...
508 // CHAIN_MSG_MAP_ALT(CEditFindReplaceImpl<CMyEdit>, 1)
509 // END_MSG_MAP()
510 // // other stuff...
511 // };
512
513 template <class T, class TFindReplaceDialog = CFindReplaceDialog>
514 class CEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDialog>
515 {
516 protected:
517 typedef CEditFindReplaceImpl<T, TFindReplaceDialog> thisClass;
518 typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass;
519
520 // Data members
521 LPTSTR m_pShadowBuffer; // Special shadow buffer only used in some cases.
522 UINT m_nShadowSize;
523 int m_bShadowBufferNeeded; // TRUE, FALSE, < 0 => Need to check
524
525 public:
526 // Constructors
527 CEditFindReplaceImpl() :
528 m_pShadowBuffer(NULL),
529 m_nShadowSize(0),
530 m_bShadowBufferNeeded(-1)
531 {
532 }
533
534 virtual ~CEditFindReplaceImpl()
535 {
536 if(m_pShadowBuffer != NULL)
537 {
538 delete [] m_pShadowBuffer;
539 m_pShadowBuffer = NULL;
540 }
541 }
542
543 // Message Handlers
544 BEGIN_MSG_MAP(thisClass)
545 ALT_MSG_MAP(1)
546 CHAIN_MSG_MAP_ALT(baseClass, 1)
547 END_MSG_MAP()
548
549 // Operations
550 // Supported only for RichEdit, so this does nothing for Edit
551 void HideSelection(BOOL /*bHide*/ = TRUE, BOOL /*bChangeStyle*/ = FALSE)
552 {
553 }
554
555 // Operations (overrideable)
556 BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE)
557 {
558 T* pT = static_cast<T*>(this);
559
560 ATLASSERT(lpszFind != NULL);
561 ATLASSERT(*lpszFind != _T('\0'));
562
563 UINT nLen = pT->GetBufferLength();
564 int nStartChar = 0, nEndChar = 0;
565 pT->GetSel(nStartChar, nEndChar);
566 UINT nStart = nStartChar;
567 int iDir = bFindDown ? +1 : -1;
568
569 // can't find a match before the first character
570 if((nStart == 0) && (iDir < 0))
571 return FALSE;
572
573 LPCTSTR lpszText = pT->LockBuffer();
574
575 bool isDBCS = false;
576 #ifdef _MBCS
577 CPINFO info = { 0 };
578 ::GetCPInfo(::GetOEMCP(), &info);
579 isDBCS = (info.MaxCharSize > 1);
580 #endif
581
582 if(iDir < 0)
583 {
584 // always go back one for search backwards
585 nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart));
586 }
587 else if((nStartChar != nEndChar) && (pT->SameAsSelected(lpszFind, bMatchCase, bWholeWord)))
588 {
589 // easy to go backward/forward with SBCS
590 #ifndef _UNICODE
591 if(::IsDBCSLeadByte(lpszText[nStart]))
592 nStart++;
593 #endif
594 nStart += iDir;
595 }
596
597 // handle search with nStart past end of buffer
598 UINT nLenFind = ::lstrlen(lpszFind);
599 if((nStart + nLenFind - 1) >= nLen)
600 {
601 if((iDir < 0) && (nLen >= nLenFind))
602 {
603 if(isDBCS)
604 {
605 // walk back to previous character n times
606 nStart = nLen;
607 int n = nLenFind;
608 while(n--)
609 {
610 nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart));
611 }
612 }
613 else
614 {
615 // single-byte character set is easy and fast
616 nStart = nLen - nLenFind;
617 }
618 ATLASSERT((nStart + nLenFind - 1) <= nLen);
619 }
620 else
621 {
622 pT->UnlockBuffer();
623 return FALSE;
624 }
625 }
626
627 // start the search at nStart
628 LPCTSTR lpsz = lpszText + nStart;
629 typedef int (WINAPI* CompareProc)(LPCTSTR str1, LPCTSTR str2);
630 CompareProc pfnCompare = bMatchCase ? lstrcmp : lstrcmpi;
631
632 if(isDBCS)
633 {
634 // double-byte string search
635 LPCTSTR lpszStop = NULL;
636 if(iDir > 0)
637 {
638 // start at current and find _first_ occurrance
639 lpszStop = lpszText + nLen - nLenFind + 1;
640 }
641 else
642 {
643 // start at top and find _last_ occurrance
644 lpszStop = lpsz;
645 lpsz = lpszText;
646 }
647
648 LPCTSTR lpszFound = NULL;
649 while(lpsz <= lpszStop)
650 {
651 #ifndef _UNICODE
652 if(!bMatchCase || (*lpsz == *lpszFind && (!::IsDBCSLeadByte(*lpsz) || lpsz[1] == lpszFind[1])))
653 #else
654 if(!bMatchCase || (*lpsz == *lpszFind && lpsz[1] == lpszFind[1]))
655 #endif
656 {
657 LPTSTR lpch = (LPTSTR)(lpsz + nLenFind);
658 TCHAR chSave = *lpch;
659 *lpch = _T('\0');
660 int nResult = (*pfnCompare)(lpsz, lpszFind);
661 *lpch = chSave;
662 if(nResult == 0)
663 {
664 lpszFound = lpsz;
665 if(iDir > 0)
666 break;
667 }
668 }
669 lpsz = ::CharNext(lpsz);
670 }
671 pT->UnlockBuffer();
672
673 if(lpszFound != NULL)
674 {
675 int n = (int)(lpszFound - lpszText);
676 pT->SetSel(n, n + nLenFind);
677 return TRUE;
678 }
679 }
680 else
681 {
682 // single-byte string search
683 UINT nCompare = 0;
684 if(iDir < 0)
685 nCompare = (UINT)(lpsz - lpszText) + 1;
686 else
687 nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1;
688
689 while(nCompare > 0)
690 {
691 ATLASSERT(lpsz >= lpszText);
692 ATLASSERT((lpsz + nLenFind - 1) <= (lpszText + nLen - 1));
693
694 LPSTR lpch = (LPSTR)(lpsz + nLenFind);
695 char chSave = *lpch;
696 *lpch = '\0';
697 int nResult = (*pfnCompare)(lpsz, lpszFind);
698 *lpch = chSave;
699 if(nResult == 0)
700 {
701 pT->UnlockBuffer();
702 int n = (int)(lpsz - lpszText);
703 pT->SetSel(n, n + nLenFind);
704 return TRUE;
705 }
706
707 // restore character at end of search
708 *lpch = chSave;
709
710 // move on to next substring
711 nCompare--;
712 lpsz += iDir;
713 }
714 pT->UnlockBuffer();
715 }
716
717 return FALSE;
718 }
719
720 LPCTSTR LockBuffer() const
721 {
722 const T* pT = static_cast<const T*>(this);
723 ATLASSERT(pT->m_hWnd != NULL);
724
725 BOOL useShadowBuffer = pT->UseShadowBuffer();
726 if(useShadowBuffer)
727 {
728 if((m_pShadowBuffer == NULL) || pT->GetModify())
729 {
730 ATLASSERT((m_pShadowBuffer != NULL) || (m_nShadowSize == 0));
731 UINT nSize = pT->GetWindowTextLength() + 1;
732 if(nSize > m_nShadowSize)
733 {
734 // need more room for shadow buffer
735 T* pThisNoConst = const_cast<T*>(pT);
736 delete[] m_pShadowBuffer;
737 pThisNoConst->m_pShadowBuffer = NULL;
738 pThisNoConst->m_nShadowSize = 0;
739 pThisNoConst->m_pShadowBuffer = new TCHAR[nSize];
740 pThisNoConst->m_nShadowSize = nSize;
741 }
742
743 // update the shadow buffer with GetWindowText
744 ATLASSERT(m_nShadowSize >= nSize);
745 ATLASSERT(m_pShadowBuffer != NULL);
746 pT->GetWindowText(m_pShadowBuffer, nSize);
747 }
748
749 return m_pShadowBuffer;
750 }
751
752 HLOCAL hLocal = pT->GetHandle();
753 ATLASSERT(hLocal != NULL);
754 LPCTSTR lpszText = (LPCTSTR)::LocalLock(hLocal);
755 ATLASSERT(lpszText != NULL);
756
757 return lpszText;
758 }
759
760 void UnlockBuffer() const
761 {
762 const T* pT = static_cast<const T*>(this);
763 ATLASSERT(pT->m_hWnd != NULL);
764
765 BOOL useShadowBuffer = pT->UseShadowBuffer();
766 if(!useShadowBuffer)
767 {
768 HLOCAL hLocal = pT->GetHandle();
769 ATLASSERT(hLocal != NULL);
770 ::LocalUnlock(hLocal);
771 }
772 }
773
774 UINT GetBufferLength() const
775 {
776 const T* pT = static_cast<const T*>(this);
777 ATLASSERT(pT->m_hWnd != NULL);
778
779 UINT nLen = 0;
780 LPCTSTR lpszText = pT->LockBuffer();
781 if(lpszText != NULL)
782 nLen = ::lstrlen(lpszText);
783 pT->UnlockBuffer();
784
785 return nLen;
786 }
787
788 LONG EndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex) const
789 {
790 LPCTSTR lpsz = lpszText + nIndex;
791 LPCTSTR lpszStop = lpszText + nLen;
792 while(lpsz < lpszStop && *lpsz != _T('\r'))
793 ++lpsz;
794 return LONG(lpsz - lpszText);
795 }
796
797 LONG GetSelText(_CSTRING_NS::CString& strText) const
798 {
799 const T* pT = static_cast<const T*>(this);
800
801 int nStartChar = 0, nEndChar = 0;
802 pT->GetSel(nStartChar, nEndChar);
803 ATLASSERT((UINT)nEndChar <= pT->GetBufferLength());
804 LPCTSTR lpszText = pT->LockBuffer();
805 LONG nLen = pT->EndOfLine(lpszText, nEndChar, nStartChar) - nStartChar;
806 SecureHelper::memcpy_x(strText.GetBuffer(nLen), nLen * sizeof(TCHAR), lpszText + nStartChar, nLen * sizeof(TCHAR));
807 strText.ReleaseBuffer(nLen);
808 pT->UnlockBuffer();
809
810 return nLen;
811 }
812
813 BOOL UseShadowBuffer(void) const
814 {
815 const T* pT = static_cast<const T*>(this);
816
817 if(pT->m_bShadowBufferNeeded < 0)
818 {
819 T* pThisNoConst = const_cast<T*>(pT);
820
821 #ifdef _versionhelpers_H_INCLUDED_
822 OSVERSIONINFOEX ovi = { sizeof(OSVERSIONINFOEX) };
823 ovi.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
824 DWORDLONG const dwlConditionMask = ::VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL);
825 bool bWin9x = (::VerifyVersionInfo(&ovi, VER_PLATFORMID, dwlConditionMask) != FALSE);
826 #else // !_versionhelpers_H_INCLUDED_
827 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
828 ::GetVersionEx(&ovi);
829
830 bool bWin9x = (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
831 #endif // _versionhelpers_H_INCLUDED_
832 if(bWin9x)
833 {
834 // Windows 95, 98, ME
835 // Under Win9x, it is necessary to maintain a shadow buffer.
836 // It is only updated when the control contents have been changed.
837 pThisNoConst->m_bShadowBufferNeeded = TRUE;
838 }
839 else
840 {
841 // Windows NT, 2000, XP, etc.
842 pThisNoConst->m_bShadowBufferNeeded = FALSE;
843
844 #ifndef _UNICODE
845 // On Windows XP (or later), if common controls version 6 is in use
846 // (such as via theming), then EM_GETHANDLE will always return a UNICODE string.
847 // If theming is enabled and Common Controls version 6 is in use,
848 // you're really not suppose to superclass or subclass common controls
849 // with an ANSI windows procedure (so its best to only theme if you use UNICODE).
850 // Using a shadow buffer uses GetWindowText instead, so it solves
851 // this problem for us (although it makes it a little less efficient).
852
853 #ifdef _versionhelpers_H_INCLUDED_
854 if(::IsWindowsXPOrGreater())
855 #else // !_versionhelpers_H_INCLUDED_
856 if ((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5))
857 #endif // _versionhelpers_H_INCLUDED_
858 {
859 DWORD dwMajor = 0, dwMinor = 0;
860 HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
861 if(SUCCEEDED(hRet))
862 {
863 if(dwMajor >= 6)
864 {
865 pThisNoConst->m_bShadowBufferNeeded = TRUE;
866
867 ATLTRACE2(atlTraceUI, 0, _T("Warning: You have compiled for MBCS/ANSI but are using common controls version 6 or later (likely through a manifest file).\r\n"));
868 ATLTRACE2(atlTraceUI, 0, _T("If you use common controls version 6 or later, you should only do so for UNICODE builds.\r\n"));
869 }
870 }
871 }
872 #endif // !_UNICODE
873 }
874 }
875
876 return (pT->m_bShadowBufferNeeded != FALSE);
877 }
878 };
879
880
881 ///////////////////////////////////////////////////////////////////////////////
882 // CRichEditFindReplaceImpl - Mixin class for implementing Find/Replace for CRichEditCtrl
883 // based window classes.
884
885 // Chain to CRichEditFindReplaceImpl message map. Your class must also derive from CRichEditCtrl.
886 // Example:
887 // class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>,
888 // public CRichEditFindReplaceImpl<CMyRichEdit>
889 // {
890 // public:
891 // BEGIN_MSG_MAP(CMyRichEdit)
892 // // your handlers...
893 // CHAIN_MSG_MAP_ALT(CRichEditFindReplaceImpl<CMyRichEdit>, 1)
894 // END_MSG_MAP()
895 // // other stuff...
896 // };
897
898 template <class T, class TFindReplaceDialog = CFindReplaceDialog>
899 class CRichEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDialog>
900 {
901 protected:
902 typedef CRichEditFindReplaceImpl<T, TFindReplaceDialog> thisClass;
903 typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass;
904
905 public:
906 BEGIN_MSG_MAP(thisClass)
907 ALT_MSG_MAP(1)
908 CHAIN_MSG_MAP_ALT(baseClass, 1)
909 END_MSG_MAP()
910
911 // Operations (overrideable)
912 BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE)
913 {
914 T* pT = static_cast<T*>(this);
915
916 ATLASSERT(lpszFind != NULL);
917 FINDTEXTEX ft = { 0 };
918
919 pT->GetSel(ft.chrg);
920 if(m_bFirstSearch)
921 {
922 if(bFindDown)
923 m_nInitialSearchPos = ft.chrg.cpMin;
924 else
925 m_nInitialSearchPos = ft.chrg.cpMax;
926 m_bFirstSearch = FALSE;
927 }
928
929 #if (_RICHEDIT_VER >= 0x0200)
930 ft.lpstrText = (LPTSTR)lpszFind;
931 #else // !(_RICHEDIT_VER >= 0x0200)
932 USES_CONVERSION;
933 ft.lpstrText = T2A((LPTSTR)lpszFind);
934 #endif // !(_RICHEDIT_VER >= 0x0200)
935
936 if(ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection
937 {
938 if(bFindDown)
939 {
940 ft.chrg.cpMin++;
941 }
942 else
943 {
944 // won't wraparound backwards
945 ft.chrg.cpMin = __max(ft.chrg.cpMin, 0);
946 }
947 }
948
949 DWORD dwFlags = bMatchCase ? FR_MATCHCASE : 0;
950 dwFlags |= bWholeWord ? FR_WHOLEWORD : 0;
951
952 ft.chrg.cpMax = pT->GetTextLength() + m_nInitialSearchPos;
953
954 if(bFindDown)
955 {
956 if(m_nInitialSearchPos >= 0)
957 ft.chrg.cpMax = pT->GetTextLength();
958
959 dwFlags |= FR_DOWN;
960 ATLASSERT(ft.chrg.cpMax >= ft.chrg.cpMin);
961 }
962 else
963 {
964 if(m_nInitialSearchPos >= 0)
965 ft.chrg.cpMax = 0;
966
967 dwFlags &= ~FR_DOWN;
968 ATLASSERT(ft.chrg.cpMax <= ft.chrg.cpMin);
969 }
970
971 BOOL bRet = FALSE;
972 if(pT->FindAndSelect(dwFlags, ft) != -1)
973 {
974 bRet = TRUE; // we found the text
975 }
976 else if(m_nInitialSearchPos > 0)
977 {
978 // if the original starting point was not the beginning
979 // of the buffer and we haven't already been here
980 if(bFindDown)
981 {
982 ft.chrg.cpMin = 0;
983 ft.chrg.cpMax = m_nInitialSearchPos;
984 }
985 else
986 {
987 ft.chrg.cpMin = pT->GetTextLength();
988 ft.chrg.cpMax = m_nInitialSearchPos;
989 }
990 m_nInitialSearchPos = m_nInitialSearchPos - pT->GetTextLength();
991
992 bRet = (pT->FindAndSelect(dwFlags, ft) != -1) ? TRUE : FALSE;
993 }
994
995 return bRet;
996 }
997
998 long FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft)
999 {
1000 T* pT = static_cast<T*>(this);
1001 LONG index = pT->FindText(dwFlags, ft);
1002 if(index != -1) // i.e. we found something
1003 pT->SetSel(ft.chrgText);
1004
1005 return index;
1006 }
1007 };
1008
1009 }; // namespace WTL
1010
1011 #endif // __ATLFIND_H__
+0
-3696
src/third_party/wtl/Include/atlframe.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLFRAME_H__
9 #define __ATLFRAME_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlframe.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLWIN_H__
18 #error atlframe.h requires atlwin.h to be included first
19 #endif
20
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // Classes in this file:
24 //
25 // CFrameWindowImpl<T, TBase, TWinTraits>
26 // CMDIWindow
27 // CMDIFrameWindowImpl<T, TBase, TWinTraits>
28 // CMDIChildWindowImpl<T, TBase, TWinTraits>
29 // COwnerDraw<T>
30 // CUpdateUIBase
31 // CUpdateUI<T>
32 // CDynamicUpdateUI<T>
33 // CAutoUpdateUI<T>
34 // CDialogResize<T>
35 // CDoubleBufferImpl<T>
36 // CDoubleBufferWindowImpl<T, TBase, TWinTraits>
37 //
38 // Global functions:
39 // AtlCreateSimpleToolBar()
40
41
42 namespace WTL
43 {
44
45 ///////////////////////////////////////////////////////////////////////////////
46 // CFrameWndClassInfo - Manages frame window Windows class information
47
48 class CFrameWndClassInfo
49 {
50 public:
51 #ifndef _WIN32_WCE
52 enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is the number of digits %p outputs
53 WNDCLASSEX m_wc;
54 #else // CE specific
55 enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string.
56 WNDCLASS m_wc;
57 #endif // !_WIN32_WCE
58 LPCTSTR m_lpszOrigName;
59 WNDPROC pWndProc;
60 LPCTSTR m_lpszCursorID;
61 BOOL m_bSystemCursor;
62 ATOM m_atom;
63 TCHAR m_szAutoName[cchAutoName];
64 UINT m_uCommonResourceID;
65
66 #ifndef _WIN32_WCE
67 ATOM Register(WNDPROC* pProc)
68 {
69 if (m_atom == 0)
70 {
71 CWindowCreateCriticalSectionLock lock;
72 if(FAILED(lock.Lock()))
73 {
74 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
75 ATLASSERT(FALSE);
76 return 0;
77 }
78
79 if(m_atom == 0)
80 {
81 HINSTANCE hInst = ModuleHelper::GetModuleInstance();
82
83 if (m_lpszOrigName != NULL)
84 {
85 ATLASSERT(pProc != NULL);
86 LPCTSTR lpsz = m_wc.lpszClassName;
87 WNDPROC proc = m_wc.lpfnWndProc;
88
89 WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
90 // try process local class first
91 if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
92 {
93 // try global class
94 if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
95 {
96 lock.Unlock();
97 return 0;
98 }
99 }
100 m_wc = wc;
101 pWndProc = m_wc.lpfnWndProc;
102 m_wc.lpszClassName = lpsz;
103 m_wc.lpfnWndProc = proc;
104 }
105 else
106 {
107 m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
108 }
109
110 m_wc.hInstance = hInst;
111 m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
112 if (m_wc.lpszClassName == NULL)
113 {
114 #if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
115 SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc);
116 #else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
117 SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
118 #endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
119 m_wc.lpszClassName = m_szAutoName;
120 }
121
122 WNDCLASSEX wcTemp = m_wc;
123 m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
124 if (m_atom == 0)
125 {
126 if(m_uCommonResourceID != 0) // use it if not zero
127 {
128 m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(),
129 MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON,
130 ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
131 m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(),
132 MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON,
133 ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
134 }
135 m_atom = ::RegisterClassEx(&m_wc);
136 }
137 }
138
139 lock.Unlock();
140 }
141
142 if (m_lpszOrigName != NULL)
143 {
144 ATLASSERT(pProc != NULL);
145 ATLASSERT(pWndProc != NULL);
146 *pProc = pWndProc;
147 }
148
149 return m_atom;
150 }
151 #else // CE specific
152 ATOM Register(WNDPROC* pProc)
153 {
154 if (m_atom == 0)
155 {
156 CWindowCreateCriticalSectionLock lock;
157 if(FAILED(lock.Lock()))
158 {
159 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
160 ATLASSERT(FALSE);
161 return 0;
162 }
163
164 if(m_atom == 0)
165 {
166 HINSTANCE hInst = ModuleHelper::GetModuleInstance();
167
168 if (m_lpszOrigName != NULL)
169 {
170 ATLASSERT(pProc != NULL);
171 LPCTSTR lpsz = m_wc.lpszClassName;
172 WNDPROC proc = m_wc.lpfnWndProc;
173
174 WNDCLASS wc = { 0 };
175 // try process local class first
176 if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
177 {
178 // try global class
179 if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
180 {
181 lock.Unlock();
182 return 0;
183 }
184 }
185 m_wc = wc;
186 pWndProc = m_wc.lpfnWndProc;
187 m_wc.lpszClassName = lpsz;
188 m_wc.lpfnWndProc = proc;
189 }
190 else
191 {
192 #if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
193 m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
194 #else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
195 m_wc.hCursor = NULL;
196 #endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
197 }
198
199 m_wc.hInstance = hInst;
200 m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
201 if (m_wc.lpszClassName == NULL)
202 {
203 wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
204 m_wc.lpszClassName = m_szAutoName;
205 }
206
207 WNDCLASS wcTemp = m_wc;
208 m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
209 if (m_atom == 0)
210 {
211 if(m_uCommonResourceID != 0) // use it if not zero
212 m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(),
213 MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON,
214 ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
215 m_atom = ::RegisterClass(&m_wc);
216 }
217 }
218
219 lock.Unlock();
220 }
221
222 if (m_lpszOrigName != NULL)
223 {
224 ATLASSERT(pProc != NULL);
225 ATLASSERT(pWndProc != NULL);
226 *pProc = pWndProc;
227 }
228
229 return m_atom;
230 }
231 #endif // _WIN32_WCE
232 };
233
234
235 ///////////////////////////////////////////////////////////////////////////////
236 // Macros for declaring frame window WNDCLASS
237
238 #ifndef _WIN32_WCE
239
240 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
241 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
242 { \
243 static WTL::CFrameWndClassInfo wc = \
244 { \
245 { sizeof(WNDCLASSEX), 0, StartWindowProc, \
246 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
247 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
248 }; \
249 return wc; \
250 }
251
252 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
253 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
254 { \
255 static WTL::CFrameWndClassInfo wc = \
256 { \
257 { sizeof(WNDCLASSEX), style, StartWindowProc, \
258 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
259 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
260 }; \
261 return wc; \
262 }
263
264 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
265 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
266 { \
267 static WTL::CFrameWndClassInfo wc = \
268 { \
269 { sizeof(WNDCLASSEX), 0, StartWindowProc, \
270 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
271 OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
272 }; \
273 return wc; \
274 }
275
276 #else // CE specific
277
278 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
279 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
280 { \
281 static WTL::CFrameWndClassInfo wc = \
282 { \
283 { 0, StartWindowProc, \
284 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
285 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
286 }; \
287 return wc; \
288 }
289
290 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
291 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
292 { \
293 static WTL::CFrameWndClassInfo wc = \
294 { \
295 { style, StartWindowProc, \
296 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
297 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
298 }; \
299 return wc; \
300 }
301
302 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
303 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
304 { \
305 static WTL::CFrameWndClassInfo wc = \
306 { \
307 { NULL, StartWindowProc, \
308 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
309 OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
310 }; \
311 return wc; \
312 }
313
314 #endif // !_WIN32_WCE
315
316
317 ///////////////////////////////////////////////////////////////////////////////
318 // CFrameWindowImpl
319
320 // Client window command chaining macro (only for frame windows)
321 #define CHAIN_CLIENT_COMMANDS() \
322 if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
323 ::SendMessage(m_hWndClient, uMsg, wParam, lParam);
324
325 // standard toolbar styles
326 #define ATL_SIMPLE_TOOLBAR_STYLE \
327 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
328 // toolbar in a rebar pane
329 #define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
330 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
331 // standard rebar styles
332 #if (_WIN32_IE >= 0x0400)
333 #define ATL_SIMPLE_REBAR_STYLE \
334 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
335 #else
336 #define ATL_SIMPLE_REBAR_STYLE \
337 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
338 #endif // !(_WIN32_IE >= 0x0400)
339 // rebar without borders
340 #if (_WIN32_IE >= 0x0400)
341 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
342 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
343 #else
344 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
345 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
346 #endif // !(_WIN32_IE >= 0x0400)
347
348 // command bar support
349 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
350
351 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND
352 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu
353 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu
354
355 struct _AtlFrameWnd_CmdBarPopupMenu
356 {
357 int cbSize;
358 HMENU hMenu;
359 UINT uFlags;
360 int x;
361 int y;
362 LPTPMPARAMS lptpm;
363 };
364
365 #define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
366
367 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
368
369
370 template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
371 class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits >
372 {
373 public:
374 DECLARE_FRAME_WND_CLASS(NULL, 0)
375
376 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
377 struct _ChevronMenuInfo
378 {
379 HMENU hMenu;
380 LPNMREBARCHEVRON lpnm;
381 bool bCmdBar;
382 };
383 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
384
385 // Data members
386 HWND m_hWndToolBar;
387 HWND m_hWndStatusBar;
388 HWND m_hWndClient;
389
390 #ifdef _WIN32_WCE
391 HWND m_hWndCECommandBar;
392 #endif // _WIN32_WCE
393
394 HACCEL m_hAccel;
395
396 // Constructor
397 CFrameWindowImplBase() :
398 m_hWndToolBar(NULL),
399 m_hWndStatusBar(NULL),
400 m_hWndClient(NULL),
401 #ifdef _WIN32_WCE
402 m_hWndCECommandBar(NULL),
403 #endif // _WIN32_WCE
404 m_hAccel(NULL)
405 { }
406
407 // Methods
408 HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
409 {
410 ATLASSERT(m_hWnd == NULL);
411
412 #if (_ATL_VER >= 0x0800)
413 // Allocate the thunk structure here, where we can fail gracefully.
414 BOOL bRet = m_thunk.Init(NULL, NULL);
415 if(bRet == FALSE)
416 {
417 ::SetLastError(ERROR_OUTOFMEMORY);
418 return NULL;
419 }
420 #endif // (_ATL_VER >= 0x0800)
421
422 if(atom == 0)
423 return NULL;
424
425 ModuleHelper::AddCreateWndData(&m_thunk.cd, this);
426
427 if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
428 MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
429 if(rect.m_lpRect == NULL)
430 rect.m_lpRect = &TBase::rcDefault;
431
432 HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
433 dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
434 rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
435 ModuleHelper::GetModuleInstance(), lpCreateParam);
436
437 ATLASSERT(hWnd == NULL || m_hWnd == hWnd);
438
439 return hWnd;
440 }
441
442 static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
443 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
444 {
445 HINSTANCE hInst = ModuleHelper::GetResourceInstance();
446 HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
447 if (hRsrc == NULL)
448 return NULL;
449
450 HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
451 if (hGlobal == NULL)
452 return NULL;
453
454 _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
455 if (pData == NULL)
456 return NULL;
457 ATLASSERT(pData->wVersion == 1);
458
459 WORD* pItems = pData->items();
460 int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
461 CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff;
462 TBBUTTON* pTBBtn = buff.Allocate(nItems);
463 ATLASSERT(pTBBtn != NULL);
464 if(pTBBtn == NULL)
465 return NULL;
466
467 const int cxSeparator = 8;
468
469 // set initial separator (half width)
470 if(bInitialSeparator)
471 {
472 pTBBtn[0].iBitmap = cxSeparator / 2;
473 pTBBtn[0].idCommand = 0;
474 pTBBtn[0].fsState = 0;
475 pTBBtn[0].fsStyle = BTNS_SEP;
476 pTBBtn[0].dwData = 0;
477 pTBBtn[0].iString = 0;
478 }
479
480 int nBmp = 0;
481 for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
482 {
483 if(pItems[i] != 0)
484 {
485 pTBBtn[j].iBitmap = nBmp++;
486 pTBBtn[j].idCommand = pItems[i];
487 pTBBtn[j].fsState = TBSTATE_ENABLED;
488 pTBBtn[j].fsStyle = BTNS_BUTTON;
489 pTBBtn[j].dwData = 0;
490 pTBBtn[j].iString = 0;
491 }
492 else
493 {
494 pTBBtn[j].iBitmap = cxSeparator;
495 pTBBtn[j].idCommand = 0;
496 pTBBtn[j].fsState = 0;
497 pTBBtn[j].fsStyle = BTNS_SEP;
498 pTBBtn[j].dwData = 0;
499 pTBBtn[j].iString = 0;
500 }
501 }
502
503 #ifndef _WIN32_WCE
504 HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
505 if(hWnd == NULL)
506 {
507 ATLASSERT(FALSE);
508 return NULL;
509 }
510 #else // CE specific
511 dwStyle;
512 nID;
513 // The toolbar must go onto the existing CommandBar or MenuBar
514 HWND hWnd = hWndParent;
515 #endif // _WIN32_WCE
516
517 ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
518
519 // check if font is taller than our bitmaps
520 CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
521 if(font.IsNull())
522 font = (HFONT)::GetStockObject(SYSTEM_FONT);
523 LOGFONT lf = { 0 };
524 font.GetLogFont(lf);
525 WORD cyFontHeight = (WORD)abs(lf.lfHeight);
526
527 #ifndef _WIN32_WCE
528 WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID);
529 if(bitsPerPixel > 4)
530 {
531 COLORREF crMask = CLR_DEFAULT;
532 if(bitsPerPixel == 32)
533 {
534 // 32-bit color bitmap with alpha channel (valid for Windows XP and later)
535 crMask = CLR_NONE;
536 }
537 HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
538 ATLASSERT(hImageList != NULL);
539 ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
540 }
541 else
542 #endif // !_WIN32_WCE
543 {
544 TBADDBITMAP tbab = { 0 };
545 tbab.hInst = hInst;
546 tbab.nID = nResourceID;
547 ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
548 }
549
550 ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
551 ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, __max(pData->wHeight, cyFontHeight)));
552 const int cxyButtonMargin = 7;
553 ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, __max(pData->wHeight, cyFontHeight) + cxyButtonMargin));
554
555 return hWnd;
556 }
557
558 #ifndef _WIN32_WCE
559 static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
560 {
561 // Ensure style combinations for proper rebar painting
562 if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
563 dwStyle &= ~WS_BORDER;
564 else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
565 dwStyle |= CCS_NODIVIDER;
566
567 // Create rebar window
568 HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
569 if(hWndReBar == NULL)
570 {
571 ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
572 return NULL;
573 }
574
575 // Initialize and send the REBARINFO structure
576 REBARINFO rbi = { sizeof(REBARINFO), 0 };
577 if(::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi) == 0)
578 {
579 ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n"));
580 ::DestroyWindow(hWndReBar);
581 return NULL;
582 }
583
584 return hWndReBar;
585 }
586
587 BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
588 {
589 ATLASSERT(!::IsWindow(m_hWndToolBar));
590 m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID);
591 return (m_hWndToolBar != NULL);
592 }
593
594 static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
595 {
596 ATLASSERT(::IsWindow(hWndReBar)); // must be already created
597 #ifdef _DEBUG
598 // block - check if this is really a rebar
599 {
600 TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 };
601 ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
602 ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
603 }
604 #endif // _DEBUG
605 ATLASSERT(::IsWindow(hWndBand)); // must be already created
606
607 // Get number of buttons on the toolbar
608 int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L);
609
610 // Set band info structure
611 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
612 #if (_WIN32_IE >= 0x0400)
613 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE;
614 #else
615 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE;
616 #endif // !(_WIN32_IE >= 0x0400)
617 if(lpstrTitle != NULL)
618 rbBand.fMask |= RBBIM_TEXT;
619 rbBand.fStyle = RBBS_CHILDEDGE;
620 #if (_WIN32_IE >= 0x0500)
621 if(nBtnCount > 0) // add chevron style for toolbar with buttons
622 rbBand.fStyle |= RBBS_USECHEVRON;
623 #endif // (_WIN32_IE >= 0x0500)
624 if(bNewRow)
625 rbBand.fStyle |= RBBS_BREAK;
626
627 rbBand.lpText = (LPTSTR)lpstrTitle;
628 rbBand.hwndChild = hWndBand;
629 if(nID == 0) // calc band ID
630 nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
631 rbBand.wID = nID;
632
633 // Calculate the size of the band
634 BOOL bRet = FALSE;
635 RECT rcTmp = { 0 };
636 if(nBtnCount > 0)
637 {
638 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp);
639 ATLASSERT(bRet);
640 rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right;
641 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
642 if(bFullWidthAlways)
643 {
644 rbBand.cxMinChild = rbBand.cx;
645 }
646 else if(lpstrTitle == NULL)
647 {
648 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp);
649 ATLASSERT(bRet);
650 rbBand.cxMinChild = rcTmp.right;
651 }
652 else
653 {
654 rbBand.cxMinChild = 0;
655 }
656 }
657 else // no buttons, either not a toolbar or really has no buttons
658 {
659 bRet = ::GetWindowRect(hWndBand, &rcTmp);
660 ATLASSERT(bRet);
661 rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left);
662 rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0;
663 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
664 }
665
666 #if (_WIN32_IE >= 0x0400)
667 rbBand.cxIdeal = rbBand.cx;
668 #endif // (_WIN32_IE >= 0x0400)
669
670 // Add the band
671 LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
672 if(lRes == 0)
673 {
674 ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n"));
675 return FALSE;
676 }
677
678 #if (_WIN32_IE >= 0x0501)
679 DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L);
680 ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
681 #endif // (_WIN32_IE >= 0x0501)
682
683 return TRUE;
684 }
685
686 BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
687 {
688 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar
689 ATLASSERT(::IsWindow(hWndBand)); // must be created
690 return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways);
691 }
692
693 #if (_WIN32_IE >= 0x0400)
694 void SizeSimpleReBarBands()
695 {
696 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar
697
698 int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L);
699
700 for(int i = 0; i < nCount; i++)
701 {
702 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
703 rbBand.fMask = RBBIM_SIZE;
704 BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand);
705 ATLASSERT(bRet);
706 RECT rect = { 0 };
707 ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect);
708 rbBand.cx += rect.left + rect.right;
709 bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand);
710 ATLASSERT(bRet);
711 }
712 }
713 #endif // (_WIN32_IE >= 0x0400)
714 #endif // _WIN32_WCE
715
716 #ifndef _WIN32_WCE
717 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
718 #else // CE specific
719 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
720 #endif // _WIN32_WCE
721 {
722 ATLASSERT(!::IsWindow(m_hWndStatusBar));
723 m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
724 return (m_hWndStatusBar != NULL);
725 }
726
727 #ifndef _WIN32_WCE
728 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
729 #else // CE specific
730 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
731 #endif // _WIN32_WCE
732 {
733 const int cchMax = 128; // max text length is 127 for status bars (+1 for null)
734 TCHAR szText[cchMax] = { 0 };
735 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
736 return CreateSimpleStatusBar(szText, dwStyle, nID);
737 }
738
739 #ifdef _WIN32_WCE
740 BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1)
741 {
742 ATLASSERT(m_hWndCECommandBar == NULL);
743 ATLASSERT(m_hWndToolBar == NULL);
744
745 m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID);
746 if(m_hWndCECommandBar == NULL)
747 return FALSE;
748
749 m_hWndToolBar = m_hWndCECommandBar;
750
751 BOOL bRet = TRUE;
752
753 if(pszMenu != NULL)
754 bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton);
755
756 bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0);
757
758 return bRet;
759 }
760
761 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
762 BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0)
763 {
764 ATLASSERT(m_hWndCECommandBar == NULL);
765
766 SHMENUBARINFO mbi = { 0 };
767 mbi.cbSize = sizeof(mbi);
768 mbi.hwndParent = m_hWnd;
769 mbi.dwFlags = dwFlags;
770 mbi.nToolBarId = nToolBarId;
771 mbi.hInstRes = ModuleHelper::GetResourceInstance();
772 mbi.nBmpId = nBmpId;
773 mbi.cBmpImages = cBmpImages;
774 mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar
775
776 BOOL bRet = ::SHCreateMenuBar(&mbi);
777 if(bRet != FALSE)
778 {
779 m_hWndCECommandBar = mbi.hwndMB;
780 SizeToMenuBar();
781 }
782
783 return bRet;
784 }
785
786 void SizeToMenuBar() // for menu bar only
787 {
788 ATLASSERT(::IsWindow(m_hWnd));
789 ATLASSERT(::IsWindow(m_hWndCECommandBar));
790
791 RECT rect = { 0 };
792 GetWindowRect(&rect);
793 RECT rectMB = { 0 };
794 ::GetWindowRect(m_hWndCECommandBar, &rectMB);
795 int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
796 SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
797 }
798 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
799 #endif // _WIN32_WCE
800
801 void UpdateLayout(BOOL bResizeBars = TRUE)
802 {
803 RECT rect = { 0 };
804 GetClientRect(&rect);
805
806 // position bars and offset their dimensions
807 UpdateBarsPosition(rect, bResizeBars);
808
809 // resize client window
810 if(m_hWndClient != NULL)
811 ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
812 rect.right - rect.left, rect.bottom - rect.top,
813 SWP_NOZORDER | SWP_NOACTIVATE);
814 }
815
816 void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
817 {
818 // resize toolbar
819 if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
820 {
821 if(bResizeBars != FALSE)
822 {
823 ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
824 ::InvalidateRect(m_hWndToolBar, NULL, TRUE);
825 }
826 RECT rectTB = { 0 };
827 ::GetWindowRect(m_hWndToolBar, &rectTB);
828 rect.top += rectTB.bottom - rectTB.top;
829 }
830
831 // resize status bar
832 if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
833 {
834 if(bResizeBars != FALSE)
835 ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
836 RECT rectSB = { 0 };
837 ::GetWindowRect(m_hWndStatusBar, &rectSB);
838 rect.bottom -= rectSB.bottom - rectSB.top;
839 }
840 }
841
842 BOOL PreTranslateMessage(MSG* pMsg)
843 {
844 if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
845 return TRUE;
846 return FALSE;
847 }
848
849 BEGIN_MSG_MAP(CFrameWindowImplBase)
850 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
851 #ifndef _WIN32_WCE
852 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
853 #endif // !_WIN32_WCE
854 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
855 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
856 #ifndef _WIN32_WCE
857 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA)
858 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW)
859 #endif // !_WIN32_WCE
860 END_MSG_MAP()
861
862 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
863 {
864 if(m_hWndClient != NULL) // view will paint itself instead
865 return 1;
866
867 bHandled = FALSE;
868 return 0;
869 }
870
871 #ifndef _WIN32_WCE
872 LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
873 {
874 bHandled = FALSE;
875
876 if(m_hWndStatusBar == NULL)
877 return 1;
878
879 WORD wFlags = HIWORD(wParam);
880 if(wFlags == 0xFFFF && lParam == NULL) // menu closing
881 {
882 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
883 }
884 else
885 {
886 const int cchBuff = 256;
887 TCHAR szBuff[cchBuff] = { 0 };
888 if(!(wFlags & MF_POPUP))
889 {
890 WORD wID = LOWORD(wParam);
891 // check for special cases
892 if(wID >= 0xF000 && wID < 0xF1F0) // system menu IDs
893 wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
894 else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST) // MRU items
895 wID = ATL_IDS_MRU_FILE;
896 else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD) // MDI child windows
897 wID = ATL_IDS_MDICHILD;
898
899 int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff);
900 for(int i = 0; i < nRet; i++)
901 {
902 if(szBuff[i] == _T('\n'))
903 {
904 szBuff[i] = 0;
905 break;
906 }
907 }
908 }
909 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
910 ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
911 }
912
913 return 1;
914 }
915 #endif // !_WIN32_WCE
916
917 LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
918 {
919 if(m_hWndClient != NULL)
920 ::SetFocus(m_hWndClient);
921
922 bHandled = FALSE;
923 return 1;
924 }
925
926 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
927 {
928 if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0)
929 ::PostQuitMessage(1);
930
931 bHandled = FALSE;
932 return 1;
933 }
934
935 #ifndef _WIN32_WCE
936 LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
937 {
938 LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh;
939 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
940 {
941 const int cchBuff = 256;
942 char szBuff[cchBuff] = { 0 };
943 int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
944 for(int i = 0; i < nRet; i++)
945 {
946 if(szBuff[i] == '\n')
947 {
948 SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
949 break;
950 }
951 }
952 #if (_WIN32_IE >= 0x0300)
953 if(nRet > 0) // string was loaded, save it
954 pDispInfo->uFlags |= TTF_DI_SETITEM;
955 #endif // (_WIN32_IE >= 0x0300)
956 }
957
958 return 0;
959 }
960
961 LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
962 {
963 LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh;
964 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
965 {
966 const int cchBuff = 256;
967 wchar_t szBuff[cchBuff] = { 0 };
968 int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
969 for(int i = 0; i < nRet; i++)
970 {
971 if(szBuff[i] == L'\n')
972 {
973 SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
974 break;
975 }
976 }
977 #if (_WIN32_IE >= 0x0300)
978 if(nRet > 0) // string was loaded, save it
979 pDispInfo->uFlags |= TTF_DI_SETITEM;
980 #endif // (_WIN32_IE >= 0x0300)
981 }
982
983 return 0;
984 }
985 #endif // !_WIN32_WCE
986
987 // Implementation - chevron menu support
988 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
989 bool PrepareChevronMenu(_ChevronMenuInfo& cmi)
990 {
991 // get rebar and toolbar
992 REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
993 rbbi.fMask = RBBIM_CHILD;
994 BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi);
995 ATLASSERT(bRet);
996
997 // assume the band is a toolbar
998 ATL::CWindow wnd = rbbi.hwndChild;
999 int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT);
1000 if(nCount <= 0) // probably not a toolbar
1001 return false;
1002
1003 // check if it's a command bar
1004 CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU);
1005 cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL);
1006
1007 // build a menu from hidden items
1008 CMenuHandle menu;
1009 bRet = menu.CreatePopupMenu();
1010 ATLASSERT(bRet);
1011 RECT rcClient = { 0 };
1012 bRet = wnd.GetClientRect(&rcClient);
1013 ATLASSERT(bRet);
1014 for(int i = 0; i < nCount; i++)
1015 {
1016 TBBUTTON tbb = { 0 };
1017 bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb);
1018 ATLASSERT(bRet);
1019 // skip hidden buttons
1020 if((tbb.fsState & TBSTATE_HIDDEN) != 0)
1021 continue;
1022 RECT rcButton = { 0 };
1023 bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton);
1024 ATLASSERT(bRet);
1025 bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0);
1026 if((rcButton.right > rcClient.right) || (rcButton.bottom > rcClient.bottom))
1027 {
1028 if(tbb.fsStyle & BTNS_SEP)
1029 {
1030 if(menu.GetMenuItemCount() > 0)
1031 menu.AppendMenu(MF_SEPARATOR);
1032 }
1033 else if(cmi.bCmdBar)
1034 {
1035 const int cchBuff = 200;
1036 TCHAR szBuff[cchBuff] = { 0 };
1037 CMenuItemInfo mii;
1038 mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
1039 mii.dwTypeData = szBuff;
1040 mii.cch = cchBuff;
1041 bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
1042 ATLASSERT(bRet);
1043 // Note: CmdBar currently supports only drop-down items
1044 ATLASSERT(::IsMenu(mii.hSubMenu));
1045 bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
1046 ATLASSERT(bRet);
1047 }
1048 else
1049 {
1050 // get button's text
1051 const int cchBuff = 200;
1052 TCHAR szBuff[cchBuff] = { 0 };
1053 LPCTSTR lpstrText = szBuff;
1054 TBBUTTONINFO tbbi = { 0 };
1055 tbbi.cbSize = sizeof(TBBUTTONINFO);
1056 tbbi.dwMask = TBIF_TEXT;
1057 tbbi.pszText = szBuff;
1058 tbbi.cchText = cchBuff;
1059 if((wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1) || (szBuff[0] == 0))
1060 {
1061 // no text for this button, try a resource string
1062 lpstrText = _T("");
1063 int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff);
1064 for(int n = 0; n < nRet; n++)
1065 {
1066 if(szBuff[n] == _T('\n'))
1067 {
1068 lpstrText = &szBuff[n + 1];
1069 break;
1070 }
1071 }
1072 }
1073 bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText);
1074 ATLASSERT(bRet);
1075 }
1076 }
1077 }
1078
1079 if(menu.GetMenuItemCount() == 0) // no hidden buttons after all
1080 {
1081 menu.DestroyMenu();
1082 ::MessageBeep((UINT)-1);
1083 return false;
1084 }
1085
1086 cmi.hMenu = menu;
1087 return true;
1088 }
1089
1090 void DisplayChevronMenu(_ChevronMenuInfo& cmi)
1091 {
1092 #ifndef TPM_VERPOSANIMATION
1093 const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag
1094 #endif
1095 // convert chevron rect to screen coordinates
1096 ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
1097 POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom };
1098 wndFrom.MapWindowPoints(NULL, &pt, 1);
1099 RECT rc = cmi.lpnm->rc;
1100 wndFrom.MapWindowPoints(NULL, &rc);
1101 // set up flags and rect
1102 UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
1103 TPMPARAMS TPMParams = { 0 };
1104 TPMParams.cbSize = sizeof(TPMPARAMS);
1105 TPMParams.rcExclude = rc;
1106 // check if this window has a command bar
1107 HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
1108 if(::IsWindow(hWndCmdBar))
1109 {
1110 CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams };
1111 ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu);
1112 }
1113 else
1114 {
1115 CMenuHandle menu = cmi.hMenu;
1116 menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams);
1117 }
1118 }
1119
1120 void CleanupChevronMenu(_ChevronMenuInfo& cmi)
1121 {
1122 CMenuHandle menu = cmi.hMenu;
1123 // if menu is from a command bar, detach submenus so they are not destroyed
1124 if(cmi.bCmdBar)
1125 {
1126 for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
1127 menu.RemoveMenu(i, MF_BYPOSITION);
1128 }
1129 // destroy menu
1130 menu.DestroyMenu();
1131 // convert chevron rect to screen coordinates
1132 ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
1133 RECT rc = cmi.lpnm->rc;
1134 wndFrom.MapWindowPoints(NULL, &rc);
1135 // eat next message if click is on the same button
1136 MSG msg = { 0 };
1137 if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt))
1138 ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
1139 }
1140 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1141 };
1142
1143
1144 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
1145 class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
1146 {
1147 public:
1148 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1149 DWORD dwStyle = 0, DWORD dwExStyle = 0,
1150 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
1151 {
1152 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
1153
1154 dwStyle = T::GetWndStyle(dwStyle);
1155 dwExStyle = T::GetWndExStyle(dwExStyle);
1156
1157 if(rect.m_lpRect == NULL)
1158 rect.m_lpRect = &TBase::rcDefault;
1159
1160 return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
1161 }
1162
1163 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
1164 {
1165 const int cchName = 256;
1166 TCHAR szWindowName[cchName] = { 0 };
1167 #ifndef _WIN32_WCE
1168 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1169 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1170 #else // CE specific
1171 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1172
1173 // This always needs to be NULL for Windows CE.
1174 // Frame Window menus have to go onto the CommandBar.
1175 // Use CreateSimpleCECommandBar
1176 HMENU hMenu = NULL;
1177 #endif // _WIN32_WCE
1178
1179 T* pT = static_cast<T*>(this);
1180 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
1181
1182 if(hWnd != NULL)
1183 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1184
1185 return hWnd;
1186 }
1187
1188 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1189 {
1190 if(nResourceID == 0)
1191 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1192 #ifndef _WIN32_WCE
1193 ATLASSERT(!::IsWindow(m_hWndToolBar));
1194 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
1195 return (m_hWndToolBar != NULL);
1196 #else // CE specific
1197 HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
1198 return (hWnd != NULL);
1199 #endif // _WIN32_WCE
1200 }
1201
1202 #ifdef _WIN32_WCE
1203 // CE specific variant that returns the handle of the toolbar
1204 HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1205 {
1206 if(nResourceID == 0)
1207 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1208
1209 return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
1210 }
1211 #endif // _WIN32_WCE
1212
1213 // message map and handlers
1214 typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass;
1215
1216 BEGIN_MSG_MAP(CFrameWindowImpl)
1217 MESSAGE_HANDLER(WM_SIZE, OnSize)
1218 #ifndef _ATL_NO_REBAR_SUPPORT
1219 #if (_WIN32_IE >= 0x0400)
1220 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
1221 #endif // (_WIN32_IE >= 0x0400)
1222 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1223 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
1224 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1225 #endif // !_ATL_NO_REBAR_SUPPORT
1226 CHAIN_MSG_MAP(_baseClass)
1227 END_MSG_MAP()
1228
1229 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1230 {
1231 if(wParam != SIZE_MINIMIZED)
1232 {
1233 T* pT = static_cast<T*>(this);
1234 pT->UpdateLayout();
1235 }
1236 bHandled = FALSE;
1237 return 1;
1238 }
1239
1240 #ifndef _ATL_NO_REBAR_SUPPORT
1241 #if (_WIN32_IE >= 0x0400)
1242 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
1243 {
1244 T* pT = static_cast<T*>(this);
1245 pT->UpdateLayout(FALSE);
1246 return 0;
1247 }
1248 #endif // (_WIN32_IE >= 0x0400)
1249
1250 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1251 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1252 {
1253 T* pT = static_cast<T*>(this);
1254 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
1255 if(!pT->PrepareChevronMenu(cmi))
1256 {
1257 bHandled = FALSE;
1258 return 1;
1259 }
1260 // display a popup menu with hidden items
1261 pT->DisplayChevronMenu(cmi);
1262 // cleanup
1263 pT->CleanupChevronMenu(cmi);
1264 return 0;
1265 }
1266 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1267 #endif // !_ATL_NO_REBAR_SUPPORT
1268 };
1269
1270
1271 ///////////////////////////////////////////////////////////////////////////////
1272 // AtlCreateSimpleToolBar - helper for creating simple toolbars
1273
1274 #ifndef _WIN32_WCE
1275
1276 inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
1277 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1278 {
1279 return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID);
1280 }
1281
1282 #endif // !_WIN32_WCE
1283
1284
1285 ///////////////////////////////////////////////////////////////////////////////
1286 // CMDIWindow
1287
1288 #ifndef _WIN32_WCE
1289
1290 #ifndef _WTL_MDIWINDOWMENU_TEXT
1291 #define _WTL_MDIWINDOWMENU_TEXT _T("&Window")
1292 #endif
1293
1294 class CMDIWindow : public ATL::CWindow
1295 {
1296 public:
1297 // Data members
1298 HWND m_hWndMDIClient;
1299 HMENU m_hMenu;
1300
1301 // Constructors
1302 CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL)
1303 { }
1304
1305 CMDIWindow& operator =(HWND hWnd)
1306 {
1307 m_hWnd = hWnd;
1308 return *this;
1309 }
1310
1311 // Operations
1312 HWND MDIGetActive(BOOL* lpbMaximized = NULL)
1313 {
1314 ATLASSERT(::IsWindow(m_hWndMDIClient));
1315 return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
1316 }
1317
1318 void MDIActivate(HWND hWndChildToActivate)
1319 {
1320 ATLASSERT(::IsWindow(m_hWndMDIClient));
1321 ATLASSERT(::IsWindow(hWndChildToActivate));
1322 ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
1323 }
1324
1325 void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
1326 {
1327 ATLASSERT(::IsWindow(m_hWndMDIClient));
1328 ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
1329 ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
1330 }
1331
1332 void MDIMaximize(HWND hWndChildToMaximize)
1333 {
1334 ATLASSERT(::IsWindow(m_hWndMDIClient));
1335 ATLASSERT(::IsWindow(hWndChildToMaximize));
1336 ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
1337 }
1338
1339 void MDIRestore(HWND hWndChildToRestore)
1340 {
1341 ATLASSERT(::IsWindow(m_hWndMDIClient));
1342 ATLASSERT(::IsWindow(hWndChildToRestore));
1343 ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0);
1344 }
1345
1346 void MDIDestroy(HWND hWndChildToDestroy)
1347 {
1348 ATLASSERT(::IsWindow(m_hWndMDIClient));
1349 ATLASSERT(::IsWindow(hWndChildToDestroy));
1350 ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
1351 }
1352
1353 BOOL MDICascade(UINT uFlags = 0)
1354 {
1355 ATLASSERT(::IsWindow(m_hWndMDIClient));
1356 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
1357 }
1358
1359 BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
1360 {
1361 ATLASSERT(::IsWindow(m_hWndMDIClient));
1362 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
1363 }
1364
1365 void MDIIconArrange()
1366 {
1367 ATLASSERT(::IsWindow(m_hWndMDIClient));
1368 ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
1369 }
1370
1371 HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
1372 {
1373 ATLASSERT(::IsWindow(m_hWndMDIClient));
1374 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
1375 }
1376
1377 HMENU MDIRefreshMenu()
1378 {
1379 ATLASSERT(::IsWindow(m_hWndMDIClient));
1380 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
1381 }
1382
1383 // Additional operations
1384 static HMENU GetStandardWindowMenu(HMENU hMenu)
1385 {
1386 int nCount = ::GetMenuItemCount(hMenu);
1387 if(nCount == -1)
1388 return NULL;
1389 int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
1390 if(nLen == 0)
1391 return NULL;
1392 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
1393 LPTSTR lpszText = buff.Allocate(nLen + 1);
1394 if(lpszText == NULL)
1395 return NULL;
1396 if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
1397 return NULL;
1398 if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0)
1399 return NULL;
1400 return ::GetSubMenu(hMenu, nCount - 2);
1401 }
1402
1403 void SetMDIFrameMenu()
1404 {
1405 HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
1406 MDISetMenu(m_hMenu, hWindowMenu);
1407 MDIRefreshMenu();
1408 ::DrawMenuBar(GetMDIFrame());
1409 }
1410
1411 HWND GetMDIFrame() const
1412 {
1413 return ::GetParent(m_hWndMDIClient);
1414 }
1415 };
1416
1417 #endif // !_WIN32_WCE
1418
1419
1420 ///////////////////////////////////////////////////////////////////////////////
1421 // CMDIFrameWindowImpl
1422
1423 #ifndef _WIN32_WCE
1424
1425 // MDI child command chaining macro (only for MDI frame windows)
1426 #define CHAIN_MDI_CHILD_COMMANDS() \
1427 if(uMsg == WM_COMMAND) \
1428 { \
1429 HWND hWndChild = MDIGetActive(); \
1430 if(hWndChild != NULL) \
1431 ::SendMessage(hWndChild, uMsg, wParam, lParam); \
1432 }
1433
1434 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
1435 class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
1436 {
1437 public:
1438 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1439 DWORD dwStyle = 0, DWORD dwExStyle = 0,
1440 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
1441 {
1442 m_hMenu = hMenu;
1443 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
1444
1445 dwStyle = T::GetWndStyle(dwStyle);
1446 dwExStyle = T::GetWndExStyle(dwExStyle);
1447
1448 if(rect.m_lpRect == NULL)
1449 rect.m_lpRect = &TBase::rcDefault;
1450
1451 return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
1452 }
1453
1454 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
1455 {
1456 const int cchName = 256;
1457 TCHAR szWindowName[cchName] = { 0 };
1458 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1459 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1460
1461 T* pT = static_cast<T*>(this);
1462 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
1463
1464 if(hWnd != NULL)
1465 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1466
1467 return hWnd;
1468 }
1469
1470 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1471 {
1472 ATLASSERT(!::IsWindow(m_hWndToolBar));
1473 if(nResourceID == 0)
1474 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1475 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
1476 return (m_hWndToolBar != NULL);
1477 }
1478
1479 virtual WNDPROC GetWindowProc()
1480 {
1481 return MDIFrameWindowProc;
1482 }
1483
1484 static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1485 {
1486 CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
1487 // set a ptr to this message and save the old value
1488 #if (_ATL_VER >= 0x0700)
1489 ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1490 const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
1491 #else // !(_ATL_VER >= 0x0700)
1492 MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
1493 const MSG* pOldMsg = pThis->m_pCurrentMsg;
1494 #endif // !(_ATL_VER >= 0x0700)
1495 pThis->m_pCurrentMsg = &msg;
1496 // pass to the message map to process
1497 LRESULT lRes = 0;
1498 BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
1499 // restore saved value for the current message
1500 ATLASSERT(pThis->m_pCurrentMsg == &msg);
1501 pThis->m_pCurrentMsg = pOldMsg;
1502 // do the default processing if message was not handled
1503 if(!bRet)
1504 {
1505 if(uMsg != WM_NCDESTROY)
1506 {
1507 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
1508 }
1509 else
1510 {
1511 // unsubclass, if needed
1512 LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
1513 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
1514 if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
1515 ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
1516 #if (_ATL_VER >= 0x0700)
1517 // mark window as destryed
1518 pThis->m_dwState |= WINSTATE_DESTROYED;
1519 #else // !(_ATL_VER >= 0x0700)
1520 // clear out window handle
1521 HWND hWnd = pThis->m_hWnd;
1522 pThis->m_hWnd = NULL;
1523 // clean up after window is destroyed
1524 pThis->OnFinalMessage(hWnd);
1525 #endif // !(_ATL_VER >= 0x0700)
1526 }
1527 }
1528 #if (_ATL_VER >= 0x0700)
1529 if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL)
1530 {
1531 // clear out window handle
1532 HWND hWndThis = pThis->m_hWnd;
1533 pThis->m_hWnd = NULL;
1534 pThis->m_dwState &= ~WINSTATE_DESTROYED;
1535 // clean up after window is destroyed
1536 pThis->OnFinalMessage(hWndThis);
1537 }
1538 #endif // (_ATL_VER >= 0x0700)
1539 return lRes;
1540 }
1541
1542 // Overriden to call DefWindowProc which uses DefFrameProc
1543 LRESULT DefWindowProc()
1544 {
1545 const MSG* pMsg = m_pCurrentMsg;
1546 LRESULT lRes = 0;
1547 if (pMsg != NULL)
1548 lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
1549 return lRes;
1550 }
1551
1552 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
1553 {
1554 return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam);
1555 }
1556
1557 BOOL PreTranslateMessage(MSG* pMsg)
1558 {
1559 if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
1560 return TRUE;
1561 return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg);
1562 }
1563
1564 HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
1565 {
1566 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
1567 DWORD dwExStyle = WS_EX_CLIENTEDGE;
1568
1569 CLIENTCREATESTRUCT ccs = { 0 };
1570 ccs.hWindowMenu = hWindowMenu;
1571 ccs.idFirstChild = nFirstChildID;
1572
1573 if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0)
1574 {
1575 // parent MDI frame's scroll styles move to the MDICLIENT
1576 dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL));
1577
1578 // fast way to turn off the scrollbar bits (without a resize)
1579 ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED);
1580 }
1581
1582 // Create MDICLIENT window
1583 m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL,
1584 dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID),
1585 ModuleHelper::GetModuleInstance(), (LPVOID)&ccs);
1586 if (m_hWndClient == NULL)
1587 {
1588 ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create MDICLIENT.\n"));
1589 return NULL;
1590 }
1591
1592 // Move it to the top of z-order
1593 ::BringWindowToTop(m_hWndClient);
1594
1595 // set as MDI client window
1596 m_hWndMDIClient = m_hWndClient;
1597
1598 // update to proper size
1599 T* pT = static_cast<T*>(this);
1600 pT->UpdateLayout();
1601
1602 return m_hWndClient;
1603 }
1604
1605 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass;
1606
1607 BEGIN_MSG_MAP(CMDIFrameWindowImpl)
1608 MESSAGE_HANDLER(WM_SIZE, OnSize)
1609 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
1610 MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
1611 #ifndef _ATL_NO_REBAR_SUPPORT
1612 #if (_WIN32_IE >= 0x0400)
1613 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
1614 #endif // (_WIN32_IE >= 0x0400)
1615 #if (_WIN32_IE >= 0x0500)
1616 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
1617 #endif // (_WIN32_IE >= 0x0500)
1618 #endif // !_ATL_NO_REBAR_SUPPORT
1619 CHAIN_MSG_MAP(_baseClass)
1620 END_MSG_MAP()
1621
1622 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1623 {
1624 if(wParam != SIZE_MINIMIZED)
1625 {
1626 T* pT = static_cast<T*>(this);
1627 pT->UpdateLayout();
1628 }
1629 // message must be handled, otherwise DefFrameProc would resize the client again
1630 return 0;
1631 }
1632
1633 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1634 {
1635 // don't allow CFrameWindowImplBase to handle this one
1636 return DefWindowProc(uMsg, wParam, lParam);
1637 }
1638
1639 LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1640 {
1641 SetMDIFrameMenu();
1642 return 0;
1643 }
1644
1645 #ifndef _ATL_NO_REBAR_SUPPORT
1646 #if (_WIN32_IE >= 0x0400)
1647 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
1648 {
1649 T* pT = static_cast<T*>(this);
1650 pT->UpdateLayout(FALSE);
1651 return 0;
1652 }
1653 #endif // (_WIN32_IE >= 0x0400)
1654
1655 #if (_WIN32_IE >= 0x0500)
1656 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1657 {
1658 T* pT = static_cast<T*>(this);
1659 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
1660 if(!pT->PrepareChevronMenu(cmi))
1661 {
1662 bHandled = FALSE;
1663 return 1;
1664 }
1665 // display a popup menu with hidden items
1666 pT->DisplayChevronMenu(cmi);
1667 // cleanup
1668 pT->CleanupChevronMenu(cmi);
1669 return 0;
1670 }
1671 #endif // (_WIN32_IE >= 0x0500)
1672 #endif // !_ATL_NO_REBAR_SUPPORT
1673 };
1674
1675 #endif // !_WIN32_WCE
1676
1677
1678 ///////////////////////////////////////////////////////////////////////////////
1679 // CMDIChildWindowImpl
1680
1681 #ifndef _WIN32_WCE
1682
1683 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CMDIChildWinTraits>
1684 class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
1685 {
1686 public:
1687 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1688 DWORD dwStyle = 0, DWORD dwExStyle = 0,
1689 UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
1690 {
1691 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
1692
1693 if(nMenuID != 0)
1694 m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
1695
1696 dwStyle = T::GetWndStyle(dwStyle);
1697 dwExStyle = T::GetWndExStyle(dwExStyle);
1698
1699 dwExStyle |= WS_EX_MDICHILD; // force this one
1700 m_pfnSuperWindowProc = ::DefMDIChildProc;
1701 m_hWndMDIClient = hWndParent;
1702 ATLASSERT(::IsWindow(m_hWndMDIClient));
1703
1704 if(rect.m_lpRect == NULL)
1705 rect.m_lpRect = &TBase::rcDefault;
1706
1707 // If the currently active MDI child is maximized, we want to create this one maximized too
1708 ATL::CWindow wndParent = hWndParent;
1709 BOOL bMaximized = FALSE;
1710 wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
1711 if(bMaximized)
1712 wndParent.SetRedraw(FALSE);
1713
1714 HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam);
1715
1716 if(bMaximized)
1717 {
1718 // Maximize and redraw everything
1719 if(hWnd != NULL)
1720 MDIMaximize(hWnd);
1721 wndParent.SetRedraw(TRUE);
1722 wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
1723 ::SetFocus(GetMDIFrame()); // focus will be set back to this window
1724 }
1725 else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus()))
1726 {
1727 ::SetFocus(hWnd);
1728 }
1729
1730 return hWnd;
1731 }
1732
1733 HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
1734 {
1735 const int cchName = 256;
1736 TCHAR szWindowName[cchName] = { 0 };
1737 if(lpcstrWindowName == NULL)
1738 {
1739 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1740 lpcstrWindowName = szWindowName;
1741 }
1742
1743 T* pT = static_cast<T*>(this);
1744 HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam);
1745
1746 if(hWnd != NULL)
1747 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1748
1749 return hWnd;
1750 }
1751
1752 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1753 {
1754 ATLASSERT(!::IsWindow(m_hWndToolBar));
1755 if(nResourceID == 0)
1756 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1757 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
1758 return (m_hWndToolBar != NULL);
1759 }
1760
1761 BOOL UpdateClientEdge(LPRECT lpRect = NULL)
1762 {
1763 // only adjust for active MDI child window
1764 HWND hWndChild = MDIGetActive();
1765 if(hWndChild != NULL && hWndChild != m_hWnd)
1766 return FALSE;
1767
1768 // need to adjust the client edge style as max/restore happens
1769 DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE);
1770 DWORD dwNewStyle = dwStyle;
1771 if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0) && ((GetStyle() & WS_MAXIMIZE) != 0))
1772 dwNewStyle &= ~(WS_EX_CLIENTEDGE);
1773 else
1774 dwNewStyle |= WS_EX_CLIENTEDGE;
1775
1776 if(dwStyle != dwNewStyle)
1777 {
1778 // SetWindowPos will not move invalid bits
1779 ::RedrawWindow(m_hWndMDIClient, NULL, NULL,
1780 RDW_INVALIDATE | RDW_ALLCHILDREN);
1781 // remove/add WS_EX_CLIENTEDGE to MDI client area
1782 ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
1783 ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0,
1784 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
1785 SWP_NOZORDER | SWP_NOCOPYBITS);
1786
1787 // return new client area
1788 if (lpRect != NULL)
1789 ::GetClientRect(m_hWndMDIClient, lpRect);
1790
1791 return TRUE;
1792 }
1793
1794 return FALSE;
1795 }
1796
1797 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass;
1798 BEGIN_MSG_MAP(CMDIChildWindowImpl)
1799 MESSAGE_HANDLER(WM_SIZE, OnSize)
1800 MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
1801 MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
1802 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
1803 MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate)
1804 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
1805 #ifndef _ATL_NO_REBAR_SUPPORT
1806 #if (_WIN32_IE >= 0x0400)
1807 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
1808 #endif // (_WIN32_IE >= 0x0400)
1809 #if (_WIN32_IE >= 0x0500)
1810 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
1811 #endif // (_WIN32_IE >= 0x0500)
1812 #endif // !_ATL_NO_REBAR_SUPPORT
1813 CHAIN_MSG_MAP(_baseClass)
1814 END_MSG_MAP()
1815
1816 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1817 {
1818 DefWindowProc(uMsg, wParam, lParam); // needed for MDI children
1819 if(wParam != SIZE_MINIMIZED)
1820 {
1821 T* pT = static_cast<T*>(this);
1822 pT->UpdateLayout();
1823 }
1824 return 0;
1825 }
1826
1827 LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1828 {
1829 // update MDI client edge and adjust MDI child rect
1830 LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam;
1831
1832 if(!(lpWndPos->flags & SWP_NOSIZE))
1833 {
1834 RECT rectClient = { 0 };
1835 if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MAXIMIZE) != 0))
1836 {
1837 ::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle());
1838 lpWndPos->x = rectClient.left;
1839 lpWndPos->y = rectClient.top;
1840 lpWndPos->cx = rectClient.right - rectClient.left;
1841 lpWndPos->cy = rectClient.bottom - rectClient.top;
1842 }
1843 }
1844
1845 bHandled = FALSE;
1846 return 1;
1847 }
1848
1849 LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1850 {
1851 LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
1852
1853 // Activate this MDI window if needed
1854 if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT)
1855 {
1856 if(MDIGetActive() != m_hWnd)
1857 MDIActivate(m_hWnd);
1858 }
1859
1860 return lRes;
1861 }
1862
1863 LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1864 {
1865 return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam);
1866 }
1867
1868 LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1869 {
1870 if((HWND)lParam == m_hWnd && m_hMenu != NULL)
1871 SetMDIFrameMenu();
1872 else if((HWND)lParam == NULL)
1873 ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0);
1874
1875 bHandled = FALSE;
1876 return 1;
1877 }
1878
1879 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1880 {
1881 if(m_hMenu != NULL)
1882 {
1883 ::DestroyMenu(m_hMenu);
1884 m_hMenu = NULL;
1885 }
1886 UpdateClientEdge();
1887 bHandled = FALSE;
1888 return 1;
1889 }
1890
1891 #ifndef _ATL_NO_REBAR_SUPPORT
1892 #if (_WIN32_IE >= 0x0400)
1893 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
1894 {
1895 T* pT = static_cast<T*>(this);
1896 pT->UpdateLayout(FALSE);
1897 return 0;
1898 }
1899 #endif // (_WIN32_IE >= 0x0400)
1900
1901 #if (_WIN32_IE >= 0x0500)
1902 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1903 {
1904 T* pT = static_cast<T*>(this);
1905 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
1906 if(!pT->PrepareChevronMenu(cmi))
1907 {
1908 bHandled = FALSE;
1909 return 1;
1910 }
1911 // display a popup menu with hidden items
1912 pT->DisplayChevronMenu(cmi);
1913 // cleanup
1914 pT->CleanupChevronMenu(cmi);
1915 return 0;
1916 }
1917 #endif // (_WIN32_IE >= 0x0500)
1918 #endif // !_ATL_NO_REBAR_SUPPORT
1919 };
1920
1921 #endif // !_WIN32_WCE
1922
1923
1924 ///////////////////////////////////////////////////////////////////////////////
1925 // COwnerDraw - MI class for owner-draw support
1926
1927 template <class T>
1928 class COwnerDraw
1929 {
1930 public:
1931 #if (_ATL_VER < 0x0700)
1932 BOOL m_bHandledOD;
1933
1934 BOOL IsMsgHandled() const
1935 {
1936 return m_bHandledOD;
1937 }
1938 void SetMsgHandled(BOOL bHandled)
1939 {
1940 m_bHandledOD = bHandled;
1941 }
1942 #endif // (_ATL_VER < 0x0700)
1943
1944 // Message map and handlers
1945 BEGIN_MSG_MAP(COwnerDraw< T >)
1946 MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
1947 MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
1948 MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)
1949 MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)
1950 ALT_MSG_MAP(1)
1951 MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
1952 MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
1953 MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)
1954 MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)
1955 END_MSG_MAP()
1956
1957 LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1958 {
1959 T* pT = static_cast<T*>(this);
1960 pT->SetMsgHandled(TRUE);
1961 pT->DrawItem((LPDRAWITEMSTRUCT)lParam);
1962 bHandled = pT->IsMsgHandled();
1963 return (LRESULT)TRUE;
1964 }
1965
1966 LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1967 {
1968 T* pT = static_cast<T*>(this);
1969 pT->SetMsgHandled(TRUE);
1970 pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam);
1971 bHandled = pT->IsMsgHandled();
1972 return (LRESULT)TRUE;
1973 }
1974
1975 LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1976 {
1977 T* pT = static_cast<T*>(this);
1978 pT->SetMsgHandled(TRUE);
1979 bHandled = pT->IsMsgHandled();
1980 return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam);
1981 }
1982
1983 LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1984 {
1985 T* pT = static_cast<T*>(this);
1986 pT->SetMsgHandled(TRUE);
1987 pT->DeleteItem((LPDELETEITEMSTRUCT)lParam);
1988 bHandled = pT->IsMsgHandled();
1989 return (LRESULT)TRUE;
1990 }
1991
1992 // Overrideables
1993 void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
1994 {
1995 // must be implemented
1996 ATLASSERT(FALSE);
1997 }
1998
1999 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
2000 {
2001 if(lpMeasureItemStruct->CtlType != ODT_MENU)
2002 {
2003 // return default height for a system font
2004 T* pT = static_cast<T*>(this);
2005 HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID);
2006 CClientDC dc(hWnd);
2007 TEXTMETRIC tm = { 0 };
2008 dc.GetTextMetrics(&tm);
2009
2010 lpMeasureItemStruct->itemHeight = tm.tmHeight;
2011 }
2012 else
2013 lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU);
2014 }
2015
2016 int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/)
2017 {
2018 // all items are equal
2019 return 0;
2020 }
2021
2022 void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/)
2023 {
2024 // default - nothing
2025 }
2026 };
2027
2028
2029 ///////////////////////////////////////////////////////////////////////////////
2030 // Update UI macros
2031
2032 // these build the Update UI map inside a class definition
2033 #define BEGIN_UPDATE_UI_MAP(thisClass) \
2034 static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \
2035 { \
2036 static const _AtlUpdateUIMap theMap[] = \
2037 {
2038
2039 #define UPDATE_ELEMENT(nID, wType) \
2040 { nID, wType },
2041
2042 #define END_UPDATE_UI_MAP() \
2043 { (WORD)-1, 0 } \
2044 }; \
2045 return theMap; \
2046 }
2047
2048 ///////////////////////////////////////////////////////////////////////////////
2049 // CUpdateUI - manages UI elements updating
2050
2051 class CUpdateUIBase
2052 {
2053 public:
2054 // constants
2055 enum
2056 {
2057 // UI element type
2058 UPDUI_MENUPOPUP = 0x0001,
2059 UPDUI_MENUBAR = 0x0002,
2060 UPDUI_CHILDWINDOW = 0x0004,
2061 UPDUI_TOOLBAR = 0x0008,
2062 UPDUI_STATUSBAR = 0x0010,
2063 // state
2064 UPDUI_ENABLED = 0x0000,
2065 UPDUI_DISABLED = 0x0100,
2066 UPDUI_CHECKED = 0x0200,
2067 UPDUI_CHECKED2 = 0x0400,
2068 UPDUI_RADIO = 0x0800,
2069 UPDUI_DEFAULT = 0x1000,
2070 UPDUI_TEXT = 0x2000,
2071 // internal state
2072 UPDUI_CLEARDEFAULT = 0x4000,
2073 };
2074
2075 // element data
2076 struct _AtlUpdateUIElement
2077 {
2078 HWND m_hWnd;
2079 WORD m_wType;
2080
2081 bool operator ==(const _AtlUpdateUIElement& e) const
2082 { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); }
2083 };
2084
2085 // map data
2086 struct _AtlUpdateUIMap
2087 {
2088 WORD m_nID;
2089 WORD m_wType;
2090
2091 bool operator ==(const _AtlUpdateUIMap& e) const
2092 { return (m_nID == e.m_nID && m_wType == e.m_wType); }
2093 };
2094
2095 // instance data
2096 #pragma warning(push)
2097 #pragma warning(disable: 4201) // nameless unions are part of C++
2098
2099 struct _AtlUpdateUIData
2100 {
2101 WORD m_wState;
2102 union
2103 {
2104 void* m_lpData;
2105 LPTSTR m_lpstrText;
2106 struct
2107 {
2108 WORD m_nIDFirst;
2109 WORD m_nIDLast;
2110 };
2111 };
2112
2113 bool operator ==(const _AtlUpdateUIData& e) const
2114 { return (m_wState == e.m_wState && m_lpData == e.m_lpData); }
2115 };
2116
2117 #pragma warning(pop)
2118
2119 ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data
2120 const _AtlUpdateUIMap* m_pUIMap; // static UI data
2121 _AtlUpdateUIData* m_pUIData; // instance UI data
2122 WORD m_wDirtyType; // global dirty flag
2123
2124 bool m_bBlockAccelerators;
2125
2126
2127 // Constructor, destructor
2128 CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bBlockAccelerators(false)
2129 { }
2130
2131 ~CUpdateUIBase()
2132 {
2133 if(m_pUIMap != NULL && m_pUIData != NULL)
2134 {
2135 const _AtlUpdateUIMap* pUIMap = m_pUIMap;
2136 _AtlUpdateUIData* pUIData = m_pUIData;
2137 while(pUIMap->m_nID != (WORD)-1)
2138 {
2139 if(pUIData->m_wState & UPDUI_TEXT)
2140 delete [] pUIData->m_lpstrText;
2141 pUIMap++;
2142 pUIData++;
2143 }
2144 delete [] m_pUIData;
2145 }
2146 }
2147
2148 // Check for disabled commands
2149 bool UIGetBlockAccelerators() const
2150 {
2151 return m_bBlockAccelerators;
2152 }
2153
2154 bool UISetBlockAccelerators(bool bBlock)
2155 {
2156 bool bOld = m_bBlockAccelerators;
2157 m_bBlockAccelerators = bBlock;
2158 return bOld;
2159 }
2160
2161 // Add elements
2162 BOOL UIAddMenuBar(HWND hWnd) // menu bar (main menu)
2163 {
2164 if(hWnd == NULL)
2165 return FALSE;
2166 _AtlUpdateUIElement e;
2167 e.m_hWnd = hWnd;
2168 e.m_wType = UPDUI_MENUBAR;
2169 return m_UIElements.Add(e);
2170 }
2171
2172 BOOL UIAddToolBar(HWND hWnd) // toolbar
2173 {
2174 if(hWnd == NULL)
2175 return FALSE;
2176 _AtlUpdateUIElement e;
2177 e.m_hWnd = hWnd;
2178 e.m_wType = UPDUI_TOOLBAR;
2179 return m_UIElements.Add(e);
2180 }
2181
2182 BOOL UIAddStatusBar(HWND hWnd) // status bar
2183 {
2184 if(hWnd == NULL)
2185 return FALSE;
2186 _AtlUpdateUIElement e;
2187 e.m_hWnd = hWnd;
2188 e.m_wType = UPDUI_STATUSBAR;
2189 return m_UIElements.Add(e);
2190 }
2191
2192 BOOL UIAddChildWindowContainer(HWND hWnd) // child window
2193 {
2194 if(hWnd == NULL)
2195 return FALSE;
2196 _AtlUpdateUIElement e;
2197 e.m_hWnd = hWnd;
2198 e.m_wType = UPDUI_CHILDWINDOW;
2199 return m_UIElements.Add(e);
2200 }
2201
2202 // Message map for popup menu updates and accelerator blocking
2203 BEGIN_MSG_MAP(CUpdateUIBase)
2204 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
2205 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
2206 END_MSG_MAP()
2207
2208 LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
2209 {
2210 bHandled = FALSE;
2211 HMENU hMenu = (HMENU)wParam;
2212 if(hMenu == NULL)
2213 return 1;
2214 _AtlUpdateUIData* pUIData = m_pUIData;
2215 if(pUIData == NULL)
2216 return 1;
2217 const _AtlUpdateUIMap* pMap = m_pUIMap;
2218 while(pMap->m_nID != (WORD)-1)
2219 {
2220 if(pMap->m_wType & UPDUI_MENUPOPUP)
2221 {
2222 UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
2223
2224 if((pUIData->m_wState & UPDUI_RADIO) != 0)
2225 ::CheckMenuRadioItem(hMenu, pUIData->m_nIDFirst, pUIData->m_nIDLast, pMap->m_nID, MF_BYCOMMAND);
2226 }
2227 pMap++;
2228 pUIData++;
2229 }
2230 return 0;
2231 }
2232
2233 LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
2234 {
2235 bHandled = FALSE;
2236 if(m_bBlockAccelerators && HIWORD(wParam) == 1) // accelerators only
2237 {
2238 int nID = LOWORD(wParam);
2239 if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED)
2240 {
2241 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID);
2242 bHandled = TRUE; // eat the command, UI item is disabled
2243 }
2244 }
2245 return 0;
2246 }
2247
2248 // methods for setting UI element state
2249 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
2250 {
2251 const _AtlUpdateUIMap* pMap = m_pUIMap;
2252 _AtlUpdateUIData* pUIData = m_pUIData;
2253 if(pUIData == NULL)
2254 return FALSE;
2255
2256 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2257 {
2258 if(nID == (int)pMap->m_nID)
2259 {
2260 if(bEnable)
2261 {
2262 if(pUIData->m_wState & UPDUI_DISABLED)
2263 {
2264 pUIData->m_wState |= pMap->m_wType;
2265 pUIData->m_wState &= ~UPDUI_DISABLED;
2266 }
2267 }
2268 else
2269 {
2270 if(!(pUIData->m_wState & UPDUI_DISABLED))
2271 {
2272 pUIData->m_wState |= pMap->m_wType;
2273 pUIData->m_wState |= UPDUI_DISABLED;
2274 }
2275 }
2276
2277 if(bForceUpdate)
2278 pUIData->m_wState |= pMap->m_wType;
2279 if(pUIData->m_wState & pMap->m_wType)
2280 m_wDirtyType |= pMap->m_wType;
2281
2282 break; // found
2283 }
2284 }
2285
2286 return TRUE;
2287 }
2288
2289 BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE)
2290 {
2291 const _AtlUpdateUIMap* pMap = m_pUIMap;
2292 _AtlUpdateUIData* pUIData = m_pUIData;
2293 if(pUIData == NULL)
2294 return FALSE;
2295
2296 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2297 {
2298 if(nID == (int)pMap->m_nID)
2299 {
2300 switch(nCheck)
2301 {
2302 case 0:
2303 if((pUIData->m_wState & UPDUI_CHECKED) || (pUIData->m_wState & UPDUI_CHECKED2))
2304 {
2305 pUIData->m_wState |= pMap->m_wType;
2306 pUIData->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2);
2307 }
2308 break;
2309 case 1:
2310 if(!(pUIData->m_wState & UPDUI_CHECKED))
2311 {
2312 pUIData->m_wState |= pMap->m_wType;
2313 pUIData->m_wState &= ~UPDUI_CHECKED2;
2314 pUIData->m_wState |= UPDUI_CHECKED;
2315 }
2316 break;
2317 case 2:
2318 if(!(pUIData->m_wState & UPDUI_CHECKED2))
2319 {
2320 pUIData->m_wState |= pMap->m_wType;
2321 pUIData->m_wState &= ~UPDUI_CHECKED;
2322 pUIData->m_wState |= UPDUI_CHECKED2;
2323 }
2324 break;
2325 }
2326
2327 if(bForceUpdate)
2328 pUIData->m_wState |= pMap->m_wType;
2329 if(pUIData->m_wState & pMap->m_wType)
2330 m_wDirtyType |= pMap->m_wType;
2331
2332 break; // found
2333 }
2334 }
2335
2336 return TRUE;
2337 }
2338
2339 // variant that supports bool (checked/not-checked, no intermediate state)
2340 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
2341 {
2342 return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate);
2343 }
2344
2345 BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE)
2346 {
2347 const _AtlUpdateUIMap* pMap = m_pUIMap;
2348 _AtlUpdateUIData* pUIData = m_pUIData;
2349 if(pUIData == NULL)
2350 return FALSE;
2351
2352 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2353 {
2354 if(nID == (int)pMap->m_nID)
2355 {
2356 if(bRadio)
2357 {
2358 if(!(pUIData->m_wState & UPDUI_RADIO))
2359 {
2360 pUIData->m_wState |= pMap->m_wType;
2361 pUIData->m_wState |= UPDUI_RADIO;
2362 }
2363 }
2364 else
2365 {
2366 if(pUIData->m_wState & UPDUI_RADIO)
2367 {
2368 pUIData->m_wState |= pMap->m_wType;
2369 pUIData->m_wState &= ~UPDUI_RADIO;
2370 }
2371 }
2372
2373 if(bForceUpdate)
2374 pUIData->m_wState |= pMap->m_wType;
2375 if(pUIData->m_wState & pMap->m_wType)
2376 m_wDirtyType |= pMap->m_wType;
2377
2378 break; // found
2379 }
2380 }
2381
2382 return TRUE;
2383 }
2384
2385 // for menu items
2386 BOOL UISetRadioMenuItem(int nID, int nIDFirst, int nIDLast, BOOL bForceUpdate = FALSE)
2387 {
2388 const _AtlUpdateUIMap* pMap = m_pUIMap;
2389 _AtlUpdateUIData* pUIData = m_pUIData;
2390 if(pUIData == NULL)
2391 return FALSE;
2392
2393 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2394 {
2395 if(nID == (int)pMap->m_nID)
2396 {
2397 pUIData->m_wState |= pMap->m_wType;
2398 pUIData->m_wState |= UPDUI_RADIO;
2399 pUIData->m_nIDFirst = (WORD)nIDFirst;
2400 pUIData->m_nIDLast = (WORD)nIDLast;
2401
2402 if(bForceUpdate)
2403 pUIData->m_wState |= pMap->m_wType;
2404 if(pUIData->m_wState & pMap->m_wType)
2405 m_wDirtyType |= pMap->m_wType;
2406 }
2407 else if(pMap->m_nID >= nIDFirst && pMap->m_nID <= nIDLast)
2408 {
2409 if(pUIData->m_wState & UPDUI_RADIO)
2410 {
2411 pUIData->m_wState &= ~pMap->m_wType;
2412 pUIData->m_wState &= ~UPDUI_RADIO;
2413 pUIData->m_nIDFirst = 0;
2414 pUIData->m_nIDLast = 0;
2415 }
2416 }
2417
2418 if(pMap->m_nID == nIDLast)
2419 break;
2420 }
2421
2422 return TRUE;
2423 }
2424
2425 BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE)
2426 {
2427 const _AtlUpdateUIMap* pMap = m_pUIMap;
2428 _AtlUpdateUIData* pUIData = m_pUIData;
2429 if(pUIData == NULL)
2430 return FALSE;
2431 if(lpstrText == NULL)
2432 lpstrText = _T("");
2433
2434 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2435 {
2436 if(nID == (int)pMap->m_nID)
2437 {
2438 if(pUIData->m_lpstrText == NULL || lstrcmp(pUIData->m_lpstrText, lpstrText))
2439 {
2440 delete [] pUIData->m_lpstrText;
2441 pUIData->m_lpstrText = NULL;
2442 int nStrLen = lstrlen(lpstrText);
2443 ATLTRY(pUIData->m_lpstrText = new TCHAR[nStrLen + 1]);
2444 if(pUIData->m_lpstrText == NULL)
2445 {
2446 ATLTRACE2(atlTraceUI, 0, _T("UISetText - memory allocation failed\n"));
2447 break;
2448 }
2449 SecureHelper::strcpy_x(pUIData->m_lpstrText, nStrLen + 1, lpstrText);
2450 pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
2451 }
2452
2453 if(bForceUpdate)
2454 pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
2455 if(pUIData->m_wState & pMap->m_wType)
2456 m_wDirtyType |= pMap->m_wType;
2457
2458 break; // found
2459 }
2460 }
2461
2462 return TRUE;
2463 }
2464
2465 BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE)
2466 {
2467 const _AtlUpdateUIMap* pMap = m_pUIMap;
2468 _AtlUpdateUIData* pUIData = m_pUIData;
2469 if(pUIData == NULL)
2470 return FALSE;
2471
2472 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2473 {
2474 if(nID == (int)pMap->m_nID)
2475 {
2476 if(bDefault)
2477 {
2478 if((pUIData->m_wState & UPDUI_DEFAULT) == 0)
2479 {
2480 pUIData->m_wState |= pMap->m_wType;
2481 pUIData->m_wState |= UPDUI_DEFAULT;
2482 }
2483 }
2484 else
2485 {
2486 if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
2487 {
2488 pUIData->m_wState |= pMap->m_wType;
2489 pUIData->m_wState &= ~UPDUI_DEFAULT;
2490 pUIData->m_wState |= UPDUI_CLEARDEFAULT;
2491 }
2492 }
2493
2494 if(bForceUpdate)
2495 pUIData->m_wState |= pMap->m_wType;
2496 if(pUIData->m_wState & pMap->m_wType)
2497 m_wDirtyType |= pMap->m_wType;
2498
2499 break; // found
2500 }
2501 }
2502
2503 return TRUE;
2504 }
2505
2506 // methods for complete state set/get
2507 BOOL UISetState(int nID, DWORD dwState)
2508 {
2509 const _AtlUpdateUIMap* pMap = m_pUIMap;
2510 _AtlUpdateUIData* pUIData = m_pUIData;
2511 if(pUIData == NULL)
2512 return FALSE;
2513 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2514 {
2515 if(nID == (int)pMap->m_nID)
2516 {
2517 pUIData->m_wState = (WORD)(dwState | pMap->m_wType);
2518 m_wDirtyType |= pMap->m_wType;
2519 break; // found
2520 }
2521 }
2522 return TRUE;
2523 }
2524
2525 DWORD UIGetState(int nID)
2526 {
2527 const _AtlUpdateUIMap* pMap = m_pUIMap;
2528 _AtlUpdateUIData* pUIData = m_pUIData;
2529 if(pUIData == NULL)
2530 return 0;
2531 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
2532 {
2533 if(nID == (int)pMap->m_nID)
2534 return pUIData->m_wState;
2535 }
2536 return 0;
2537 }
2538
2539 // methods for updating UI
2540 #ifndef _WIN32_WCE
2541 BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE)
2542 {
2543 if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate)
2544 return TRUE;
2545
2546 const _AtlUpdateUIMap* pMap = m_pUIMap;
2547 _AtlUpdateUIData* pUIData = m_pUIData;
2548 if(pUIData == NULL)
2549 return FALSE;
2550
2551 while(pMap->m_nID != (WORD)-1)
2552 {
2553 for(int i = 0; i < m_UIElements.GetSize(); i++)
2554 {
2555 if(m_UIElements[i].m_wType == UPDUI_MENUBAR)
2556 {
2557 HMENU hMenu = ::GetMenu(m_UIElements[i].m_hWnd);
2558 if(hMenu != NULL && (pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR))
2559 UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
2560 }
2561 if(bMainMenu)
2562 ::DrawMenuBar(m_UIElements[i].m_hWnd);
2563 }
2564 pMap++;
2565 pUIData->m_wState &= ~UPDUI_MENUBAR;
2566 if(pUIData->m_wState & UPDUI_TEXT)
2567 {
2568 delete [] pUIData->m_lpstrText;
2569 pUIData->m_lpstrText = NULL;
2570 pUIData->m_wState &= ~UPDUI_TEXT;
2571 }
2572 pUIData++;
2573 }
2574
2575 m_wDirtyType &= ~UPDUI_MENUBAR;
2576 return TRUE;
2577 }
2578 #endif // !_WIN32_WCE
2579
2580 BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE)
2581 {
2582 if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate)
2583 return TRUE;
2584
2585 const _AtlUpdateUIMap* pMap = m_pUIMap;
2586 _AtlUpdateUIData* pUIData = m_pUIData;
2587 if(pUIData == NULL)
2588 return FALSE;
2589
2590 while(pMap->m_nID != (WORD)-1)
2591 {
2592 for(int i = 0; i < m_UIElements.GetSize(); i++)
2593 {
2594 if(m_UIElements[i].m_wType == UPDUI_TOOLBAR)
2595 {
2596 if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR))
2597 UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
2598 }
2599 }
2600 pMap++;
2601 pUIData->m_wState &= ~UPDUI_TOOLBAR;
2602 pUIData++;
2603 }
2604
2605 m_wDirtyType &= ~UPDUI_TOOLBAR;
2606 return TRUE;
2607 }
2608
2609 BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE)
2610 {
2611 if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate)
2612 return TRUE;
2613
2614 const _AtlUpdateUIMap* pMap = m_pUIMap;
2615 _AtlUpdateUIData* pUIData = m_pUIData;
2616 if(pUIData == NULL)
2617 return FALSE;
2618
2619 while(pMap->m_nID != (WORD)-1)
2620 {
2621 for(int i = 0; i < m_UIElements.GetSize(); i++)
2622 {
2623 if(m_UIElements[i].m_wType == UPDUI_STATUSBAR)
2624 {
2625 if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR))
2626 UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
2627 }
2628 }
2629 pMap++;
2630 pUIData->m_wState &= ~UPDUI_STATUSBAR;
2631 if(pUIData->m_wState & UPDUI_TEXT)
2632 {
2633 delete [] pUIData->m_lpstrText;
2634 pUIData->m_lpstrText = NULL;
2635 pUIData->m_wState &= ~UPDUI_TEXT;
2636 }
2637 pUIData++;
2638 }
2639
2640 m_wDirtyType &= ~UPDUI_STATUSBAR;
2641 return TRUE;
2642 }
2643
2644 BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE)
2645 {
2646 if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate)
2647 return TRUE;
2648
2649 const _AtlUpdateUIMap* pMap = m_pUIMap;
2650 _AtlUpdateUIData* pUIData = m_pUIData;
2651 if(pUIData == NULL)
2652 return FALSE;
2653
2654 while(pMap->m_nID != (WORD)-1)
2655 {
2656 for(int i = 0; i < m_UIElements.GetSize(); i++)
2657 {
2658 if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW)
2659 {
2660 if((pUIData->m_wState & UPDUI_CHILDWINDOW) && (pMap->m_wType & UPDUI_CHILDWINDOW))
2661 UIUpdateChildWindow(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
2662 }
2663 }
2664 pMap++;
2665 pUIData->m_wState &= ~UPDUI_CHILDWINDOW;
2666 if(pUIData->m_wState & UPDUI_TEXT)
2667 {
2668 delete [] pUIData->m_lpstrText;
2669 pUIData->m_lpstrText = NULL;
2670 pUIData->m_wState &= ~UPDUI_TEXT;
2671 }
2672 pUIData++;
2673 }
2674
2675 m_wDirtyType &= ~UPDUI_CHILDWINDOW;
2676 return TRUE;
2677 }
2678
2679 // internal element specific methods
2680 static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu)
2681 {
2682 #ifndef _WIN32_WCE
2683 if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0)
2684 {
2685 ::SetMenuDefaultItem(hMenu, (UINT)-1, 0);
2686 pUIData->m_wState &= ~UPDUI_CLEARDEFAULT;
2687 }
2688 #endif // !_WIN32_WCE
2689
2690 CMenuItemInfo mii;
2691 mii.fMask = MIIM_STATE;
2692 mii.wID = nID;
2693
2694 #ifndef _WIN32_WCE
2695 if((pUIData->m_wState & UPDUI_DISABLED) != 0)
2696 mii.fState |= MFS_DISABLED | MFS_GRAYED;
2697 else
2698 mii.fState |= MFS_ENABLED;
2699
2700 if((pUIData->m_wState & UPDUI_CHECKED) != 0)
2701 mii.fState |= MFS_CHECKED;
2702 else
2703 mii.fState |= MFS_UNCHECKED;
2704
2705 if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
2706 mii.fState |= MFS_DEFAULT;
2707 #else // CE specific
2708 // ::SetMenuItemInfo() can't disable or check menu items
2709 // on Windows CE, so we have to do that directly
2710 UINT uEnable = MF_BYCOMMAND;
2711 if((pUIData->m_wState & UPDUI_DISABLED) != 0)
2712 uEnable |= MF_GRAYED;
2713 else
2714 uEnable |= MF_ENABLED;
2715 ::EnableMenuItem(hMenu, nID, uEnable);
2716
2717 UINT uCheck = MF_BYCOMMAND;
2718 if((pUIData->m_wState & UPDUI_CHECKED) != 0)
2719 uCheck |= MF_CHECKED;
2720 else
2721 uCheck |= MF_UNCHECKED;
2722 ::CheckMenuItem(hMenu, nID, uCheck);
2723 #endif // _WIN32_WCE
2724
2725 if((pUIData->m_wState & UPDUI_TEXT) != 0)
2726 {
2727 CMenuItemInfo miiNow;
2728 miiNow.fMask = MIIM_TYPE;
2729 miiNow.wID = nID;
2730 if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow))
2731 {
2732 mii.fMask |= MIIM_TYPE;
2733 // MFT_BITMAP and MFT_SEPARATOR don't go together with MFT_STRING
2734 #ifndef _WIN32_WCE
2735 mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_SEPARATOR)) | MFT_STRING;
2736 #else // CE specific
2737 mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) | MFT_STRING;
2738 #endif // _WIN32_WCE
2739 mii.dwTypeData = pUIData->m_lpstrText;
2740 }
2741 }
2742
2743 ::SetMenuItemInfo(hMenu, nID, FALSE, &mii);
2744 }
2745
2746 static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar)
2747 {
2748 // Note: only handles enabled/disabled, checked state, and radio (press)
2749 ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
2750 ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE);
2751 ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE);
2752 ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE);
2753 }
2754
2755 static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar)
2756 {
2757 // Note: only handles text
2758 if(pUIData->m_wState & UPDUI_TEXT)
2759 ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpstrText);
2760 }
2761
2762 static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND hWnd)
2763 {
2764 HWND hChild = ::GetDlgItem(hWnd, nID);
2765
2766 ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
2767 // for check and radio, assume that window is a button
2768 int nCheck = BST_UNCHECKED;
2769 if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO)
2770 nCheck = BST_CHECKED;
2771 else if(pUIData->m_wState & UPDUI_CHECKED2)
2772 nCheck = BST_INDETERMINATE;
2773 ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L);
2774 if(pUIData->m_wState & UPDUI_DEFAULT)
2775 {
2776 DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0, 0L);
2777 if(HIWORD(dwRet) == DC_HASDEFID)
2778 {
2779 HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LOWORD(dwRet));
2780 // remove BS_DEFPUSHBUTTON
2781 ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
2782 }
2783 ::SendMessage(hWnd, DM_SETDEFID, nID, 0L);
2784 }
2785 if(pUIData->m_wState & UPDUI_TEXT)
2786 ::SetWindowText(hChild, pUIData->m_lpstrText);
2787 }
2788 };
2789
2790 template <class T>
2791 class CUpdateUI : public CUpdateUIBase
2792 {
2793 public:
2794 CUpdateUI()
2795 {
2796 T* pT = static_cast<T*>(this);
2797 pT;
2798 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
2799 m_pUIMap = pMap;
2800 ATLASSERT(m_pUIMap != NULL);
2801 int nCount = 1;
2802 for( ; pMap->m_nID != (WORD)-1; nCount++)
2803 pMap++;
2804
2805 // check for duplicates (debug only)
2806 #ifdef _DEBUG
2807 for(int i = 0; i < nCount; i++)
2808 {
2809 for(int j = 0; j < nCount; j++)
2810 {
2811 // shouldn't have duplicates in the update UI map
2812 if(i != j)
2813 ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[i].m_nID);
2814 }
2815 }
2816 #endif // _DEBUG
2817
2818 ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]);
2819 ATLASSERT(m_pUIData != NULL);
2820
2821 if(m_pUIData != NULL)
2822 memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount);
2823 }
2824 };
2825
2826
2827 ///////////////////////////////////////////////////////////////////////////////
2828 // CDynamicUpdateUI - allows update elements to dynamically added and removed
2829 // in addition to a static update UI map
2830
2831 template <class T>
2832 class CDynamicUpdateUI : public CUpdateUIBase
2833 {
2834 public:
2835 // Data members
2836 ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap; // copy of the static UI data
2837 ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData; // instance UI data
2838
2839 // Constructor/destructor
2840 CDynamicUpdateUI()
2841 {
2842 T* pT = static_cast<T*>(this);
2843 pT;
2844 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
2845 ATLASSERT(pMap != NULL);
2846
2847 for(;;)
2848 {
2849 BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap);
2850 ATLASSERT(bRet);
2851
2852 if(bRet != FALSE)
2853 {
2854 _AtlUpdateUIData data = { 0, NULL };
2855 bRet = m_arrUIData.Add(data);
2856 ATLASSERT(bRet);
2857 }
2858
2859 if(pMap->m_nID == (WORD)-1)
2860 break;
2861
2862 pMap++;
2863 }
2864
2865 ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize());
2866
2867 #ifdef _DEBUG
2868 // check for duplicates (debug only)
2869 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
2870 {
2871 for(int j = 0; j < m_arrUIMap.GetSize(); j++)
2872 {
2873 // shouldn't have duplicates in the update UI map
2874 if(i != j)
2875 ATLASSERT(m_arrUIMap[j].m_nID != m_arrUIMap[i].m_nID);
2876 }
2877 }
2878 #endif // _DEBUG
2879
2880 // Set internal data pointers to point to the new data arrays
2881 m_pUIMap = m_arrUIMap.m_aT;
2882 m_pUIData = m_arrUIData.m_aT;
2883 }
2884
2885 ~CDynamicUpdateUI()
2886 {
2887 for(int i = 0; i < m_arrUIData.GetSize(); i++)
2888 {
2889 if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0)
2890 delete [] m_arrUIData[i].m_lpstrText;
2891 }
2892
2893 // Reset internal data pointers (memory will be released by CSimpleArray d-tor)
2894 m_pUIMap = NULL;
2895 m_pUIData = NULL;
2896 }
2897
2898 // Methods for dynamically adding and removing update elements
2899 bool UIAddUpdateElement(WORD nID, WORD wType)
2900 {
2901 // check for duplicates
2902 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
2903 {
2904 // shouldn't have duplicates in the update UI map
2905 ATLASSERT(m_arrUIMap[i].m_nID != nID);
2906 if(m_arrUIMap[i].m_nID == nID)
2907 return false;
2908 }
2909
2910 bool bRetVal = false;
2911
2912 // Add new end element
2913 _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 };
2914 BOOL bRet = m_arrUIMap.Add(uumEnd);
2915 ATLASSERT(bRet);
2916
2917 if(bRet != FALSE)
2918 {
2919 _AtlUpdateUIData uud = { 0, NULL };
2920 bRet = m_arrUIData.Add(uud);
2921 ATLASSERT(bRet);
2922
2923 // Set new data to the previous end element
2924 if(bRet != FALSE)
2925 {
2926 int nSize = m_arrUIMap.GetSize();
2927 _AtlUpdateUIMap uum = { nID, wType };
2928 m_arrUIMap.SetAtIndex(nSize - 2, uum);
2929 m_arrUIData.SetAtIndex(nSize - 2, uud);
2930
2931 // Set internal data pointers again, just in case that memory moved
2932 m_pUIMap = m_arrUIMap.m_aT;
2933 m_pUIData = m_arrUIData.m_aT;
2934
2935 bRetVal = true;
2936 }
2937 }
2938
2939 return bRetVal;
2940 }
2941
2942 bool UIRemoveUpdateElement(WORD nID)
2943 {
2944 bool bRetVal = false;
2945
2946 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
2947 {
2948 if(m_arrUIMap[i].m_nID == nID)
2949 {
2950 if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0)
2951 delete [] m_arrUIData[i].m_lpstrText;
2952
2953 BOOL bRet = m_arrUIMap.RemoveAt(i);
2954 ATLASSERT(bRet);
2955 bRet = m_arrUIData.RemoveAt(i);
2956 ATLASSERT(bRet);
2957
2958 bRetVal = true;
2959 break;
2960 }
2961 }
2962
2963 return bRetVal;
2964 }
2965 };
2966
2967
2968 ///////////////////////////////////////////////////////////////////////////////
2969 // CAutoUpdateUI : Automatic mapping of UI elements
2970
2971 template <class T>
2972 class CAutoUpdateUI : public CDynamicUpdateUI<T>
2973 {
2974 public:
2975 LPCTSTR UIGetText(int nID)
2976 {
2977 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
2978 {
2979 if(m_arrUIMap[i].m_nID == nID)
2980 return m_arrUIData[i].m_lpstrText;
2981 }
2982
2983 return NULL;
2984 }
2985
2986 // Element
2987 template <WORD t_wType>
2988 bool UIAddElement(UINT nID)
2989 {
2990 // check for existing UI map element
2991 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
2992 {
2993 if(m_arrUIMap[i].m_nID == nID)
2994 {
2995 // set requested type
2996 m_arrUIMap[i].m_wType |= t_wType;
2997 return true;
2998 }
2999 }
3000
3001 // Add element to UI map with requested type
3002 return UIAddUpdateElement((WORD)nID, t_wType);
3003 }
3004
3005 template <WORD t_wType>
3006 bool UIRemoveElement(UINT nID)
3007 {
3008 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
3009 {
3010 if(m_arrUIMap[i].m_nID == nID) // matching UI map element
3011 {
3012 WORD wType = m_arrUIMap[i].m_wType & ~t_wType;
3013 if (wType != 0) // has other types
3014 {
3015 m_arrUIMap[i].m_wType = wType; // keep other types
3016 return true;
3017 }
3018 else
3019 {
3020 return UIRemoveUpdateElement((WORD)nID);
3021 }
3022 }
3023 }
3024
3025 return false;
3026 }
3027
3028 // Menu
3029 bool UIAddMenu(HMENU hMenu, bool bSetText = false)
3030 {
3031 #if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
3032 using ATL::GetMenuString;
3033 #endif
3034 ATLASSERT(::IsMenu(hMenu));
3035 MENUITEMINFO mii = {sizeof(MENUITEMINFO), MIIM_TYPE | MIIM_ID | MIIM_SUBMENU};
3036
3037 // Complete the UI map
3038 for (INT uItem = 0; CMenuHandle(hMenu).GetMenuItemInfo(uItem, TRUE, &mii); uItem++)
3039 {
3040 if(mii.hSubMenu)
3041 {
3042 // Add submenu to UI map
3043 UIAddMenu(mii.hSubMenu, bSetText);
3044 }
3045 else if (mii.wID != 0)
3046 {
3047 // Add element to UI map
3048 UIAddElement<UPDUI_MENUPOPUP>(mii.wID);
3049 #if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
3050 if (bSetText)
3051 {
3052 TCHAR sText[64] = { 0 };
3053 if (GetMenuString(hMenu, uItem, sText, 64, MF_BYPOSITION))
3054 UISetText(mii.wID, sText);
3055 }
3056 #else
3057 bSetText;
3058 #endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
3059 }
3060 }
3061
3062 return true;
3063 }
3064
3065 bool UIAddMenu(UINT uID, bool bSetText = false)
3066 {
3067 CMenu menu;
3068 ATLVERIFY(menu.LoadMenu(uID));
3069 return UIAddMenu(menu, bSetText);
3070 }
3071
3072 // ToolBar
3073 #if !defined(_WIN32_WCE) || (defined(_AUTOUI_CE_TOOLBAR) && defined(TBIF_BYINDEX))
3074 bool UIAddToolBar(HWND hWndToolBar)
3075 {
3076 ATLASSERT(::IsWindow(hWndToolBar));
3077 TBBUTTONINFO tbbi = { sizeof(TBBUTTONINFO), TBIF_COMMAND | TBIF_STYLE | TBIF_BYINDEX };
3078
3079 // Add toolbar buttons
3080 for (int uItem = 0; ::SendMessage(hWndToolBar, TB_GETBUTTONINFO, uItem, (LPARAM)&tbbi) != -1; uItem++)
3081 {
3082 if (tbbi.fsStyle ^ BTNS_SEP)
3083 UIAddElement<UPDUI_TOOLBAR>(tbbi.idCommand);
3084 }
3085
3086 // Add embedded controls if any
3087 if (::GetWindow(hWndToolBar, GW_CHILD))
3088 UIAddChildWindowContainer(hWndToolBar);
3089
3090 return (CUpdateUIBase::UIAddToolBar(hWndToolBar) != FALSE);
3091 }
3092 #endif // !defined(_WIN32_WCE) || (defined(_AUTOUI_CE_TOOLBAR) && defined(TBIF_BYINDEX))
3093
3094 // Container
3095 bool UIAddChildWindowContainer(HWND hWnd)
3096 {
3097 ATLASSERT(::IsWindow(hWnd));
3098
3099 // Add children controls if any
3100 for (ATL::CWindow wCtl = ::GetWindow(hWnd, GW_CHILD); wCtl.IsWindow(); wCtl = wCtl.GetWindow(GW_HWNDNEXT))
3101 {
3102 int id = wCtl.GetDlgCtrlID();
3103 if(id != 0)
3104 UIAddElement<UPDUI_CHILDWINDOW>(id);
3105 }
3106
3107 return (CUpdateUIBase::UIAddChildWindowContainer(hWnd) != FALSE);
3108 }
3109
3110 // StatusBar
3111 BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE)
3112 {
3113 if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate)
3114 return TRUE;
3115
3116 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
3117 {
3118 for(int e = 0; e < m_UIElements.GetSize(); e++)
3119 {
3120 if((m_UIElements[e].m_wType == UPDUI_STATUSBAR) &&
3121 (m_arrUIMap[i].m_wType & UPDUI_STATUSBAR) &&
3122 (m_arrUIData[i].m_wState & UPDUI_STATUSBAR))
3123 {
3124 UIUpdateStatusBarElement(m_arrUIMap[i].m_nID, &m_arrUIData[i], m_UIElements[e].m_hWnd);
3125 m_arrUIData[i].m_wState &= ~UPDUI_STATUSBAR;
3126 if(m_arrUIData[i].m_wState & UPDUI_TEXT)
3127 m_arrUIData[i].m_wState &= ~UPDUI_TEXT;
3128 }
3129 }
3130 }
3131
3132 m_wDirtyType &= ~UPDUI_STATUSBAR;
3133 return TRUE;
3134 }
3135
3136 bool UIAddStatusBar(HWND hWndStatusBar, INT nPanes = 1)
3137 {
3138 ATLASSERT(::IsWindow(hWndStatusBar));
3139
3140 // Add StatusBar panes
3141 for (int iPane = 0; iPane < nPanes; iPane++)
3142 UIAddElement<UPDUI_STATUSBAR>(ID_DEFAULT_PANE + iPane);
3143
3144 return (CUpdateUIBase::UIAddStatusBar(hWndStatusBar) != FALSE);
3145 }
3146
3147 // UI Map used if derived class has none
3148 BEGIN_UPDATE_UI_MAP(CAutoUpdateUI)
3149 END_UPDATE_UI_MAP()
3150 };
3151
3152
3153 ///////////////////////////////////////////////////////////////////////////////
3154 // CDialogResize - provides support for resizing dialog controls
3155 // (works for any window that has child controls)
3156
3157 // Put CDialogResize in the list of base classes for a dialog (or even plain window),
3158 // then implement DLGRESIZE map by specifying controls and groups of control
3159 // and using DLSZ_* values to specify how are they supposed to be resized.
3160 //
3161 // Notes:
3162 // - Resizeable border (WS_THICKFRAME style) should be set in the dialog template
3163 // for top level dialogs (popup or overlapped), so that users can resize the dialog.
3164 // - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SIZE_X,
3165 // DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined.
3166 // - Order of controls is important - group controls are resized and moved based
3167 // on the position of the previous control in a group.
3168
3169 // dialog resize map macros
3170 #define BEGIN_DLGRESIZE_MAP(thisClass) \
3171 static const _AtlDlgResizeMap* GetDlgResizeMap() \
3172 { \
3173 static const _AtlDlgResizeMap theMap[] = \
3174 {
3175
3176 #define END_DLGRESIZE_MAP() \
3177 { -1, 0 }, \
3178 }; \
3179 return theMap; \
3180 }
3181
3182 #define DLGRESIZE_CONTROL(id, flags) \
3183 { id, flags },
3184
3185 #define BEGIN_DLGRESIZE_GROUP() \
3186 { -1, _DLSZ_BEGIN_GROUP },
3187
3188 #define END_DLGRESIZE_GROUP() \
3189 { -1, _DLSZ_END_GROUP },
3190
3191
3192 template <class T>
3193 class CDialogResize
3194 {
3195 public:
3196 // Data declarations and members
3197 enum
3198 {
3199 DLSZ_SIZE_X = 0x00000001,
3200 DLSZ_SIZE_Y = 0x00000002,
3201 DLSZ_MOVE_X = 0x00000004,
3202 DLSZ_MOVE_Y = 0x00000008,
3203 DLSZ_REPAINT = 0x00000010,
3204 DLSZ_CENTER_X = 0x00000020,
3205 DLSZ_CENTER_Y = 0x00000040,
3206
3207 // internal use only
3208 _DLSZ_BEGIN_GROUP = 0x00001000,
3209 _DLSZ_END_GROUP = 0x00002000,
3210 _DLSZ_GRIPPER = 0x00004000
3211 };
3212
3213 struct _AtlDlgResizeMap
3214 {
3215 int m_nCtlID;
3216 DWORD m_dwResizeFlags;
3217 };
3218
3219 struct _AtlDlgResizeData
3220 {
3221 int m_nCtlID;
3222 DWORD m_dwResizeFlags;
3223 RECT m_rect;
3224
3225 int GetGroupCount() const
3226 {
3227 return (int)LOBYTE(HIWORD(m_dwResizeFlags));
3228 }
3229
3230 void SetGroupCount(int nCount)
3231 {
3232 ATLASSERT(nCount > 0 && nCount < 256);
3233 DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0));
3234 m_dwResizeFlags &= 0xFF00FFFF;
3235 m_dwResizeFlags |= dwCount;
3236 }
3237
3238 bool operator ==(const _AtlDlgResizeData& r) const
3239 { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwResizeFlags); }
3240 };
3241
3242 ATL::CSimpleArray<_AtlDlgResizeData> m_arrData;
3243 SIZE m_sizeDialog;
3244 POINT m_ptMinTrackSize;
3245 bool m_bGripper;
3246
3247
3248 // Constructor
3249 CDialogResize() : m_bGripper(false)
3250 {
3251 m_sizeDialog.cx = 0;
3252 m_sizeDialog.cy = 0;
3253 m_ptMinTrackSize.x = -1;
3254 m_ptMinTrackSize.y = -1;
3255 }
3256
3257 // Operations
3258 void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true, DWORD dwForceStyle = WS_CLIPCHILDREN)
3259 {
3260 T* pT = static_cast<T*>(this);
3261 ATLASSERT(::IsWindow(pT->m_hWnd));
3262
3263 DWORD dwStyle = pT->GetStyle();
3264
3265 #ifdef _DEBUG
3266 // Debug only: Check if top level dialogs have a resizeable border.
3267 if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) == 0))
3268 ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n"));
3269 #endif // _DEBUG
3270
3271 // Force specified styles (default WS_CLIPCHILDREN reduces flicker)
3272 if((dwStyle & dwForceStyle) != dwForceStyle)
3273 pT->ModifyStyle(0, dwForceStyle);
3274
3275 #ifndef _WIN32_WCE
3276 // Adding this style removes an empty icon that dialogs with WS_THICKFRAME have.
3277 // Setting icon to NULL is required when XP themes are active.
3278 // Note: This will not prevent adding an icon for the dialog using SetIcon()
3279 if((dwStyle & WS_CHILD) == 0)
3280 {
3281 pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME);
3282 if(pT->GetIcon(FALSE) == NULL)
3283 pT->SetIcon(NULL, FALSE);
3284 }
3285 #endif
3286
3287 // Cleanup in case of multiple initialization
3288 // block: first check for the gripper control, destroy it if needed
3289 {
3290 ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
3291 if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0)
3292 wndGripper.DestroyWindow();
3293 }
3294 // clear out everything else
3295 m_arrData.RemoveAll();
3296 m_sizeDialog.cx = 0;
3297 m_sizeDialog.cy = 0;
3298 m_ptMinTrackSize.x = -1;
3299 m_ptMinTrackSize.y = -1;
3300
3301 // Get initial dialog client size
3302 RECT rectDlg = { 0 };
3303 pT->GetClientRect(&rectDlg);
3304 m_sizeDialog.cx = rectDlg.right;
3305 m_sizeDialog.cy = rectDlg.bottom;
3306
3307 #ifndef _WIN32_WCE
3308 // Create gripper if requested
3309 m_bGripper = false;
3310 if(bAddGripper)
3311 {
3312 // shouldn't exist already
3313 ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)));
3314 if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)))
3315 {
3316 ATL::CWindow wndGripper;
3317 wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, rectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR);
3318 ATLASSERT(wndGripper.IsWindow());
3319 if(wndGripper.IsWindow())
3320 {
3321 m_bGripper = true;
3322 RECT rectCtl = { 0 };
3323 wndGripper.GetWindowRect(&rectCtl);
3324 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
3325 _AtlDlgResizeData data = { ATL_IDW_STATUS_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
3326 m_arrData.Add(data);
3327 }
3328 }
3329 }
3330 #else // CE specific
3331 bAddGripper; // avoid level 4 warning
3332 #endif // _WIN32_WCE
3333
3334 // Get min track position if requested
3335 if(bUseMinTrackSize)
3336 {
3337 if((dwStyle & WS_CHILD) != 0)
3338 {
3339 RECT rect = { 0 };
3340 pT->GetClientRect(&rect);
3341 m_ptMinTrackSize.x = rect.right - rect.left;
3342 m_ptMinTrackSize.y = rect.bottom - rect.top;
3343 }
3344 else
3345 {
3346 RECT rect = { 0 };
3347 pT->GetWindowRect(&rect);
3348 m_ptMinTrackSize.x = rect.right - rect.left;
3349 m_ptMinTrackSize.y = rect.bottom - rect.top;
3350 }
3351 }
3352
3353 // Walk the map and initialize data
3354 const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap();
3355 ATLASSERT(pMap != NULL);
3356 int nGroupStart = -1;
3357 for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++)
3358 {
3359 if(pMap->m_nCtlID == -1)
3360 {
3361 switch(pMap->m_dwResizeFlags)
3362 {
3363 case _DLSZ_BEGIN_GROUP:
3364 ATLASSERT(nGroupStart == -1);
3365 nGroupStart = m_arrData.GetSize();
3366 break;
3367 case _DLSZ_END_GROUP:
3368 {
3369 ATLASSERT(nGroupStart != -1);
3370 int nGroupCount = m_arrData.GetSize() - nGroupStart;
3371 m_arrData[nGroupStart].SetGroupCount(nGroupCount);
3372 nGroupStart = -1;
3373 }
3374 break;
3375 default:
3376 ATLASSERT(FALSE && _T("Invalid DLGRESIZE Map Entry"));
3377 break;
3378 }
3379 }
3380 else
3381 {
3382 // this ID conflicts with the default gripper one
3383 ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE);
3384
3385 ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID);
3386 ATLASSERT(ctl.IsWindow());
3387 RECT rectCtl = { 0 };
3388 ctl.GetWindowRect(&rectCtl);
3389 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
3390
3391 DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0;
3392 _AtlDlgResizeData data = { pMap->m_nCtlID, pMap->m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
3393 m_arrData.Add(data);
3394 }
3395 }
3396 ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the DLGRESIZE Map"));
3397 }
3398
3399 void DlgResize_UpdateLayout(int cxWidth, int cyHeight)
3400 {
3401 T* pT = static_cast<T*>(this);
3402 ATLASSERT(::IsWindow(pT->m_hWnd));
3403
3404 // Restrict minimum size if requested
3405 if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
3406 {
3407 if(cxWidth < m_ptMinTrackSize.x)
3408 cxWidth = m_ptMinTrackSize.x;
3409 if(cyHeight < m_ptMinTrackSize.y)
3410 cyHeight = m_ptMinTrackSize.y;
3411 }
3412
3413 BOOL bVisible = pT->IsWindowVisible();
3414 if(bVisible)
3415 pT->SetRedraw(FALSE);
3416
3417 for(int i = 0; i < m_arrData.GetSize(); i++)
3418 {
3419 if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) != 0) // start of a group
3420 {
3421 int nGroupCount = m_arrData[i].GetGroupCount();
3422 ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize());
3423 RECT rectGroup = m_arrData[i].m_rect;
3424
3425 int j = 1;
3426 for(j = 1; j < nGroupCount; j++)
3427 {
3428 rectGroup.left = __min(rectGroup.left, m_arrData[i + j].m_rect.left);
3429 rectGroup.top = __min(rectGroup.top, m_arrData[i + j].m_rect.top);
3430 rectGroup.right = __max(rectGroup.right, m_arrData[i + j].m_rect.right);
3431 rectGroup.bottom = __max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom);
3432 }
3433
3434 for(j = 0; j < nGroupCount; j++)
3435 {
3436 _AtlDlgResizeData* pDataPrev = NULL;
3437 if(j > 0)
3438 pDataPrev = &(m_arrData[i + j - 1]);
3439 pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i + j], true, pDataPrev);
3440 }
3441
3442 i += nGroupCount - 1; // increment to skip all group controls
3443 }
3444 else // one control entry
3445 {
3446 RECT rectGroup = { 0 };
3447 pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i], false);
3448 }
3449 }
3450
3451 if(bVisible)
3452 pT->SetRedraw(TRUE);
3453
3454 pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
3455 }
3456
3457 // Message map and handlers
3458 BEGIN_MSG_MAP(CDialogResize)
3459 MESSAGE_HANDLER(WM_SIZE, OnSize)
3460 #ifndef _WIN32_WCE
3461 MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
3462 #endif // _WIN32_WCE
3463 END_MSG_MAP()
3464
3465 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3466 {
3467 T* pT = static_cast<T*>(this);
3468 #ifndef _WIN32_WCE
3469 if(m_bGripper)
3470 {
3471 ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
3472 if(wParam == SIZE_MAXIMIZED)
3473 wndGripper.ShowWindow(SW_HIDE);
3474 else if(wParam == SIZE_RESTORED)
3475 wndGripper.ShowWindow(SW_SHOW);
3476 }
3477 #endif // _WIN32_WCE
3478 if(wParam != SIZE_MINIMIZED)
3479 {
3480 ATLASSERT(::IsWindow(pT->m_hWnd));
3481 pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
3482 }
3483 return 0;
3484 }
3485
3486 #ifndef _WIN32_WCE
3487 LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
3488 {
3489 if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
3490 {
3491 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
3492 lpMMI->ptMinTrackSize = m_ptMinTrackSize;
3493 }
3494 return 0;
3495 }
3496 #endif // _WIN32_WCE
3497
3498 // Implementation
3499 bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGroup, _AtlDlgResizeData& data, bool bGroup,
3500 _AtlDlgResizeData* pDataPrev = NULL)
3501 {
3502 T* pT = static_cast<T*>(this);
3503 ATLASSERT(::IsWindow(pT->m_hWnd));
3504 ATL::CWindow ctl;
3505 RECT rectCtl = { 0 };
3506
3507 ctl = pT->GetDlgItem(data.m_nCtlID);
3508 if(!ctl.GetWindowRect(&rectCtl))
3509 return false;
3510 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
3511
3512 if(bGroup)
3513 {
3514 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
3515 {
3516 int cxRight = rectGroup.right + cxWidth - m_sizeDialog.cx;
3517 int cxCtl = data.m_rect.right - data.m_rect.left;
3518 rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2;
3519 rectCtl.right = rectCtl.left + cxCtl;
3520 }
3521 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
3522 {
3523 rectCtl.left = rectGroup.left + ::MulDiv(data.m_rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
3524
3525 if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0)
3526 {
3527 rectCtl.right = rectGroup.left + ::MulDiv(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
3528
3529 if(pDataPrev != NULL)
3530 {
3531 ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
3532 RECT rcPrev = { 0 };
3533 ctlPrev.GetWindowRect(&rcPrev);
3534 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
3535 int dxAdjust = (rectCtl.left - rcPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right);
3536 rcPrev.right += dxAdjust;
3537 ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
3538 }
3539 }
3540 else
3541 {
3542 rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left);
3543 }
3544 }
3545
3546 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
3547 {
3548 int cyBottom = rectGroup.bottom + cyHeight - m_sizeDialog.cy;
3549 int cyCtl = data.m_rect.bottom - data.m_rect.top;
3550 rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2;
3551 rectCtl.bottom = rectCtl.top + cyCtl;
3552 }
3553 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
3554 {
3555 rectCtl.top = rectGroup.top + ::MulDiv(data.m_rect.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
3556
3557 if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0)
3558 {
3559 rectCtl.bottom = rectGroup.top + ::MulDiv(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
3560
3561 if(pDataPrev != NULL)
3562 {
3563 ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
3564 RECT rcPrev = { 0 };
3565 ctlPrev.GetWindowRect(&rcPrev);
3566 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
3567 int dxAdjust = (rectCtl.top - rcPrev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom);
3568 rcPrev.bottom += dxAdjust;
3569 ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
3570 }
3571 }
3572 else
3573 {
3574 rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top);
3575 }
3576 }
3577 }
3578 else // no group
3579 {
3580 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
3581 {
3582 int cxCtl = data.m_rect.right - data.m_rect.left;
3583 rectCtl.left = (cxWidth - cxCtl) / 2;
3584 rectCtl.right = rectCtl.left + cxCtl;
3585 }
3586 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
3587 {
3588 rectCtl.right = data.m_rect.right + (cxWidth - m_sizeDialog.cx);
3589
3590 if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0)
3591 rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left);
3592 }
3593
3594 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
3595 {
3596 int cyCtl = data.m_rect.bottom - data.m_rect.top;
3597 rectCtl.top = (cyHeight - cyCtl) / 2;
3598 rectCtl.bottom = rectCtl.top + cyCtl;
3599 }
3600 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
3601 {
3602 rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeDialog.cy);
3603
3604 if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0)
3605 rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top);
3606 }
3607 }
3608
3609 if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0)
3610 ctl.Invalidate();
3611
3612 if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0)
3613 ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE);
3614
3615 return true;
3616 }
3617 };
3618
3619
3620 ///////////////////////////////////////////////////////////////////////////////
3621 // CDoubleBufferImpl - Provides double-buffer painting support to any window
3622
3623 template <class T>
3624 class CDoubleBufferImpl
3625 {
3626 public:
3627 // Overrideables
3628 void DoPaint(CDCHandle /*dc*/)
3629 {
3630 // must be implemented in a derived class
3631 ATLASSERT(FALSE);
3632 }
3633
3634 // Message map and handlers
3635 BEGIN_MSG_MAP(CDoubleBufferImpl)
3636 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
3637 MESSAGE_HANDLER(WM_PAINT, OnPaint)
3638 #ifndef _WIN32_WCE
3639 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
3640 #endif // !_WIN32_WCE
3641 END_MSG_MAP()
3642
3643 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
3644 {
3645 return 1; // no background painting needed
3646 }
3647
3648 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
3649 {
3650 T* pT = static_cast<T*>(this);
3651 ATLASSERT(::IsWindow(pT->m_hWnd));
3652
3653 if(wParam != NULL)
3654 {
3655 RECT rect = { 0 };
3656 pT->GetClientRect(&rect);
3657 CMemoryDC dcMem((HDC)wParam, rect);
3658 pT->DoPaint(dcMem.m_hDC);
3659 }
3660 else
3661 {
3662 CPaintDC dc(pT->m_hWnd);
3663 CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint);
3664 pT->DoPaint(dcMem.m_hDC);
3665 }
3666
3667 return 0;
3668 }
3669 };
3670
3671
3672 ///////////////////////////////////////////////////////////////////////////////
3673 // CDoubleBufferWindowImpl - Implements a double-buffer painting window
3674
3675 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
3676 class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CDoubleBufferImpl< T >
3677 {
3678 public:
3679 BEGIN_MSG_MAP(CDoubleBufferWindowImpl)
3680 CHAIN_MSG_MAP(CDoubleBufferImpl< T >)
3681 END_MSG_MAP()
3682 };
3683
3684
3685 // command bar support
3686 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
3687 #undef CBRM_GETMENU
3688 #undef CBRM_TRACKPOPUPMENU
3689 #undef CBRM_GETCMDBAR
3690 #undef CBRPOPUPMENU
3691 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
3692
3693 }; // namespace WTL
3694
3695 #endif // __ATLFRAME_H__
+0
-3889
src/third_party/wtl/Include/atlgdi.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLGDI_H__
9 #define __ATLGDI_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlgdi.h requires atlapp.h to be included first
15 #endif
16
17
18 // protect template members from windowsx.h macros
19 #ifdef _INC_WINDOWSX
20 #undef CopyRgn
21 #undef CreateBrush
22 #undef CreatePen
23 #undef SelectBrush
24 #undef SelectPen
25 #undef SelectFont
26 #undef SelectBitmap
27 #endif // _INC_WINDOWSX
28
29 // required libraries
30 #if !defined(_ATL_NO_MSIMG) && !defined(_WIN32_WCE)
31 #pragma comment(lib, "msimg32.lib")
32 #endif
33 #if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
34 #pragma comment(lib, "opengl32.lib")
35 #endif
36
37
38 ///////////////////////////////////////////////////////////////////////////////
39 // Classes in this file:
40 //
41 // CPenT<t_bManaged>
42 // CBrushT<t_bManaged>
43 // CLogFont
44 // CFontT<t_bManaged>
45 // CBitmapT<t_bManaged>
46 // CPaletteT<t_bManaged>
47 // CRgnT<t_bManaged>
48 // CDCT<t_bManaged>
49 // CPaintDC
50 // CClientDC
51 // CWindowDC
52 // CMemoryDC
53 // CEnhMetaFileInfo
54 // CEnhMetaFileT<t_bManaged>
55 // CEnhMetaFileDC
56 //
57 // Global functions:
58 // AtlGetBitmapResourceInfo()
59 // AtlGetBitmapResourceBitsPerPixel()
60 // AtlIsAlphaBitmapResource()
61 // AtlIsDib16()
62 // AtlGetDibColorTableSize()
63 // AtlGetDibNumColors(),
64 // AtlGetDibBitmap()
65 // AtlCopyBitmap()
66 // AtlCreatePackedDib16()
67 // AtlSetClipboardDib16()
68 // AtlGetClipboardDib()
69
70
71 namespace WTL
72 {
73
74 ///////////////////////////////////////////////////////////////////////////////
75 // Bitmap resource helpers to extract bitmap information for a bitmap resource
76
77 inline LPBITMAPINFOHEADER AtlGetBitmapResourceInfo(HMODULE hModule, ATL::_U_STRINGorID image)
78 {
79 HRSRC hResource = ::FindResource(hModule, image.m_lpstr, RT_BITMAP);
80 ATLASSERT(hResource != NULL);
81 HGLOBAL hGlobal = ::LoadResource(hModule, hResource);
82 ATLASSERT(hGlobal != NULL);
83 LPBITMAPINFOHEADER pBitmapInfoHeader = (LPBITMAPINFOHEADER)::LockResource(hGlobal);
84 ATLASSERT(pBitmapInfoHeader != NULL);
85 return pBitmapInfoHeader;
86 }
87
88 inline WORD AtlGetBitmapResourceBitsPerPixel(HMODULE hModule, ATL::_U_STRINGorID image)
89 {
90 LPBITMAPINFOHEADER pBitmapInfoHeader = AtlGetBitmapResourceInfo(hModule, image);
91 ATLASSERT(pBitmapInfoHeader != NULL);
92 return pBitmapInfoHeader->biBitCount;
93 }
94
95 inline WORD AtlGetBitmapResourceBitsPerPixel(ATL::_U_STRINGorID image)
96 {
97 return AtlGetBitmapResourceBitsPerPixel(ModuleHelper::GetResourceInstance(), image);
98 }
99
100 ///////////////////////////////////////////////////////////////////////////////
101 // 32-bit (alpha channel) bitmap resource helper
102
103 // Note: 32-bit (alpha channel) images work only on Windows XP with Common Controls version 6.
104 // If you want your app to work on older version of Windows, load non-alpha images if Common
105 // Controls version is less than 6.
106
107 inline bool AtlIsAlphaBitmapResource(ATL::_U_STRINGorID image)
108 {
109 return (AtlGetBitmapResourceBitsPerPixel(image) == 32);
110 }
111
112
113 ///////////////////////////////////////////////////////////////////////////////
114 // CPen
115
116 template <bool t_bManaged>
117 class CPenT
118 {
119 public:
120 // Data members
121 HPEN m_hPen;
122
123 // Constructor/destructor/operators
124 CPenT(HPEN hPen = NULL) : m_hPen(hPen)
125 { }
126
127 ~CPenT()
128 {
129 if(t_bManaged && m_hPen != NULL)
130 DeleteObject();
131 }
132
133 CPenT<t_bManaged>& operator =(HPEN hPen)
134 {
135 Attach(hPen);
136 return *this;
137 }
138
139 void Attach(HPEN hPen)
140 {
141 if(t_bManaged && m_hPen != NULL && m_hPen != hPen)
142 ::DeleteObject(m_hPen);
143 m_hPen = hPen;
144 }
145
146 HPEN Detach()
147 {
148 HPEN hPen = m_hPen;
149 m_hPen = NULL;
150 return hPen;
151 }
152
153 operator HPEN() const { return m_hPen; }
154
155 bool IsNull() const { return (m_hPen == NULL); }
156
157 // Create methods
158 HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
159 {
160 ATLASSERT(m_hPen == NULL);
161 m_hPen = ::CreatePen(nPenStyle, nWidth, crColor);
162 return m_hPen;
163 }
164
165 #ifndef _WIN32_WCE
166 HPEN CreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL)
167 {
168 ATLASSERT(m_hPen == NULL);
169 m_hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle);
170 return m_hPen;
171 }
172 #endif // !_WIN32_WCE
173
174 HPEN CreatePenIndirect(LPLOGPEN lpLogPen)
175 {
176 ATLASSERT(m_hPen == NULL);
177 m_hPen = ::CreatePenIndirect(lpLogPen);
178 return m_hPen;
179 }
180
181 BOOL DeleteObject()
182 {
183 ATLASSERT(m_hPen != NULL);
184 BOOL bRet = ::DeleteObject(m_hPen);
185 if(bRet)
186 m_hPen = NULL;
187 return bRet;
188 }
189
190 // Attributes
191 int GetLogPen(LOGPEN* pLogPen) const
192 {
193 ATLASSERT(m_hPen != NULL);
194 return ::GetObject(m_hPen, sizeof(LOGPEN), pLogPen);
195 }
196
197 bool GetLogPen(LOGPEN& LogPen) const
198 {
199 ATLASSERT(m_hPen != NULL);
200 return (::GetObject(m_hPen, sizeof(LOGPEN), &LogPen) == sizeof(LOGPEN));
201 }
202
203 #ifndef _WIN32_WCE
204 int GetExtLogPen(EXTLOGPEN* pLogPen, int nSize = sizeof(EXTLOGPEN)) const
205 {
206 ATLASSERT(m_hPen != NULL);
207 return ::GetObject(m_hPen, nSize, pLogPen);
208 }
209
210 bool GetExtLogPen(EXTLOGPEN& ExtLogPen, int nSize = sizeof(EXTLOGPEN)) const
211 {
212 ATLASSERT(m_hPen != NULL);
213 int nRet = ::GetObject(m_hPen, nSize, &ExtLogPen);
214 return ((nRet > 0) && (nRet <= nSize));
215 }
216 #endif // !_WIN32_WCE
217 };
218
219 typedef CPenT<false> CPenHandle;
220 typedef CPenT<true> CPen;
221
222
223 ///////////////////////////////////////////////////////////////////////////////
224 // CBrush
225
226 template <bool t_bManaged>
227 class CBrushT
228 {
229 public:
230 // Data members
231 HBRUSH m_hBrush;
232
233 // Constructor/destructor/operators
234 CBrushT(HBRUSH hBrush = NULL) : m_hBrush(hBrush)
235 { }
236
237 ~CBrushT()
238 {
239 if(t_bManaged && m_hBrush != NULL)
240 DeleteObject();
241 }
242
243 CBrushT<t_bManaged>& operator =(HBRUSH hBrush)
244 {
245 Attach(hBrush);
246 return *this;
247 }
248
249 void Attach(HBRUSH hBrush)
250 {
251 if(t_bManaged && m_hBrush != NULL && m_hBrush != hBrush)
252 ::DeleteObject(m_hBrush);
253 m_hBrush = hBrush;
254 }
255
256 HBRUSH Detach()
257 {
258 HBRUSH hBrush = m_hBrush;
259 m_hBrush = NULL;
260 return hBrush;
261 }
262
263 operator HBRUSH() const { return m_hBrush; }
264
265 bool IsNull() const { return (m_hBrush == NULL); }
266
267 // Create methods
268 HBRUSH CreateSolidBrush(COLORREF crColor)
269 {
270 ATLASSERT(m_hBrush == NULL);
271 m_hBrush = ::CreateSolidBrush(crColor);
272 return m_hBrush;
273 }
274
275 #ifndef _WIN32_WCE
276 HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor)
277 {
278 ATLASSERT(m_hBrush == NULL);
279 m_hBrush = ::CreateHatchBrush(nIndex, crColor);
280 return m_hBrush;
281 }
282 #endif // !_WIN32_WCE
283
284 #if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
285 HBRUSH CreateBrushIndirect(const LOGBRUSH* lpLogBrush)
286 {
287 ATLASSERT(m_hBrush == NULL);
288 #ifndef _WIN32_WCE
289 m_hBrush = ::CreateBrushIndirect(lpLogBrush);
290 #else // CE specific
291 m_hBrush = ATL::CreateBrushIndirect(lpLogBrush);
292 #endif // _WIN32_WCE
293 return m_hBrush;
294 }
295 #endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
296
297 HBRUSH CreatePatternBrush(HBITMAP hBitmap)
298 {
299 ATLASSERT(m_hBrush == NULL);
300 m_hBrush = ::CreatePatternBrush(hBitmap);
301 return m_hBrush;
302 }
303
304 HBRUSH CreateDIBPatternBrush(HGLOBAL hPackedDIB, UINT nUsage)
305 {
306 ATLASSERT(hPackedDIB != NULL);
307 const void* lpPackedDIB = GlobalLock(hPackedDIB);
308 ATLASSERT(lpPackedDIB != NULL);
309 m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
310 GlobalUnlock(hPackedDIB);
311 return m_hBrush;
312 }
313
314 HBRUSH CreateDIBPatternBrush(const void* lpPackedDIB, UINT nUsage)
315 {
316 ATLASSERT(m_hBrush == NULL);
317 m_hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
318 return m_hBrush;
319 }
320
321 HBRUSH CreateSysColorBrush(int nIndex)
322 {
323 ATLASSERT(m_hBrush == NULL);
324 m_hBrush = ::GetSysColorBrush(nIndex);
325 return m_hBrush;
326 }
327
328 BOOL DeleteObject()
329 {
330 ATLASSERT(m_hBrush != NULL);
331 BOOL bRet = ::DeleteObject(m_hBrush);
332 if(bRet)
333 m_hBrush = NULL;
334 return bRet;
335 }
336
337 // Attributes
338 int GetLogBrush(LOGBRUSH* pLogBrush) const
339 {
340 ATLASSERT(m_hBrush != NULL);
341 return ::GetObject(m_hBrush, sizeof(LOGBRUSH), pLogBrush);
342 }
343
344 bool GetLogBrush(LOGBRUSH& LogBrush) const
345 {
346 ATLASSERT(m_hBrush != NULL);
347 return (::GetObject(m_hBrush, sizeof(LOGBRUSH), &LogBrush) == sizeof(LOGBRUSH));
348 }
349 };
350
351 typedef CBrushT<false> CBrushHandle;
352 typedef CBrushT<true> CBrush;
353
354
355 ///////////////////////////////////////////////////////////////////////////////
356 // CFont
357
358 class CLogFont : public LOGFONT
359 {
360 public:
361 CLogFont()
362 {
363 memset(this, 0, sizeof(LOGFONT));
364 }
365
366 CLogFont(const LOGFONT& lf)
367 {
368 Copy(&lf);
369 }
370
371 CLogFont(HFONT hFont)
372 {
373 ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
374 ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
375 }
376
377 HFONT CreateFontIndirect()
378 {
379 return ::CreateFontIndirect(this);
380 }
381
382 void SetBold()
383 {
384 lfWeight = FW_BOLD;
385 }
386
387 bool IsBold() const
388 {
389 return (lfWeight >= FW_BOLD);
390 }
391
392 void MakeBolder(int iScale = 1)
393 {
394 lfWeight += FW_BOLD * iScale;
395 }
396
397 void MakeLarger(int iScale)
398 {
399 if(lfHeight > 0)
400 lfHeight += iScale;
401 else
402 lfHeight -= iScale;
403 }
404
405 void SetHeight(LONG nPointSize, HDC hDC = NULL)
406 {
407 HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
408 // For MM_TEXT mapping mode
409 lfHeight = -::MulDiv(nPointSize, ::GetDeviceCaps(hDC1, LOGPIXELSY), 72);
410 if(hDC == NULL)
411 ::ReleaseDC(NULL, hDC1);
412 }
413
414 LONG GetHeight(HDC hDC = NULL) const
415 {
416 HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
417 // For MM_TEXT mapping mode
418 LONG nPointSize = ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC1, LOGPIXELSY));
419 if(hDC == NULL)
420 ::ReleaseDC(NULL, hDC1);
421
422 return nPointSize;
423 }
424
425 LONG GetDeciPointHeight(HDC hDC = NULL) const
426 {
427 HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
428 #ifndef _WIN32_WCE
429 POINT ptOrg = { 0, 0 };
430 ::DPtoLP(hDC1, &ptOrg, 1);
431 POINT pt = { 0, 0 };
432 pt.y = abs(lfHeight) + ptOrg.y;
433 ::LPtoDP(hDC1, &pt,1);
434 LONG nDeciPoint = ::MulDiv(pt.y, 720, ::GetDeviceCaps(hDC1, LOGPIXELSY)); // 72 points/inch, 10 decipoints/point
435 #else // CE specific
436 // DP and LP are always the same on CE
437 LONG nDeciPoint = ::MulDiv(abs(lfHeight), 720, ::GetDeviceCaps(hDC1, LOGPIXELSY)); // 72 points/inch, 10 decipoints/point
438 #endif // _WIN32_WCE
439 if(hDC == NULL)
440 ::ReleaseDC(NULL, hDC1);
441
442 return nDeciPoint;
443 }
444
445 void SetHeightFromDeciPoint(LONG nDeciPtHeight, HDC hDC = NULL)
446 {
447 HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
448 #ifndef _WIN32_WCE
449 POINT pt = { 0, 0 };
450 pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), nDeciPtHeight, 720); // 72 points/inch, 10 decipoints/point
451 ::DPtoLP(hDC1, &pt, 1);
452 POINT ptOrg = { 0, 0 };
453 ::DPtoLP(hDC1, &ptOrg, 1);
454 lfHeight = -abs(pt.y - ptOrg.y);
455 #else // CE specific
456 // DP and LP are always the same on CE
457 lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), nDeciPtHeight, 720)); // 72 points/inch, 10 decipoints/point
458 #endif // _WIN32_WCE
459 if(hDC == NULL)
460 ::ReleaseDC(NULL, hDC1);
461 }
462
463 #ifndef _WIN32_WCE
464 void SetCaptionFont()
465 {
466 NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
467 ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
468 Copy(&ncm.lfCaptionFont);
469 }
470
471 void SetMenuFont()
472 {
473 NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
474 ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
475 Copy(&ncm.lfMenuFont);
476 }
477
478 void SetStatusFont()
479 {
480 NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
481 ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
482 Copy(&ncm.lfStatusFont);
483 }
484
485 void SetMessageBoxFont()
486 {
487 NONCLIENTMETRICS ncm = { RunTimeHelper::SizeOf_NONCLIENTMETRICS() };
488 ATLVERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0));
489 Copy(&ncm.lfMessageFont);
490 }
491 #endif // !_WIN32_WCE
492
493 void Copy(const LOGFONT* pLogFont)
494 {
495 ATLASSERT(pLogFont != NULL);
496 *(LOGFONT*)this = *pLogFont;
497 }
498
499 CLogFont& operator =(const CLogFont& src)
500 {
501 Copy(&src);
502 return *this;
503 }
504
505 CLogFont& operator =(const LOGFONT& src)
506 {
507 Copy(&src);
508 return *this;
509 }
510
511 CLogFont& operator =(HFONT hFont)
512 {
513 ATLASSERT(::GetObjectType(hFont) == OBJ_FONT);
514 ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*)this);
515 return *this;
516 }
517
518 bool operator ==(const LOGFONT& logfont) const
519 {
520 return(logfont.lfHeight == lfHeight &&
521 logfont.lfWidth == lfWidth &&
522 logfont.lfEscapement == lfEscapement &&
523 logfont.lfOrientation == lfOrientation &&
524 logfont.lfWeight == lfWeight &&
525 logfont.lfItalic == lfItalic &&
526 logfont.lfUnderline == lfUnderline &&
527 logfont.lfStrikeOut == lfStrikeOut &&
528 logfont.lfCharSet == lfCharSet &&
529 logfont.lfOutPrecision == lfOutPrecision &&
530 logfont.lfClipPrecision == lfClipPrecision &&
531 logfont.lfQuality == lfQuality &&
532 logfont.lfPitchAndFamily == lfPitchAndFamily &&
533 lstrcmp(logfont.lfFaceName, lfFaceName) == 0);
534 }
535 };
536
537
538 template <bool t_bManaged>
539 class CFontT
540 {
541 public:
542 // Data members
543 HFONT m_hFont;
544
545 // Constructor/destructor/operators
546 CFontT(HFONT hFont = NULL) : m_hFont(hFont)
547 { }
548
549 ~CFontT()
550 {
551 if(t_bManaged && m_hFont != NULL)
552 DeleteObject();
553 }
554
555 CFontT<t_bManaged>& operator =(HFONT hFont)
556 {
557 Attach(hFont);
558 return *this;
559 }
560
561 void Attach(HFONT hFont)
562 {
563 if(t_bManaged && m_hFont != NULL && m_hFont != hFont)
564 ::DeleteObject(m_hFont);
565 m_hFont = hFont;
566 }
567
568 HFONT Detach()
569 {
570 HFONT hFont = m_hFont;
571 m_hFont = NULL;
572 return hFont;
573 }
574
575 operator HFONT() const { return m_hFont; }
576
577 bool IsNull() const { return (m_hFont == NULL); }
578
579 // Create methods
580 HFONT CreateFontIndirect(const LOGFONT* lpLogFont)
581 {
582 ATLASSERT(m_hFont == NULL);
583 m_hFont = ::CreateFontIndirect(lpLogFont);
584 return m_hFont;
585 }
586
587 #if !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500)
588 HFONT CreateFontIndirectEx(CONST ENUMLOGFONTEXDV* penumlfex)
589 {
590 ATLASSERT(m_hFont == NULL);
591 m_hFont = ::CreateFontIndirectEx(penumlfex);
592 return m_hFont;
593 }
594 #endif // !defined(_WIN32_WCE) && (_WIN32_WINNT >= 0x0500)
595
596 #if !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
597 HFONT CreateFont(int nHeight, int nWidth, int nEscapement,
598 int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline,
599 BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision,
600 BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily,
601 LPCTSTR lpszFacename)
602 {
603 ATLASSERT(m_hFont == NULL);
604 #ifndef _WIN32_WCE
605 m_hFont = ::CreateFont(nHeight, nWidth, nEscapement,
606 nOrientation, nWeight, bItalic, bUnderline, cStrikeOut,
607 nCharSet, nOutPrecision, nClipPrecision, nQuality,
608 nPitchAndFamily, lpszFacename);
609 #else // CE specific
610 m_hFont = ATL::CreateFont(nHeight, nWidth, nEscapement,
611 nOrientation, nWeight, bItalic, bUnderline, cStrikeOut,
612 nCharSet, nOutPrecision, nClipPrecision, nQuality,
613 nPitchAndFamily, lpszFacename);
614 #endif // _WIN32_WCE
615 return m_hFont;
616 }
617 #endif // !defined(_WIN32_WCE) || (_ATL_VER >= 0x0800)
618
619 HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, HDC hDC = NULL, bool bBold = false, bool bItalic = false)
620 {
621 LOGFONT logFont = { 0 };
622 logFont.lfCharSet = DEFAULT_CHARSET;
623 logFont.lfHeight = nPointSize;
624 SecureHelper::strncpy_x(logFont.lfFaceName, _countof(logFont.lfFaceName), lpszFaceName, _TRUNCATE);
625
626 if(bBold)
627 logFont.lfWeight = FW_BOLD;
628 if(bItalic)
629 logFont.lfItalic = (BYTE)TRUE;
630
631 return CreatePointFontIndirect(&logFont, hDC);
632 }
633
634 HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, HDC hDC = NULL)
635 {
636 HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(NULL);
637
638 // convert nPointSize to logical units based on hDC
639 LOGFONT logFont = *lpLogFont;
640 #ifndef _WIN32_WCE
641 POINT pt = { 0, 0 };
642 pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720); // 72 points/inch, 10 decipoints/point
643 ::DPtoLP(hDC1, &pt, 1);
644 POINT ptOrg = { 0, 0 };
645 ::DPtoLP(hDC1, &ptOrg, 1);
646 logFont.lfHeight = -abs(pt.y - ptOrg.y);
647 #else // CE specific
648 // DP and LP are always the same on CE
649 logFont.lfHeight = -abs(::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720)); // 72 points/inch, 10 decipoints/point
650 #endif // _WIN32_WCE
651
652 if(hDC == NULL)
653 ::ReleaseDC(NULL, hDC1);
654
655 return CreateFontIndirect(&logFont);
656 }
657
658 BOOL DeleteObject()
659 {
660 ATLASSERT(m_hFont != NULL);
661 BOOL bRet = ::DeleteObject(m_hFont);
662 if(bRet)
663 m_hFont = NULL;
664 return bRet;
665 }
666
667 // Attributes
668 int GetLogFont(LOGFONT* pLogFont) const
669 {
670 ATLASSERT(m_hFont != NULL);
671 return ::GetObject(m_hFont, sizeof(LOGFONT), pLogFont);
672 }
673
674 bool GetLogFont(LOGFONT& LogFont) const
675 {
676 ATLASSERT(m_hFont != NULL);
677 return (::GetObject(m_hFont, sizeof(LOGFONT), &LogFont) == sizeof(LOGFONT));
678 }
679 };
680
681 typedef CFontT<false> CFontHandle;
682 typedef CFontT<true> CFont;
683
684
685 ///////////////////////////////////////////////////////////////////////////////
686 // CBitmap
687
688 template <bool t_bManaged>
689 class CBitmapT
690 {
691 public:
692 // Data members
693 HBITMAP m_hBitmap;
694
695 // Constructor/destructor/operators
696 CBitmapT(HBITMAP hBitmap = NULL) : m_hBitmap(hBitmap)
697 { }
698
699 ~CBitmapT()
700 {
701 if(t_bManaged && m_hBitmap != NULL)
702 DeleteObject();
703 }
704
705 CBitmapT<t_bManaged>& operator =(HBITMAP hBitmap)
706 {
707 Attach(hBitmap);
708 return *this;
709 }
710
711 void Attach(HBITMAP hBitmap)
712 {
713 if(t_bManaged && m_hBitmap != NULL&& m_hBitmap != hBitmap)
714 ::DeleteObject(m_hBitmap);
715 m_hBitmap = hBitmap;
716 }
717
718 HBITMAP Detach()
719 {
720 HBITMAP hBitmap = m_hBitmap;
721 m_hBitmap = NULL;
722 return hBitmap;
723 }
724
725 operator HBITMAP() const { return m_hBitmap; }
726
727 bool IsNull() const { return (m_hBitmap == NULL); }
728
729 // Create and load methods
730 HBITMAP LoadBitmap(ATL::_U_STRINGorID bitmap)
731 {
732 ATLASSERT(m_hBitmap == NULL);
733 m_hBitmap = ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr);
734 return m_hBitmap;
735 }
736
737 HBITMAP LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
738 {
739 ATLASSERT(m_hBitmap == NULL);
740 m_hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap));
741 return m_hBitmap;
742 }
743
744 #ifndef _WIN32_WCE
745 HBITMAP LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0)
746 {
747 ATLASSERT(m_hBitmap == NULL);
748 m_hBitmap = ::CreateMappedBitmap(ModuleHelper::GetResourceInstance(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
749 return m_hBitmap;
750 }
751 #endif // !_WIN32_WCE
752
753 HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, const void* lpBits)
754 {
755 ATLASSERT(m_hBitmap == NULL);
756 m_hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits);
757 return m_hBitmap;
758 }
759
760 #ifndef _WIN32_WCE
761 HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap)
762 {
763 ATLASSERT(m_hBitmap == NULL);
764 m_hBitmap = ::CreateBitmapIndirect(lpBitmap);
765 return m_hBitmap;
766 }
767 #endif // !_WIN32_WCE
768
769 HBITMAP CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight)
770 {
771 ATLASSERT(m_hBitmap == NULL);
772 m_hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
773 return m_hBitmap;
774 }
775
776 #ifndef _WIN32_WCE
777 HBITMAP CreateDiscardableBitmap(HDC hDC, int nWidth, int nHeight)
778 {
779 ATLASSERT(m_hBitmap == NULL);
780 m_hBitmap = ::CreateDiscardableBitmap(hDC, nWidth, nHeight);
781 return m_hBitmap;
782 }
783 #endif // !_WIN32_WCE
784
785 BOOL DeleteObject()
786 {
787 ATLASSERT(m_hBitmap != NULL);
788 BOOL bRet = ::DeleteObject(m_hBitmap);
789 if(bRet)
790 m_hBitmap = NULL;
791 return bRet;
792 }
793
794 // Attributes
795 int GetBitmap(BITMAP* pBitMap) const
796 {
797 ATLASSERT(m_hBitmap != NULL);
798 return ::GetObject(m_hBitmap, sizeof(BITMAP), pBitMap);
799 }
800
801 bool GetBitmap(BITMAP& bm) const
802 {
803 ATLASSERT(m_hBitmap != NULL);
804 return (::GetObject(m_hBitmap, sizeof(BITMAP), &bm) == sizeof(BITMAP));
805 }
806
807 bool GetSize(SIZE& size) const
808 {
809 ATLASSERT(m_hBitmap != NULL);
810 BITMAP bm = { 0 };
811 if(!GetBitmap(&bm))
812 return false;
813 size.cx = bm.bmWidth;
814 size.cy = bm.bmHeight;
815 return true;
816 }
817
818 #ifndef _WIN32_WCE
819 DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const
820 {
821 ATLASSERT(m_hBitmap != NULL);
822 return ::GetBitmapBits(m_hBitmap, dwCount, lpBits);
823 }
824 #endif // !_WIN32_WCE
825
826 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
827 DWORD SetBitmapBits(DWORD dwCount, const void* lpBits)
828 {
829 ATLASSERT(m_hBitmap != NULL);
830 return ::SetBitmapBits(m_hBitmap, dwCount, lpBits);
831 }
832 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
833
834 #ifndef _WIN32_WCE
835 BOOL GetBitmapDimension(LPSIZE lpSize) const
836 {
837 ATLASSERT(m_hBitmap != NULL);
838 return ::GetBitmapDimensionEx(m_hBitmap, lpSize);
839 }
840
841 BOOL SetBitmapDimension(int nWidth, int nHeight, LPSIZE lpSize = NULL)
842 {
843 ATLASSERT(m_hBitmap != NULL);
844 return ::SetBitmapDimensionEx(m_hBitmap, nWidth, nHeight, lpSize);
845 }
846
847 // DIB support
848 HBITMAP CreateDIBitmap(HDC hDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse)
849 {
850 ATLASSERT(m_hBitmap == NULL);
851 m_hBitmap = ::CreateDIBitmap(hDC, lpbmih, dwInit, lpbInit, lpbmi, uColorUse);
852 return m_hBitmap;
853 }
854 #endif // !_WIN32_WCE
855
856 HBITMAP CreateDIBSection(HDC hDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset)
857 {
858 ATLASSERT(m_hBitmap == NULL);
859 m_hBitmap = ::CreateDIBSection(hDC, lpbmi, uColorUse, ppvBits, hSection, dwOffset);
860 return m_hBitmap;
861 }
862
863 #ifndef _WIN32_WCE
864 int GetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const
865 {
866 ATLASSERT(m_hBitmap != NULL);
867 return ::GetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
868 }
869
870 int SetDIBits(HDC hDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
871 {
872 ATLASSERT(m_hBitmap != NULL);
873 return ::SetDIBits(hDC, m_hBitmap, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
874 }
875 #endif // !_WIN32_WCE
876 };
877
878 typedef CBitmapT<false> CBitmapHandle;
879 typedef CBitmapT<true> CBitmap;
880
881
882 ///////////////////////////////////////////////////////////////////////////////
883 // CPalette
884
885 template <bool t_bManaged>
886 class CPaletteT
887 {
888 public:
889 // Data members
890 HPALETTE m_hPalette;
891
892 // Constructor/destructor/operators
893 CPaletteT(HPALETTE hPalette = NULL) : m_hPalette(hPalette)
894 { }
895
896 ~CPaletteT()
897 {
898 if(t_bManaged && m_hPalette != NULL)
899 DeleteObject();
900 }
901
902 CPaletteT<t_bManaged>& operator =(HPALETTE hPalette)
903 {
904 Attach(hPalette);
905 return *this;
906 }
907
908 void Attach(HPALETTE hPalette)
909 {
910 if(t_bManaged && m_hPalette != NULL && m_hPalette != hPalette)
911 ::DeleteObject(m_hPalette);
912 m_hPalette = hPalette;
913 }
914
915 HPALETTE Detach()
916 {
917 HPALETTE hPalette = m_hPalette;
918 m_hPalette = NULL;
919 return hPalette;
920 }
921
922 operator HPALETTE() const { return m_hPalette; }
923
924 bool IsNull() const { return (m_hPalette == NULL); }
925
926 // Create methods
927 HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette)
928 {
929 ATLASSERT(m_hPalette == NULL);
930 m_hPalette = ::CreatePalette(lpLogPalette);
931 return m_hPalette;
932 }
933
934 #ifndef _WIN32_WCE
935 HPALETTE CreateHalftonePalette(HDC hDC)
936 {
937 ATLASSERT(m_hPalette == NULL);
938 ATLASSERT(hDC != NULL);
939 m_hPalette = ::CreateHalftonePalette(hDC);
940 return m_hPalette;
941 }
942 #endif // !_WIN32_WCE
943
944 BOOL DeleteObject()
945 {
946 ATLASSERT(m_hPalette != NULL);
947 BOOL bRet = ::DeleteObject(m_hPalette);
948 if(bRet)
949 m_hPalette = NULL;
950 return bRet;
951 }
952
953 // Attributes
954 int GetEntryCount() const
955 {
956 ATLASSERT(m_hPalette != NULL);
957 WORD nEntries = 0;
958 ::GetObject(m_hPalette, sizeof(WORD), &nEntries);
959 return (int)nEntries;
960 }
961
962 UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const
963 {
964 ATLASSERT(m_hPalette != NULL);
965 return ::GetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
966 }
967
968 UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
969 {
970 ATLASSERT(m_hPalette != NULL);
971 return ::SetPaletteEntries(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
972 }
973
974 // Operations
975 #ifndef _WIN32_WCE
976 void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
977 {
978 ATLASSERT(m_hPalette != NULL);
979 ::AnimatePalette(m_hPalette, nStartIndex, nNumEntries, lpPaletteColors);
980 }
981
982 BOOL ResizePalette(UINT nNumEntries)
983 {
984 ATLASSERT(m_hPalette != NULL);
985 return ::ResizePalette(m_hPalette, nNumEntries);
986 }
987 #endif // !_WIN32_WCE
988
989 UINT GetNearestPaletteIndex(COLORREF crColor) const
990 {
991 ATLASSERT(m_hPalette != NULL);
992 return ::GetNearestPaletteIndex(m_hPalette, crColor);
993 }
994 };
995
996 typedef CPaletteT<false> CPaletteHandle;
997 typedef CPaletteT<true> CPalette;
998
999
1000 ///////////////////////////////////////////////////////////////////////////////
1001 // CRgn
1002
1003 template <bool t_bManaged>
1004 class CRgnT
1005 {
1006 public:
1007 // Data members
1008 HRGN m_hRgn;
1009
1010 // Constructor/destructor/operators
1011 CRgnT(HRGN hRgn = NULL) : m_hRgn(hRgn)
1012 { }
1013
1014 ~CRgnT()
1015 {
1016 if(t_bManaged && m_hRgn != NULL)
1017 DeleteObject();
1018 }
1019
1020 CRgnT<t_bManaged>& operator =(HRGN hRgn)
1021 {
1022 Attach(hRgn);
1023 return *this;
1024 }
1025
1026 void Attach(HRGN hRgn)
1027 {
1028 if(t_bManaged && m_hRgn != NULL && m_hRgn != hRgn)
1029 ::DeleteObject(m_hRgn);
1030 m_hRgn = hRgn;
1031 }
1032
1033 HRGN Detach()
1034 {
1035 HRGN hRgn = m_hRgn;
1036 m_hRgn = NULL;
1037 return hRgn;
1038 }
1039
1040 operator HRGN() const { return m_hRgn; }
1041
1042 bool IsNull() const { return (m_hRgn == NULL); }
1043
1044 // Create methods
1045 HRGN CreateRectRgn(int x1, int y1, int x2, int y2)
1046 {
1047 ATLASSERT(m_hRgn == NULL);
1048 m_hRgn = ::CreateRectRgn(x1, y1, x2, y2);
1049 return m_hRgn;
1050 }
1051
1052 HRGN CreateRectRgnIndirect(LPCRECT lpRect)
1053 {
1054 ATLASSERT(m_hRgn == NULL);
1055 m_hRgn = ::CreateRectRgnIndirect(lpRect);
1056 return m_hRgn;
1057 }
1058
1059 #ifndef _WIN32_WCE
1060 HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2)
1061 {
1062 ATLASSERT(m_hRgn == NULL);
1063 m_hRgn = ::CreateEllipticRgn(x1, y1, x2, y2);
1064 return m_hRgn;
1065 }
1066
1067 HRGN CreateEllipticRgnIndirect(LPCRECT lpRect)
1068 {
1069 ATLASSERT(m_hRgn == NULL);
1070 m_hRgn = ::CreateEllipticRgnIndirect(lpRect);
1071 return m_hRgn;
1072 }
1073
1074 HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode)
1075 {
1076 ATLASSERT(m_hRgn == NULL);
1077 m_hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode);
1078 return m_hRgn;
1079 }
1080
1081 HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode)
1082 {
1083 ATLASSERT(m_hRgn == NULL);
1084 m_hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode);
1085 return m_hRgn;
1086 }
1087
1088 HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3)
1089 {
1090 ATLASSERT(m_hRgn == NULL);
1091 m_hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3);
1092 return m_hRgn;
1093 }
1094
1095 HRGN CreateFromPath(HDC hDC)
1096 {
1097 ATLASSERT(m_hRgn == NULL);
1098 ATLASSERT(hDC != NULL);
1099 m_hRgn = ::PathToRegion(hDC);
1100 return m_hRgn;
1101 }
1102
1103 HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData)
1104 {
1105 ATLASSERT(m_hRgn == NULL);
1106 m_hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData);
1107 return m_hRgn;
1108 }
1109 #endif // !_WIN32_WCE
1110
1111 BOOL DeleteObject()
1112 {
1113 ATLASSERT(m_hRgn != NULL);
1114 BOOL bRet = ::DeleteObject(m_hRgn);
1115 if(bRet)
1116 m_hRgn = NULL;
1117 return bRet;
1118 }
1119
1120 // Operations
1121 void SetRectRgn(int x1, int y1, int x2, int y2)
1122 {
1123 ATLASSERT(m_hRgn != NULL);
1124 ::SetRectRgn(m_hRgn, x1, y1, x2, y2);
1125 }
1126
1127 void SetRectRgn(LPCRECT lpRect)
1128 {
1129 ATLASSERT(m_hRgn != NULL);
1130 ::SetRectRgn(m_hRgn, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
1131 }
1132
1133 int CombineRgn(HRGN hRgnSrc1, HRGN hRgnSrc2, int nCombineMode)
1134 {
1135 ATLASSERT(m_hRgn != NULL);
1136 return ::CombineRgn(m_hRgn, hRgnSrc1, hRgnSrc2, nCombineMode);
1137 }
1138
1139 int CombineRgn(HRGN hRgnSrc, int nCombineMode)
1140 {
1141 ATLASSERT(m_hRgn != NULL);
1142 return ::CombineRgn(m_hRgn, m_hRgn, hRgnSrc, nCombineMode);
1143 }
1144
1145 int CopyRgn(HRGN hRgnSrc)
1146 {
1147 ATLASSERT(m_hRgn != NULL);
1148 return ::CombineRgn(m_hRgn, hRgnSrc, NULL, RGN_COPY);
1149 }
1150
1151 BOOL EqualRgn(HRGN hRgn) const
1152 {
1153 ATLASSERT(m_hRgn != NULL);
1154 return ::EqualRgn(m_hRgn, hRgn);
1155 }
1156
1157 int OffsetRgn(int x, int y)
1158 {
1159 ATLASSERT(m_hRgn != NULL);
1160 return ::OffsetRgn(m_hRgn, x, y);
1161 }
1162
1163 int OffsetRgn(POINT point)
1164 {
1165 ATLASSERT(m_hRgn != NULL);
1166 return ::OffsetRgn(m_hRgn, point.x, point.y);
1167 }
1168
1169 int GetRgnBox(LPRECT lpRect) const
1170 {
1171 ATLASSERT(m_hRgn != NULL);
1172 return ::GetRgnBox(m_hRgn, lpRect);
1173 }
1174
1175 BOOL PtInRegion(int x, int y) const
1176 {
1177 ATLASSERT(m_hRgn != NULL);
1178 return ::PtInRegion(m_hRgn, x, y);
1179 }
1180
1181 BOOL PtInRegion(POINT point) const
1182 {
1183 ATLASSERT(m_hRgn != NULL);
1184 return ::PtInRegion(m_hRgn, point.x, point.y);
1185 }
1186
1187 BOOL RectInRegion(LPCRECT lpRect) const
1188 {
1189 ATLASSERT(m_hRgn != NULL);
1190 return ::RectInRegion(m_hRgn, lpRect);
1191 }
1192
1193 int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const
1194 {
1195 ATLASSERT(m_hRgn != NULL);
1196 return (int)::GetRegionData(m_hRgn, nDataSize, lpRgnData);
1197 }
1198 };
1199
1200 typedef CRgnT<false> CRgnHandle;
1201 typedef CRgnT<true> CRgn;
1202
1203
1204 ///////////////////////////////////////////////////////////////////////////////
1205 // CDC - The device context class
1206
1207 template <bool t_bManaged>
1208 class CDCT
1209 {
1210 public:
1211 // Data members
1212 HDC m_hDC;
1213
1214 // Constructor/destructor/operators
1215 CDCT(HDC hDC = NULL) : m_hDC(hDC)
1216 {
1217 }
1218
1219 ~CDCT()
1220 {
1221 if(t_bManaged && m_hDC != NULL)
1222 ::DeleteDC(Detach());
1223 }
1224
1225 CDCT<t_bManaged>& operator =(HDC hDC)
1226 {
1227 Attach(hDC);
1228 return *this;
1229 }
1230
1231 void Attach(HDC hDC)
1232 {
1233 if(t_bManaged && m_hDC != NULL && m_hDC != hDC)
1234 ::DeleteDC(m_hDC);
1235 m_hDC = hDC;
1236 }
1237
1238 HDC Detach()
1239 {
1240 HDC hDC = m_hDC;
1241 m_hDC = NULL;
1242 return hDC;
1243 }
1244
1245 operator HDC() const { return m_hDC; }
1246
1247 bool IsNull() const { return (m_hDC == NULL); }
1248
1249 // Operations
1250 #ifndef _WIN32_WCE
1251 HWND WindowFromDC() const
1252 {
1253 ATLASSERT(m_hDC != NULL);
1254 return ::WindowFromDC(m_hDC);
1255 }
1256 #endif // !_WIN32_WCE
1257
1258 CPenHandle GetCurrentPen() const
1259 {
1260 ATLASSERT(m_hDC != NULL);
1261 return CPenHandle((HPEN)::GetCurrentObject(m_hDC, OBJ_PEN));
1262 }
1263
1264 CBrushHandle GetCurrentBrush() const
1265 {
1266 ATLASSERT(m_hDC != NULL);
1267 return CBrushHandle((HBRUSH)::GetCurrentObject(m_hDC, OBJ_BRUSH));
1268 }
1269
1270 CPaletteHandle GetCurrentPalette() const
1271 {
1272 ATLASSERT(m_hDC != NULL);
1273 return CPaletteHandle((HPALETTE)::GetCurrentObject(m_hDC, OBJ_PAL));
1274 }
1275
1276 CFontHandle GetCurrentFont() const
1277 {
1278 ATLASSERT(m_hDC != NULL);
1279 return CFontHandle((HFONT)::GetCurrentObject(m_hDC, OBJ_FONT));
1280 }
1281
1282 CBitmapHandle GetCurrentBitmap() const
1283 {
1284 ATLASSERT(m_hDC != NULL);
1285 return CBitmapHandle((HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP));
1286 }
1287
1288 HDC CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const DEVMODE* lpInitData)
1289 {
1290 ATLASSERT(m_hDC == NULL);
1291 m_hDC = ::CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData);
1292 return m_hDC;
1293 }
1294
1295 HDC CreateCompatibleDC(HDC hDC = NULL)
1296 {
1297 ATLASSERT(m_hDC == NULL);
1298 m_hDC = ::CreateCompatibleDC(hDC);
1299 return m_hDC;
1300 }
1301
1302 BOOL DeleteDC()
1303 {
1304 if(m_hDC == NULL)
1305 return FALSE;
1306 BOOL bRet = ::DeleteDC(m_hDC);
1307 if(bRet)
1308 m_hDC = NULL;
1309 return bRet;
1310 }
1311
1312 // Device-Context Functions
1313 int SaveDC()
1314 {
1315 ATLASSERT(m_hDC != NULL);
1316 return ::SaveDC(m_hDC);
1317 }
1318
1319 BOOL RestoreDC(int nSavedDC)
1320 {
1321 ATLASSERT(m_hDC != NULL);
1322 return ::RestoreDC(m_hDC, nSavedDC);
1323 }
1324
1325 int GetDeviceCaps(int nIndex) const
1326 {
1327 ATLASSERT(m_hDC != NULL);
1328 return ::GetDeviceCaps(m_hDC, nIndex);
1329 }
1330
1331 #ifndef _WIN32_WCE
1332 UINT SetBoundsRect(LPCRECT lpRectBounds, UINT flags)
1333 {
1334 ATLASSERT(m_hDC != NULL);
1335 return ::SetBoundsRect(m_hDC, lpRectBounds, flags);
1336 }
1337
1338 UINT GetBoundsRect(LPRECT lpRectBounds, UINT flags) const
1339 {
1340 ATLASSERT(m_hDC != NULL);
1341 return ::GetBoundsRect(m_hDC, lpRectBounds, flags);
1342 }
1343
1344 BOOL ResetDC(const DEVMODE* lpDevMode)
1345 {
1346 ATLASSERT(m_hDC != NULL);
1347 return ::ResetDC(m_hDC, lpDevMode) != NULL;
1348 }
1349
1350 // Drawing-Tool Functions
1351 BOOL GetBrushOrg(LPPOINT lpPoint) const
1352 {
1353 ATLASSERT(m_hDC != NULL);
1354 return ::GetBrushOrgEx(m_hDC, lpPoint);
1355 }
1356 #endif // !_WIN32_WCE
1357
1358 BOOL SetBrushOrg(int x, int y, LPPOINT lpPoint = NULL)
1359 {
1360 ATLASSERT(m_hDC != NULL);
1361 return ::SetBrushOrgEx(m_hDC, x, y, lpPoint);
1362 }
1363
1364 BOOL SetBrushOrg(POINT point, LPPOINT lpPointRet = NULL)
1365 {
1366 ATLASSERT(m_hDC != NULL);
1367 return ::SetBrushOrgEx(m_hDC, point.x, point.y, lpPointRet);
1368 }
1369
1370 #ifndef _WIN32_WCE
1371 int EnumObjects(int nObjectType, int (CALLBACK* lpfn)(LPVOID, LPARAM), LPARAM lpData)
1372 {
1373 ATLASSERT(m_hDC != NULL);
1374 #ifdef STRICT
1375 return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, lpData);
1376 #else
1377 return ::EnumObjects(m_hDC, nObjectType, (GOBJENUMPROC)lpfn, (LPVOID)lpData);
1378 #endif
1379 }
1380 #endif // !_WIN32_WCE
1381
1382 // Type-safe selection helpers
1383 HPEN SelectPen(HPEN hPen)
1384 {
1385 ATLASSERT(m_hDC != NULL);
1386 #ifndef _WIN32_WCE
1387 ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN || ::GetObjectType(hPen) == OBJ_EXTPEN);
1388 #else // CE specific
1389 ATLASSERT(hPen == NULL || ::GetObjectType(hPen) == OBJ_PEN);
1390 #endif // _WIN32_WCE
1391 return (HPEN)::SelectObject(m_hDC, hPen);
1392 }
1393
1394 HBRUSH SelectBrush(HBRUSH hBrush)
1395 {
1396 ATLASSERT(m_hDC != NULL);
1397 ATLASSERT(hBrush == NULL || ::GetObjectType(hBrush) == OBJ_BRUSH);
1398 return (HBRUSH)::SelectObject(m_hDC, hBrush);
1399 }
1400
1401 HFONT SelectFont(HFONT hFont)
1402 {
1403 ATLASSERT(m_hDC != NULL);
1404 ATLASSERT(hFont == NULL || ::GetObjectType(hFont) == OBJ_FONT);
1405 return (HFONT)::SelectObject(m_hDC, hFont);
1406 }
1407
1408 HBITMAP SelectBitmap(HBITMAP hBitmap)
1409 {
1410 ATLASSERT(m_hDC != NULL);
1411 ATLASSERT(hBitmap == NULL || ::GetObjectType(hBitmap) == OBJ_BITMAP);
1412 return (HBITMAP)::SelectObject(m_hDC, hBitmap);
1413 }
1414
1415 int SelectRgn(HRGN hRgn) // special return for regions
1416 {
1417 ATLASSERT(m_hDC != NULL);
1418 ATLASSERT(hRgn == NULL || ::GetObjectType(hRgn) == OBJ_REGION);
1419 return PtrToInt(::SelectObject(m_hDC, hRgn));
1420 }
1421
1422 // Type-safe selection helpers for stock objects
1423 HPEN SelectStockPen(int nPen)
1424 {
1425 ATLASSERT(m_hDC != NULL);
1426 #if (_WIN32_WINNT >= 0x0500)
1427 ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN);
1428 #else
1429 ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN);
1430 #endif // !(_WIN32_WINNT >= 0x0500)
1431 return SelectPen((HPEN)::GetStockObject(nPen));
1432 }
1433
1434 HBRUSH SelectStockBrush(int nBrush)
1435 {
1436 #if (_WIN32_WINNT >= 0x0500)
1437 ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH);
1438 #else
1439 ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH);
1440 #endif // !(_WIN32_WINNT >= 0x0500)
1441 return SelectBrush((HBRUSH)::GetStockObject(nBrush));
1442 }
1443
1444 HFONT SelectStockFont(int nFont)
1445 {
1446 #ifndef _WIN32_WCE
1447 ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT);
1448 #else // CE specific
1449 ATLASSERT(nFont == SYSTEM_FONT);
1450 #endif // _WIN32_WCE
1451 return SelectFont((HFONT)::GetStockObject(nFont));
1452 }
1453
1454 HPALETTE SelectStockPalette(int nPalette, BOOL bForceBackground)
1455 {
1456 ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported
1457 return SelectPalette((HPALETTE)::GetStockObject(nPalette), bForceBackground);
1458 }
1459
1460 // Color and Color Palette Functions
1461 COLORREF GetNearestColor(COLORREF crColor) const
1462 {
1463 ATLASSERT(m_hDC != NULL);
1464 return ::GetNearestColor(m_hDC, crColor);
1465 }
1466
1467 HPALETTE SelectPalette(HPALETTE hPalette, BOOL bForceBackground)
1468 {
1469 ATLASSERT(m_hDC != NULL);
1470
1471 return ::SelectPalette(m_hDC, hPalette, bForceBackground);
1472 }
1473
1474 UINT RealizePalette()
1475 {
1476 ATLASSERT(m_hDC != NULL);
1477 return ::RealizePalette(m_hDC);
1478 }
1479
1480 #ifndef _WIN32_WCE
1481 void UpdateColors()
1482 {
1483 ATLASSERT(m_hDC != NULL);
1484 ::UpdateColors(m_hDC);
1485 }
1486 #endif // !_WIN32_WCE
1487
1488 // Drawing-Attribute Functions
1489 COLORREF GetBkColor() const
1490 {
1491 ATLASSERT(m_hDC != NULL);
1492 return ::GetBkColor(m_hDC);
1493 }
1494
1495 int GetBkMode() const
1496 {
1497 ATLASSERT(m_hDC != NULL);
1498 return ::GetBkMode(m_hDC);
1499 }
1500
1501 #ifndef _WIN32_WCE
1502 int GetPolyFillMode() const
1503 {
1504 ATLASSERT(m_hDC != NULL);
1505 return ::GetPolyFillMode(m_hDC);
1506 }
1507
1508 int GetROP2() const
1509 {
1510 ATLASSERT(m_hDC != NULL);
1511 return ::GetROP2(m_hDC);
1512 }
1513
1514 int GetStretchBltMode() const
1515 {
1516 ATLASSERT(m_hDC != NULL);
1517 return ::GetStretchBltMode(m_hDC);
1518 }
1519 #endif // !_WIN32_WCE
1520
1521 COLORREF GetTextColor() const
1522 {
1523 ATLASSERT(m_hDC != NULL);
1524 return ::GetTextColor(m_hDC);
1525 }
1526
1527 COLORREF SetBkColor(COLORREF crColor)
1528 {
1529 ATLASSERT(m_hDC != NULL);
1530 return ::SetBkColor(m_hDC, crColor);
1531 }
1532
1533 int SetBkMode(int nBkMode)
1534 {
1535 ATLASSERT(m_hDC != NULL);
1536 return ::SetBkMode(m_hDC, nBkMode);
1537 }
1538
1539 #ifndef _WIN32_WCE
1540 int SetPolyFillMode(int nPolyFillMode)
1541 {
1542 ATLASSERT(m_hDC != NULL);
1543 return ::SetPolyFillMode(m_hDC, nPolyFillMode);
1544 }
1545 #endif // !_WIN32_WCE
1546
1547 int SetROP2(int nDrawMode)
1548 {
1549 ATLASSERT(m_hDC != NULL);
1550 return ::SetROP2(m_hDC, nDrawMode);
1551 }
1552
1553 #ifndef _WIN32_WCE
1554 int SetStretchBltMode(int nStretchMode)
1555 {
1556 ATLASSERT(m_hDC != NULL);
1557 return ::SetStretchBltMode(m_hDC, nStretchMode);
1558 }
1559 #endif // !_WIN32_WCE
1560
1561 COLORREF SetTextColor(COLORREF crColor)
1562 {
1563 ATLASSERT(m_hDC != NULL);
1564 return ::SetTextColor(m_hDC, crColor);
1565 }
1566
1567 #ifndef _WIN32_WCE
1568 BOOL GetColorAdjustment(LPCOLORADJUSTMENT lpColorAdjust) const
1569 {
1570 ATLASSERT(m_hDC != NULL);
1571 return ::GetColorAdjustment(m_hDC, lpColorAdjust);
1572 }
1573
1574 BOOL SetColorAdjustment(const COLORADJUSTMENT* lpColorAdjust)
1575 {
1576 ATLASSERT(m_hDC != NULL);
1577 return ::SetColorAdjustment(m_hDC, lpColorAdjust);
1578 }
1579
1580 // Mapping Functions
1581 int GetMapMode() const
1582 {
1583 ATLASSERT(m_hDC != NULL);
1584 return ::GetMapMode(m_hDC);
1585 }
1586
1587 BOOL GetViewportOrg(LPPOINT lpPoint) const
1588 {
1589 ATLASSERT(m_hDC != NULL);
1590 return ::GetViewportOrgEx(m_hDC, lpPoint);
1591 }
1592
1593 int SetMapMode(int nMapMode)
1594 {
1595 ATLASSERT(m_hDC != NULL);
1596 return ::SetMapMode(m_hDC, nMapMode);
1597 }
1598 #endif // !_WIN32_WCE
1599
1600 // Viewport Origin
1601 BOOL SetViewportOrg(int x, int y, LPPOINT lpPoint = NULL)
1602 {
1603 ATLASSERT(m_hDC != NULL);
1604 return ::SetViewportOrgEx(m_hDC, x, y, lpPoint);
1605 }
1606
1607 BOOL SetViewportOrg(POINT point, LPPOINT lpPointRet = NULL)
1608 {
1609 ATLASSERT(m_hDC != NULL);
1610 return SetViewportOrg(point.x, point.y, lpPointRet);
1611 }
1612
1613 #ifndef _WIN32_WCE
1614 BOOL OffsetViewportOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL)
1615 {
1616 ATLASSERT(m_hDC != NULL);
1617 return ::OffsetViewportOrgEx(m_hDC, nWidth, nHeight, lpPoint);
1618 }
1619
1620 // Viewport Extent
1621 BOOL GetViewportExt(LPSIZE lpSize) const
1622 {
1623 ATLASSERT(m_hDC != NULL);
1624 return ::GetViewportExtEx(m_hDC, lpSize);
1625 }
1626
1627 BOOL SetViewportExt(int x, int y, LPSIZE lpSize = NULL)
1628 {
1629 ATLASSERT(m_hDC != NULL);
1630 return ::SetViewportExtEx(m_hDC, x, y, lpSize);
1631 }
1632
1633 BOOL SetViewportExt(SIZE size, LPSIZE lpSizeRet = NULL)
1634 {
1635 ATLASSERT(m_hDC != NULL);
1636 return SetViewportExt(size.cx, size.cy, lpSizeRet);
1637 }
1638
1639 BOOL ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL)
1640 {
1641 ATLASSERT(m_hDC != NULL);
1642 return ::ScaleViewportExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize);
1643 }
1644 #endif // !_WIN32_WCE
1645
1646 // Window Origin
1647 #ifndef _WIN32_WCE
1648 BOOL GetWindowOrg(LPPOINT lpPoint) const
1649 {
1650 ATLASSERT(m_hDC != NULL);
1651 return ::GetWindowOrgEx(m_hDC, lpPoint);
1652 }
1653
1654 BOOL SetWindowOrg(int x, int y, LPPOINT lpPoint = NULL)
1655 {
1656 ATLASSERT(m_hDC != NULL);
1657 return ::SetWindowOrgEx(m_hDC, x, y, lpPoint);
1658 }
1659
1660 BOOL SetWindowOrg(POINT point, LPPOINT lpPointRet = NULL)
1661 {
1662 ATLASSERT(m_hDC != NULL);
1663 return SetWindowOrg(point.x, point.y, lpPointRet);
1664 }
1665
1666 BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint = NULL)
1667 {
1668 ATLASSERT(m_hDC != NULL);
1669 return ::OffsetWindowOrgEx(m_hDC, nWidth, nHeight, lpPoint);
1670 }
1671
1672 // Window extent
1673 BOOL GetWindowExt(LPSIZE lpSize) const
1674 {
1675 ATLASSERT(m_hDC != NULL);
1676 return ::GetWindowExtEx(m_hDC, lpSize);
1677 }
1678
1679 BOOL SetWindowExt(int x, int y, LPSIZE lpSize = NULL)
1680 {
1681 ATLASSERT(m_hDC != NULL);
1682 return ::SetWindowExtEx(m_hDC, x, y, lpSize);
1683 }
1684
1685 BOOL SetWindowExt(SIZE size, LPSIZE lpSizeRet = NULL)
1686 {
1687 ATLASSERT(m_hDC != NULL);
1688 return SetWindowExt(size.cx, size.cy, lpSizeRet);
1689 }
1690
1691 BOOL ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize = NULL)
1692 {
1693 ATLASSERT(m_hDC != NULL);
1694 return ::ScaleWindowExtEx(m_hDC, xNum, xDenom, yNum, yDenom, lpSize);
1695 }
1696
1697 // Coordinate Functions
1698 BOOL DPtoLP(LPPOINT lpPoints, int nCount = 1) const
1699 {
1700 ATLASSERT(m_hDC != NULL);
1701 return ::DPtoLP(m_hDC, lpPoints, nCount);
1702 }
1703
1704 BOOL DPtoLP(LPRECT lpRect) const
1705 {
1706 ATLASSERT(m_hDC != NULL);
1707 return ::DPtoLP(m_hDC, (LPPOINT)lpRect, 2);
1708 }
1709
1710 BOOL DPtoLP(LPSIZE lpSize) const
1711 {
1712 SIZE sizeWinExt = { 0, 0 };
1713 if(!GetWindowExt(&sizeWinExt))
1714 return FALSE;
1715 SIZE sizeVpExt = { 0, 0 };
1716 if(!GetViewportExt(&sizeVpExt))
1717 return FALSE;
1718 lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeWinExt.cx), abs(sizeVpExt.cx));
1719 lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeWinExt.cy), abs(sizeVpExt.cy));
1720 return TRUE;
1721 }
1722
1723 BOOL LPtoDP(LPPOINT lpPoints, int nCount = 1) const
1724 {
1725 ATLASSERT(m_hDC != NULL);
1726 return ::LPtoDP(m_hDC, lpPoints, nCount);
1727 }
1728
1729 BOOL LPtoDP(LPRECT lpRect) const
1730 {
1731 ATLASSERT(m_hDC != NULL);
1732 return ::LPtoDP(m_hDC, (LPPOINT)lpRect, 2);
1733 }
1734
1735 BOOL LPtoDP(LPSIZE lpSize) const
1736 {
1737 SIZE sizeWinExt = { 0, 0 };
1738 if(!GetWindowExt(&sizeWinExt))
1739 return FALSE;
1740 SIZE sizeVpExt = { 0, 0 };
1741 if(!GetViewportExt(&sizeVpExt))
1742 return FALSE;
1743 lpSize->cx = ::MulDiv(lpSize->cx, abs(sizeVpExt.cx), abs(sizeWinExt.cx));
1744 lpSize->cy = ::MulDiv(lpSize->cy, abs(sizeVpExt.cy), abs(sizeWinExt.cy));
1745 return TRUE;
1746 }
1747
1748 // Special Coordinate Functions (useful for dealing with metafiles and OLE)
1749 #define HIMETRIC_INCH 2540 // HIMETRIC units per inch
1750
1751 void DPtoHIMETRIC(LPSIZE lpSize) const
1752 {
1753 ATLASSERT(m_hDC != NULL);
1754 int nMapMode;
1755 if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT)
1756 {
1757 // when using a constrained map mode, map against physical inch
1758 ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC);
1759 DPtoLP(lpSize);
1760 ((CDCHandle*)this)->SetMapMode(nMapMode);
1761 }
1762 else
1763 {
1764 // map against logical inch for non-constrained mapping modes
1765 int cxPerInch = GetDeviceCaps(LOGPIXELSX);
1766 int cyPerInch = GetDeviceCaps(LOGPIXELSY);
1767 ATLASSERT(cxPerInch != 0 && cyPerInch != 0);
1768 lpSize->cx = ::MulDiv(lpSize->cx, HIMETRIC_INCH, cxPerInch);
1769 lpSize->cy = ::MulDiv(lpSize->cy, HIMETRIC_INCH, cyPerInch);
1770 }
1771 }
1772
1773 void HIMETRICtoDP(LPSIZE lpSize) const
1774 {
1775 ATLASSERT(m_hDC != NULL);
1776 int nMapMode;
1777 if((nMapMode = GetMapMode()) < MM_ISOTROPIC && nMapMode != MM_TEXT)
1778 {
1779 // when using a constrained map mode, map against physical inch
1780 ((CDCHandle*)this)->SetMapMode(MM_HIMETRIC);
1781 LPtoDP(lpSize);
1782 ((CDCHandle*)this)->SetMapMode(nMapMode);
1783 }
1784 else
1785 {
1786 // map against logical inch for non-constrained mapping modes
1787 int cxPerInch = GetDeviceCaps(LOGPIXELSX);
1788 int cyPerInch = GetDeviceCaps(LOGPIXELSY);
1789 ATLASSERT(cxPerInch != 0 && cyPerInch != 0);
1790 lpSize->cx = ::MulDiv(lpSize->cx, cxPerInch, HIMETRIC_INCH);
1791 lpSize->cy = ::MulDiv(lpSize->cy, cyPerInch, HIMETRIC_INCH);
1792 }
1793 }
1794
1795 void LPtoHIMETRIC(LPSIZE lpSize) const
1796 {
1797 LPtoDP(lpSize);
1798 DPtoHIMETRIC(lpSize);
1799 }
1800
1801 void HIMETRICtoLP(LPSIZE lpSize) const
1802 {
1803 HIMETRICtoDP(lpSize);
1804 DPtoLP(lpSize);
1805 }
1806 #endif // !_WIN32_WCE
1807
1808 // Region Functions
1809 BOOL FillRgn(HRGN hRgn, HBRUSH hBrush)
1810 {
1811 ATLASSERT(m_hDC != NULL);
1812 return ::FillRgn(m_hDC, hRgn, hBrush);
1813 }
1814
1815 #ifndef _WIN32_WCE
1816 BOOL FrameRgn(HRGN hRgn, HBRUSH hBrush, int nWidth, int nHeight)
1817 {
1818 ATLASSERT(m_hDC != NULL);
1819 return ::FrameRgn(m_hDC, hRgn, hBrush, nWidth, nHeight);
1820 }
1821
1822 BOOL InvertRgn(HRGN hRgn)
1823 {
1824 ATLASSERT(m_hDC != NULL);
1825 return ::InvertRgn(m_hDC, hRgn);
1826 }
1827
1828 BOOL PaintRgn(HRGN hRgn)
1829 {
1830 ATLASSERT(m_hDC != NULL);
1831 return ::PaintRgn(m_hDC, hRgn);
1832 }
1833 #endif // !_WIN32_WCE
1834
1835 // Clipping Functions
1836 int GetClipBox(LPRECT lpRect) const
1837 {
1838 ATLASSERT(m_hDC != NULL);
1839 return ::GetClipBox(m_hDC, lpRect);
1840 }
1841
1842 int GetClipRgn(CRgn& region) const
1843 {
1844 ATLASSERT(m_hDC != NULL);
1845 if(region.IsNull())
1846 region.CreateRectRgn(0, 0, 0, 0);
1847
1848 int nRet = ::GetClipRgn(m_hDC, region);
1849 if(nRet != 1)
1850 region.DeleteObject();
1851
1852 return nRet;
1853 }
1854
1855 #ifndef _WIN32_WCE
1856 BOOL PtVisible(int x, int y) const
1857 {
1858 ATLASSERT(m_hDC != NULL);
1859 return ::PtVisible(m_hDC, x, y);
1860 }
1861
1862 BOOL PtVisible(POINT point) const
1863 {
1864 ATLASSERT(m_hDC != NULL);
1865 return ::PtVisible(m_hDC, point.x, point.y);
1866 }
1867 #endif // !_WIN32_WCE
1868
1869 BOOL RectVisible(LPCRECT lpRect) const
1870 {
1871 ATLASSERT(m_hDC != NULL);
1872 return ::RectVisible(m_hDC, lpRect);
1873 }
1874
1875 int SelectClipRgn(HRGN hRgn)
1876 {
1877 ATLASSERT(m_hDC != NULL);
1878 return ::SelectClipRgn(m_hDC, (HRGN)hRgn);
1879 }
1880
1881 int ExcludeClipRect(int x1, int y1, int x2, int y2)
1882 {
1883 ATLASSERT(m_hDC != NULL);
1884 return ::ExcludeClipRect(m_hDC, x1, y1, x2, y2);
1885 }
1886
1887 int ExcludeClipRect(LPCRECT lpRect)
1888 {
1889 ATLASSERT(m_hDC != NULL);
1890 return ::ExcludeClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
1891 }
1892
1893 #ifndef _WIN32_WCE
1894 int ExcludeUpdateRgn(HWND hWnd)
1895 {
1896 ATLASSERT(m_hDC != NULL);
1897 return ::ExcludeUpdateRgn(m_hDC, hWnd);
1898 }
1899 #endif // !_WIN32_WCE
1900
1901 int IntersectClipRect(int x1, int y1, int x2, int y2)
1902 {
1903 ATLASSERT(m_hDC != NULL);
1904 return ::IntersectClipRect(m_hDC, x1, y1, x2, y2);
1905 }
1906
1907 int IntersectClipRect(LPCRECT lpRect)
1908 {
1909 ATLASSERT(m_hDC != NULL);
1910 return ::IntersectClipRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
1911 }
1912
1913 #ifndef _WIN32_WCE
1914 int OffsetClipRgn(int x, int y)
1915 {
1916 ATLASSERT(m_hDC != NULL);
1917 return ::OffsetClipRgn(m_hDC, x, y);
1918 }
1919
1920 int OffsetClipRgn(SIZE size)
1921 {
1922 ATLASSERT(m_hDC != NULL);
1923 return ::OffsetClipRgn(m_hDC, size.cx, size.cy);
1924 }
1925
1926 int SelectClipRgn(HRGN hRgn, int nMode)
1927 {
1928 ATLASSERT(m_hDC != NULL);
1929 return ::ExtSelectClipRgn(m_hDC, hRgn, nMode);
1930 }
1931 #endif // !_WIN32_WCE
1932
1933 // Line-Output Functions
1934 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
1935 BOOL GetCurrentPosition(LPPOINT lpPoint) const
1936 {
1937 ATLASSERT(m_hDC != NULL);
1938 return ::GetCurrentPositionEx(m_hDC, lpPoint);
1939 }
1940
1941 BOOL MoveTo(int x, int y, LPPOINT lpPoint = NULL)
1942 {
1943 ATLASSERT(m_hDC != NULL);
1944 return ::MoveToEx(m_hDC, x, y, lpPoint);
1945 }
1946
1947 BOOL MoveTo(POINT point, LPPOINT lpPointRet = NULL)
1948 {
1949 ATLASSERT(m_hDC != NULL);
1950 return MoveTo(point.x, point.y, lpPointRet);
1951 }
1952
1953 BOOL LineTo(int x, int y)
1954 {
1955 ATLASSERT(m_hDC != NULL);
1956 return ::LineTo(m_hDC, x, y);
1957 }
1958
1959 BOOL LineTo(POINT point)
1960 {
1961 ATLASSERT(m_hDC != NULL);
1962 return LineTo(point.x, point.y);
1963 }
1964 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
1965
1966 #ifndef _WIN32_WCE
1967 BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
1968 {
1969 ATLASSERT(m_hDC != NULL);
1970 return ::Arc(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
1971 }
1972
1973 BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
1974 {
1975 ATLASSERT(m_hDC != NULL);
1976 return ::Arc(m_hDC, lpRect->left, lpRect->top,
1977 lpRect->right, lpRect->bottom, ptStart.x, ptStart.y,
1978 ptEnd.x, ptEnd.y);
1979 }
1980 #endif // !_WIN32_WCE
1981
1982 BOOL Polyline(const POINT* lpPoints, int nCount)
1983 {
1984 ATLASSERT(m_hDC != NULL);
1985 return ::Polyline(m_hDC, lpPoints, nCount);
1986 }
1987
1988 #ifndef _WIN32_WCE
1989 BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle)
1990 {
1991 ATLASSERT(m_hDC != NULL);
1992 return ::AngleArc(m_hDC, x, y, nRadius, fStartAngle, fSweepAngle);
1993 }
1994
1995 BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
1996 {
1997 ATLASSERT(m_hDC != NULL);
1998 return ::ArcTo(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
1999 }
2000
2001 BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
2002 {
2003 ATLASSERT(m_hDC != NULL);
2004 return ArcTo(lpRect->left, lpRect->top, lpRect->right,
2005 lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
2006 }
2007
2008 int GetArcDirection() const
2009 {
2010 ATLASSERT(m_hDC != NULL);
2011 return ::GetArcDirection(m_hDC);
2012 }
2013
2014 int SetArcDirection(int nArcDirection)
2015 {
2016 ATLASSERT(m_hDC != NULL);
2017 return ::SetArcDirection(m_hDC, nArcDirection);
2018 }
2019
2020 BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount)
2021 {
2022 ATLASSERT(m_hDC != NULL);
2023 return ::PolyDraw(m_hDC, lpPoints, lpTypes, nCount);
2024 }
2025
2026 BOOL PolylineTo(const POINT* lpPoints, int nCount)
2027 {
2028 ATLASSERT(m_hDC != NULL);
2029 return ::PolylineTo(m_hDC, lpPoints, nCount);
2030 }
2031
2032 BOOL PolyPolyline(const POINT* lpPoints,
2033 const DWORD* lpPolyPoints, int nCount)
2034 {
2035 ATLASSERT(m_hDC != NULL);
2036 return ::PolyPolyline(m_hDC, lpPoints, lpPolyPoints, nCount);
2037 }
2038
2039 BOOL PolyBezier(const POINT* lpPoints, int nCount)
2040 {
2041 ATLASSERT(m_hDC != NULL);
2042 return ::PolyBezier(m_hDC, lpPoints, nCount);
2043 }
2044
2045 BOOL PolyBezierTo(const POINT* lpPoints, int nCount)
2046 {
2047 ATLASSERT(m_hDC != NULL);
2048 return ::PolyBezierTo(m_hDC, lpPoints, nCount);
2049 }
2050 #endif // !_WIN32_WCE
2051
2052 // Simple Drawing Functions
2053 BOOL FillRect(LPCRECT lpRect, HBRUSH hBrush)
2054 {
2055 ATLASSERT(m_hDC != NULL);
2056 return ::FillRect(m_hDC, lpRect, hBrush);
2057 }
2058
2059 BOOL FillRect(LPCRECT lpRect, int nColorIndex)
2060 {
2061 ATLASSERT(m_hDC != NULL);
2062 #ifndef _WIN32_WCE
2063 return ::FillRect(m_hDC, lpRect, (HBRUSH)LongToPtr(nColorIndex + 1));
2064 #else // CE specific
2065 return ::FillRect(m_hDC, lpRect, ::GetSysColorBrush(nColorIndex));
2066 #endif // _WIN32_WCE
2067 }
2068
2069 #ifndef _WIN32_WCE
2070 BOOL FrameRect(LPCRECT lpRect, HBRUSH hBrush)
2071 {
2072 ATLASSERT(m_hDC != NULL);
2073 return ::FrameRect(m_hDC, lpRect, hBrush);
2074 }
2075 #endif // !_WIN32_WCE
2076
2077 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 420)
2078 BOOL InvertRect(LPCRECT lpRect)
2079 {
2080 ATLASSERT(m_hDC != NULL);
2081 return ::InvertRect(m_hDC, lpRect);
2082 }
2083 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420)
2084
2085 BOOL DrawIcon(int x, int y, HICON hIcon)
2086 {
2087 ATLASSERT(m_hDC != NULL);
2088 #ifndef _WIN32_WCE
2089 return ::DrawIcon(m_hDC, x, y, hIcon);
2090 #else // CE specific
2091 return ::DrawIconEx(m_hDC, x, y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
2092 #endif // _WIN32_WCE
2093 }
2094
2095 BOOL DrawIcon(POINT point, HICON hIcon)
2096 {
2097 ATLASSERT(m_hDC != NULL);
2098 #ifndef _WIN32_WCE
2099 return ::DrawIcon(m_hDC, point.x, point.y, hIcon);
2100 #else // CE specific
2101 return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
2102 #endif // _WIN32_WCE
2103 }
2104
2105 BOOL DrawIconEx(int x, int y, HICON hIcon, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
2106 {
2107 ATLASSERT(m_hDC != NULL);
2108 return ::DrawIconEx(m_hDC, x, y, hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
2109 }
2110
2111 BOOL DrawIconEx(POINT point, HICON hIcon, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
2112 {
2113 ATLASSERT(m_hDC != NULL);
2114 return ::DrawIconEx(m_hDC, point.x, point.y, hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
2115 }
2116
2117 #ifndef _WIN32_WCE
2118 BOOL DrawState(POINT pt, SIZE size, HBITMAP hBitmap, UINT nFlags, HBRUSH hBrush = NULL)
2119 {
2120 ATLASSERT(m_hDC != NULL);
2121 return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hBitmap, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_BITMAP);
2122 }
2123
2124 BOOL DrawState(POINT pt, SIZE size, HICON hIcon, UINT nFlags, HBRUSH hBrush = NULL)
2125 {
2126 ATLASSERT(m_hDC != NULL);
2127 return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)hIcon, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_ICON);
2128 }
2129
2130 BOOL DrawState(POINT pt, SIZE size, LPCTSTR lpszText, UINT nFlags, BOOL bPrefixText = TRUE, int nTextLen = 0, HBRUSH hBrush = NULL)
2131 {
2132 ATLASSERT(m_hDC != NULL);
2133 return ::DrawState(m_hDC, hBrush, NULL, (LPARAM)lpszText, (WPARAM)nTextLen, pt.x, pt.y, size.cx, size.cy, nFlags | (bPrefixText ? DST_PREFIXTEXT : DST_TEXT));
2134 }
2135
2136 BOOL DrawState(POINT pt, SIZE size, DRAWSTATEPROC lpDrawProc, LPARAM lData, UINT nFlags, HBRUSH hBrush = NULL)
2137 {
2138 ATLASSERT(m_hDC != NULL);
2139 return ::DrawState(m_hDC, hBrush, lpDrawProc, lData, 0, pt.x, pt.y, size.cx, size.cy, nFlags | DST_COMPLEX);
2140 }
2141 #endif // !_WIN32_WCE
2142
2143 // Ellipse and Polygon Functions
2144 #ifndef _WIN32_WCE
2145 BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
2146 {
2147 ATLASSERT(m_hDC != NULL);
2148 return ::Chord(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
2149 }
2150
2151 BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
2152 {
2153 ATLASSERT(m_hDC != NULL);
2154 return ::Chord(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
2155 }
2156 #endif // !_WIN32_WCE
2157
2158 void DrawFocusRect(LPCRECT lpRect)
2159 {
2160 ATLASSERT(m_hDC != NULL);
2161 ::DrawFocusRect(m_hDC, lpRect);
2162 }
2163
2164 BOOL Ellipse(int x1, int y1, int x2, int y2)
2165 {
2166 ATLASSERT(m_hDC != NULL);
2167 return ::Ellipse(m_hDC, x1, y1, x2, y2);
2168 }
2169
2170 BOOL Ellipse(LPCRECT lpRect)
2171 {
2172 ATLASSERT(m_hDC != NULL);
2173 return ::Ellipse(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
2174 }
2175
2176 #ifndef _WIN32_WCE
2177 BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
2178 {
2179 ATLASSERT(m_hDC != NULL);
2180 return ::Pie(m_hDC, x1, y1, x2, y2, x3, y3, x4, y4);
2181 }
2182
2183 BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd)
2184 {
2185 ATLASSERT(m_hDC != NULL);
2186 return ::Pie(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
2187 }
2188 #endif // !_WIN32_WCE
2189
2190 BOOL Polygon(const POINT* lpPoints, int nCount)
2191 {
2192 ATLASSERT(m_hDC != NULL);
2193 return ::Polygon(m_hDC, lpPoints, nCount);
2194 }
2195
2196 #ifndef _WIN32_WCE
2197 BOOL PolyPolygon(const POINT* lpPoints, const INT* lpPolyCounts, int nCount)
2198 {
2199 ATLASSERT(m_hDC != NULL);
2200 return ::PolyPolygon(m_hDC, lpPoints, lpPolyCounts, nCount);
2201 }
2202 #endif // !_WIN32_WCE
2203
2204 BOOL Rectangle(int x1, int y1, int x2, int y2)
2205 {
2206 ATLASSERT(m_hDC != NULL);
2207 return ::Rectangle(m_hDC, x1, y1, x2, y2);
2208 }
2209
2210 BOOL Rectangle(LPCRECT lpRect)
2211 {
2212 ATLASSERT(m_hDC != NULL);
2213 return ::Rectangle(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
2214 }
2215
2216 BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3)
2217 {
2218 ATLASSERT(m_hDC != NULL);
2219 return ::RoundRect(m_hDC, x1, y1, x2, y2, x3, y3);
2220 }
2221
2222 BOOL RoundRect(LPCRECT lpRect, POINT point)
2223 {
2224 ATLASSERT(m_hDC != NULL);
2225 return ::RoundRect(m_hDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, point.x, point.y);
2226 }
2227
2228 // Bitmap Functions
2229 BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop)
2230 {
2231 ATLASSERT(m_hDC != NULL);
2232 return ::PatBlt(m_hDC, x, y, nWidth, nHeight, dwRop);
2233 }
2234
2235 BOOL BitBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC,
2236 int xSrc, int ySrc, DWORD dwRop)
2237 {
2238 ATLASSERT(m_hDC != NULL);
2239 return ::BitBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, dwRop);
2240 }
2241
2242 BOOL StretchBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop)
2243 {
2244 ATLASSERT(m_hDC != NULL);
2245 return ::StretchBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop);
2246 }
2247
2248 COLORREF GetPixel(int x, int y) const
2249 {
2250 ATLASSERT(m_hDC != NULL);
2251 return ::GetPixel(m_hDC, x, y);
2252 }
2253
2254 COLORREF GetPixel(POINT point) const
2255 {
2256 ATLASSERT(m_hDC != NULL);
2257 return ::GetPixel(m_hDC, point.x, point.y);
2258 }
2259
2260 COLORREF SetPixel(int x, int y, COLORREF crColor)
2261 {
2262 ATLASSERT(m_hDC != NULL);
2263 return ::SetPixel(m_hDC, x, y, crColor);
2264 }
2265
2266 COLORREF SetPixel(POINT point, COLORREF crColor)
2267 {
2268 ATLASSERT(m_hDC != NULL);
2269 return ::SetPixel(m_hDC, point.x, point.y, crColor);
2270 }
2271
2272 #ifndef _WIN32_WCE
2273 BOOL FloodFill(int x, int y, COLORREF crColor)
2274 {
2275 ATLASSERT(m_hDC != NULL);
2276 return ::FloodFill(m_hDC, x, y, crColor);
2277 }
2278
2279 BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType)
2280 {
2281 ATLASSERT(m_hDC != NULL);
2282 return ::ExtFloodFill(m_hDC, x, y, crColor, nFillType);
2283 }
2284 #endif // !_WIN32_WCE
2285
2286 BOOL MaskBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, HBITMAP hMaskBitmap, int xMask, int yMask, DWORD dwRop)
2287 {
2288 ATLASSERT(m_hDC != NULL);
2289 return ::MaskBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, hMaskBitmap, xMask, yMask, dwRop);
2290 }
2291
2292 #ifndef _WIN32_WCE
2293 BOOL PlgBlt(LPPOINT lpPoint, HDC hSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, HBITMAP hMaskBitmap, int xMask, int yMask)
2294 {
2295 ATLASSERT(m_hDC != NULL);
2296 return ::PlgBlt(m_hDC, lpPoint, hSrcDC, xSrc, ySrc, nWidth, nHeight, hMaskBitmap, xMask, yMask);
2297 }
2298
2299 BOOL SetPixelV(int x, int y, COLORREF crColor)
2300 {
2301 ATLASSERT(m_hDC != NULL);
2302 return ::SetPixelV(m_hDC, x, y, crColor);
2303 }
2304
2305 BOOL SetPixelV(POINT point, COLORREF crColor)
2306 {
2307 ATLASSERT(m_hDC != NULL);
2308 return ::SetPixelV(m_hDC, point.x, point.y, crColor);
2309 }
2310 #endif // !_WIN32_WCE
2311
2312 #if !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE)
2313 #ifndef _WIN32_WCE
2314 BOOL TransparentBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent)
2315 {
2316 ATLASSERT(m_hDC != NULL);
2317 return ::TransparentBlt(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent);
2318 }
2319 #else // CE specific
2320 BOOL TransparentImage(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, UINT crTransparent)
2321 {
2322 ATLASSERT(m_hDC != NULL);
2323 return ::TransparentImage(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, crTransparent);
2324 }
2325 #endif // _WIN32_WCE
2326
2327 #if (!defined(_WIN32_WCE) || (_WIN32_WCE >= 420))
2328 BOOL GradientFill(const PTRIVERTEX pVertices, DWORD nVertices, void* pMeshElements, DWORD nMeshElements, DWORD dwMode)
2329 {
2330 ATLASSERT(m_hDC != NULL);
2331 return ::GradientFill(m_hDC, pVertices, nVertices, pMeshElements, nMeshElements, dwMode);
2332 }
2333
2334 BOOL GradientFillRect(RECT& rect, COLORREF clr1, COLORREF clr2, bool bHorizontal)
2335 {
2336 ATLASSERT(m_hDC != NULL);
2337
2338 TRIVERTEX arrTvx[2] = { { 0 }, { 0 } };
2339
2340 arrTvx[0].x = rect.left;
2341 arrTvx[0].y = rect.top;
2342 arrTvx[0].Red = MAKEWORD(0, GetRValue(clr1));
2343 arrTvx[0].Green = MAKEWORD(0, GetGValue(clr1));
2344 arrTvx[0].Blue = MAKEWORD(0, GetBValue(clr1));
2345 arrTvx[0].Alpha = 0;
2346
2347 arrTvx[1].x = rect.right;
2348 arrTvx[1].y = rect.bottom;
2349 arrTvx[1].Red = MAKEWORD(0, GetRValue(clr2));
2350 arrTvx[1].Green = MAKEWORD(0, GetGValue(clr2));
2351 arrTvx[1].Blue = MAKEWORD(0, GetBValue(clr2));
2352 arrTvx[1].Alpha = 0;
2353
2354 GRADIENT_RECT gr = { 0, 1 };
2355
2356 return ::GradientFill(m_hDC, arrTvx, 2, &gr, 1, bHorizontal ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V);
2357 }
2358 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420)
2359
2360 #if !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500)
2361 BOOL AlphaBlend(int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, BLENDFUNCTION bf)
2362 {
2363 ATLASSERT(m_hDC != NULL);
2364 return ::AlphaBlend(m_hDC, x, y, nWidth, nHeight, hSrcDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf);
2365 }
2366 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE > 0x500)
2367 #endif // !defined(_ATL_NO_MSIMG) || defined(_WIN32_WCE)
2368
2369 // Extra bitmap functions
2370 // Helper function for painting a disabled toolbar or menu bitmap
2371 // This function can take either an HBITMAP (for SS) or a DC with
2372 // the bitmap already painted (for cmdbar)
2373 BOOL DitherBlt(int x, int y, int nWidth, int nHeight, HDC hSrcDC, HBITMAP hBitmap, int xSrc, int ySrc,
2374 HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE),
2375 HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT),
2376 HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW))
2377 {
2378 ATLASSERT(m_hDC != NULL || hBitmap != NULL);
2379 ATLASSERT(nWidth > 0 && nHeight > 0);
2380
2381 // Create a generic DC for all BitBlts
2382 CDCHandle dc = (hSrcDC != NULL) ? hSrcDC : ::CreateCompatibleDC(m_hDC);
2383 ATLASSERT(dc.m_hDC != NULL);
2384 if(dc.m_hDC == NULL)
2385 return FALSE;
2386
2387 // Create a DC for the monochrome DIB section
2388 CDC dcBW = ::CreateCompatibleDC(m_hDC);
2389 ATLASSERT(dcBW.m_hDC != NULL);
2390 if(dcBW.m_hDC == NULL)
2391 {
2392 if(hSrcDC == NULL)
2393 dc.DeleteDC();
2394 return FALSE;
2395 }
2396
2397 // Create the monochrome DIB section with a black and white palette
2398 struct RGBBWBITMAPINFO
2399 {
2400 BITMAPINFOHEADER bmiHeader;
2401 RGBQUAD bmiColors[2];
2402 };
2403
2404 RGBBWBITMAPINFO rgbBWBitmapInfo =
2405 {
2406 { sizeof(BITMAPINFOHEADER), nWidth, nHeight, 1, 1, BI_RGB, 0, 0, 0, 0, 0 },
2407 { { 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 } }
2408 };
2409
2410 VOID* pbitsBW;
2411 CBitmap bmpBW = ::CreateDIBSection(dcBW, (LPBITMAPINFO)&rgbBWBitmapInfo, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
2412 ATLASSERT(bmpBW.m_hBitmap != NULL);
2413 if(bmpBW.m_hBitmap == NULL)
2414 {
2415 if(hSrcDC == NULL)
2416 dc.DeleteDC();
2417 return FALSE;
2418 }
2419
2420 // Attach the monochrome DIB section and the bitmap to the DCs
2421 HBITMAP hbmOldBW = dcBW.SelectBitmap(bmpBW);
2422 HBITMAP hbmOldDC = NULL;
2423 if(hBitmap != NULL)
2424 hbmOldDC = dc.SelectBitmap(hBitmap);
2425
2426 // Block: Dark gray removal: we want (128, 128, 128) pixels to become black and not white
2427 {
2428 CDC dcTemp1 = ::CreateCompatibleDC(m_hDC);
2429 CDC dcTemp2 = ::CreateCompatibleDC(m_hDC);
2430 CBitmap bmpTemp1;
2431 bmpTemp1.CreateCompatibleBitmap(dc, nWidth, nHeight);
2432 CBitmap bmpTemp2;
2433 bmpTemp2.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
2434 HBITMAP hOldBmp1 = dcTemp1.SelectBitmap(bmpTemp1);
2435 HBITMAP hOldBmp2 = dcTemp2.SelectBitmap(bmpTemp2);
2436 // Let's copy our image, it will be altered
2437 dcTemp1.BitBlt(0, 0, nWidth, nHeight, dc, xSrc, ySrc, SRCCOPY);
2438
2439 // All dark gray pixels will become white, the others black
2440 dcTemp1.SetBkColor(RGB(128, 128, 128));
2441 dcTemp2.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY);
2442 // Do an XOR to set to black these white pixels
2443 dcTemp1.BitBlt(0, 0, nWidth, nHeight, dcTemp2, 0, 0, SRCINVERT);
2444
2445 // BitBlt the bitmap into the monochrome DIB section
2446 // The DIB section will do a true monochrome conversion
2447 // The magenta background being closer to white will become white
2448 dcBW.BitBlt(0, 0, nWidth, nHeight, dcTemp1, 0, 0, SRCCOPY);
2449
2450 // Cleanup
2451 dcTemp1.SelectBitmap(hOldBmp1);
2452 dcTemp2.SelectBitmap(hOldBmp2);
2453 }
2454
2455 // Paint the destination rectangle using hBrushBackground
2456 if(hBrushBackground != NULL)
2457 {
2458 RECT rc = { x, y, x + nWidth, y + nHeight };
2459 FillRect(&rc, hBrushBackground);
2460 }
2461
2462 // BitBlt the black bits in the monochrome bitmap into hBrush3DEffect color in the destination DC
2463 // The magic ROP comes from the Charles Petzold's book
2464 HBRUSH hOldBrush = SelectBrush(hBrush3DEffect);
2465 BitBlt(x + 1, y + 1, nWidth, nHeight, dcBW, 0, 0, 0xB8074A);
2466
2467 // BitBlt the black bits in the monochrome bitmap into hBrushDisabledImage color in the destination DC
2468 SelectBrush(hBrushDisabledImage);
2469 BitBlt(x, y, nWidth, nHeight, dcBW, 0, 0, 0xB8074A);
2470
2471 SelectBrush(hOldBrush);
2472 dcBW.SelectBitmap(hbmOldBW);
2473 dc.SelectBitmap(hbmOldDC);
2474
2475 if(hSrcDC == NULL)
2476 dc.DeleteDC();
2477
2478 return TRUE;
2479 }
2480
2481 // Text Functions
2482 #ifndef _WIN32_WCE
2483 BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1)
2484 {
2485 ATLASSERT(m_hDC != NULL);
2486 if(nCount == -1)
2487 nCount = lstrlen(lpszString);
2488 return ::TextOut(m_hDC, x, y, lpszString, nCount);
2489 }
2490 #endif // !_WIN32_WCE
2491
2492 BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, UINT nCount = -1, LPINT lpDxWidths = NULL)
2493 {
2494 ATLASSERT(m_hDC != NULL);
2495 if(nCount == -1)
2496 nCount = lstrlen(lpszString);
2497 return ::ExtTextOut(m_hDC, x, y, nOptions, lpRect, lpszString, nCount, lpDxWidths);
2498 }
2499
2500 #ifndef _WIN32_WCE
2501 SIZE TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL, int nTabOrigin = 0)
2502 {
2503 ATLASSERT(m_hDC != NULL);
2504 if(nCount == -1)
2505 nCount = lstrlen(lpszString);
2506 LONG lRes = ::TabbedTextOut(m_hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin);
2507 SIZE size = { GET_X_LPARAM(lRes), GET_Y_LPARAM(lRes) };
2508 return size;
2509 }
2510 #endif // !_WIN32_WCE
2511
2512 int DrawText(LPCTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat)
2513 {
2514 ATLASSERT(m_hDC != NULL);
2515 #ifndef _WIN32_WCE
2516 ATLASSERT((uFormat & DT_MODIFYSTRING) == 0);
2517 #endif // !_WIN32_WCE
2518 return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat);
2519 }
2520
2521 int DrawText(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat)
2522 {
2523 ATLASSERT(m_hDC != NULL);
2524 return ::DrawText(m_hDC, lpstrText, cchText, lpRect, uFormat);
2525 }
2526
2527 #ifndef _WIN32_WCE
2528 int DrawTextEx(LPTSTR lpstrText, int cchText, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams = NULL)
2529 {
2530 ATLASSERT(m_hDC != NULL);
2531 return ::DrawTextEx(m_hDC, lpstrText, cchText, lpRect, uFormat, lpDTParams);
2532 }
2533 #endif // !_WIN32_WCE
2534
2535 #if (_WIN32_WINNT >= 0x0501)
2536 int DrawShadowText(LPCWSTR lpstrText, int cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset)
2537 {
2538 ATLASSERT(m_hDC != NULL);
2539 // This function is present only if comctl32.dll version 6 is loaded;
2540 // we use LoadLibrary/GetProcAddress to allow apps compiled with
2541 // _WIN32_WINNT >= 0x0501 to run on older Windows/CommCtrl
2542 int nRet = 0;
2543 HMODULE hCommCtrlDLL = ::LoadLibrary(_T("comctl32.dll"));
2544 ATLASSERT(hCommCtrlDLL != NULL);
2545 if(hCommCtrlDLL != NULL)
2546 {
2547 typedef int (WINAPI *PFN_DrawShadowText)(HDC hDC, LPCWSTR lpstrText, UINT cchText, LPRECT lpRect, DWORD dwFlags, COLORREF clrText, COLORREF clrShadow, int xOffset, int yOffset);
2548 PFN_DrawShadowText pfnDrawShadowText = (PFN_DrawShadowText)::GetProcAddress(hCommCtrlDLL, "DrawShadowText");
2549 ATLASSERT(pfnDrawShadowText != NULL); // this function requires CommCtrl6
2550 if(pfnDrawShadowText != NULL)
2551 nRet = pfnDrawShadowText(m_hDC, lpstrText, cchText, lpRect, dwFlags, clrText, clrShadow, xOffset, yOffset);
2552 ::FreeLibrary(hCommCtrlDLL);
2553 }
2554 return nRet;
2555 }
2556 #endif // (_WIN32_WINNT >= 0x0501)
2557
2558 BOOL GetTextExtent(LPCTSTR lpszString, int nCount, LPSIZE lpSize) const
2559 {
2560 ATLASSERT(m_hDC != NULL);
2561 if(nCount == -1)
2562 nCount = lstrlen(lpszString);
2563 return ::GetTextExtentPoint32(m_hDC, lpszString, nCount, lpSize);
2564 }
2565
2566 BOOL GetTextExtentExPoint(LPCTSTR lpszString, int cchString, LPSIZE lpSize, int nMaxExtent, LPINT lpnFit = NULL, LPINT alpDx = NULL)
2567 {
2568 ATLASSERT(m_hDC != NULL);
2569 return ::GetTextExtentExPoint(m_hDC, lpszString, cchString, nMaxExtent, lpnFit, alpDx, lpSize);
2570 }
2571
2572 #ifndef _WIN32_WCE
2573 DWORD GetTabbedTextExtent(LPCTSTR lpszString, int nCount = -1, int nTabPositions = 0, LPINT lpnTabStopPositions = NULL) const
2574 {
2575 ATLASSERT(m_hDC != NULL);
2576 if(nCount == -1)
2577 nCount = lstrlen(lpszString);
2578 return ::GetTabbedTextExtent(m_hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions);
2579 }
2580
2581 BOOL GrayString(HBRUSH hBrush, BOOL (CALLBACK* lpfnOutput)(HDC, LPARAM, int), LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight)
2582 {
2583 ATLASSERT(m_hDC != NULL);
2584 return ::GrayString(m_hDC, hBrush, (GRAYSTRINGPROC)lpfnOutput, lpData, nCount, x, y, nWidth, nHeight);
2585 }
2586 #endif // !_WIN32_WCE
2587
2588 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
2589 UINT GetTextAlign() const
2590 {
2591 ATLASSERT(m_hDC != NULL);
2592 return ::GetTextAlign(m_hDC);
2593 }
2594
2595 UINT SetTextAlign(UINT nFlags)
2596 {
2597 ATLASSERT(m_hDC != NULL);
2598 return ::SetTextAlign(m_hDC, nFlags);
2599 }
2600 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
2601
2602 int GetTextFace(LPTSTR lpszFacename, int nCount) const
2603 {
2604 ATLASSERT(m_hDC != NULL);
2605 return ::GetTextFace(m_hDC, nCount, lpszFacename);
2606 }
2607
2608 int GetTextFaceLen() const
2609 {
2610 ATLASSERT(m_hDC != NULL);
2611 return ::GetTextFace(m_hDC, 0, NULL);
2612 }
2613
2614 #ifndef _ATL_NO_COM
2615 #ifdef _OLEAUTO_H_
2616 BOOL GetTextFace(BSTR& bstrFace) const
2617 {
2618 USES_CONVERSION;
2619 ATLASSERT(m_hDC != NULL);
2620 ATLASSERT(bstrFace == NULL);
2621
2622 int nLen = GetTextFaceLen();
2623 if(nLen == 0)
2624 return FALSE;
2625
2626 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
2627 LPTSTR lpszText = buff.Allocate(nLen);
2628 if(lpszText == NULL)
2629 return FALSE;
2630
2631 if(!GetTextFace(lpszText, nLen))
2632 return FALSE;
2633
2634 bstrFace = ::SysAllocString(T2OLE(lpszText));
2635 return (bstrFace != NULL) ? TRUE : FALSE;
2636 }
2637 #endif
2638 #endif // !_ATL_NO_COM
2639
2640 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
2641 int GetTextFace(_CSTRING_NS::CString& strFace) const
2642 {
2643 ATLASSERT(m_hDC != NULL);
2644
2645 int nLen = GetTextFaceLen();
2646 if(nLen == 0)
2647 return 0;
2648
2649 LPTSTR lpstr = strFace.GetBufferSetLength(nLen);
2650 if(lpstr == NULL)
2651 return 0;
2652 int nRet = GetTextFace(lpstr, nLen);
2653 strFace.ReleaseBuffer();
2654 return nRet;
2655 }
2656 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
2657
2658 BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const
2659 {
2660 ATLASSERT(m_hDC != NULL);
2661 return ::GetTextMetrics(m_hDC, lpMetrics);
2662 }
2663
2664 #ifndef _WIN32_WCE
2665 int SetTextJustification(int nBreakExtra, int nBreakCount)
2666 {
2667 ATLASSERT(m_hDC != NULL);
2668 return ::SetTextJustification(m_hDC, nBreakExtra, nBreakCount);
2669 }
2670
2671 int GetTextCharacterExtra() const
2672 {
2673 ATLASSERT(m_hDC != NULL);
2674 return ::GetTextCharacterExtra(m_hDC);
2675 }
2676
2677 int SetTextCharacterExtra(int nCharExtra)
2678 {
2679 ATLASSERT(m_hDC != NULL);
2680 return ::SetTextCharacterExtra(m_hDC, nCharExtra);
2681 }
2682 #endif // !_WIN32_WCE
2683
2684 // Advanced Drawing
2685 BOOL DrawEdge(LPRECT lpRect, UINT nEdge, UINT nFlags)
2686 {
2687 ATLASSERT(m_hDC != NULL);
2688 return ::DrawEdge(m_hDC, lpRect, nEdge, nFlags);
2689 }
2690
2691 BOOL DrawFrameControl(LPRECT lpRect, UINT nType, UINT nState)
2692 {
2693 ATLASSERT(m_hDC != NULL);
2694 return ::DrawFrameControl(m_hDC, lpRect, nType, nState);
2695 }
2696
2697 // Scrolling Functions
2698 BOOL ScrollDC(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate)
2699 {
2700 ATLASSERT(m_hDC != NULL);
2701 return ::ScrollDC(m_hDC, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate);
2702 }
2703
2704 // Font Functions
2705 #ifndef _WIN32_WCE
2706 BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const
2707 {
2708 ATLASSERT(m_hDC != NULL);
2709 return ::GetCharWidth(m_hDC, nFirstChar, nLastChar, lpBuffer);
2710 }
2711
2712 // GetCharWidth32 is not supported under Win9x
2713 BOOL GetCharWidth32(UINT nFirstChar, UINT nLastChar, LPINT lpBuffer) const
2714 {
2715 ATLASSERT(m_hDC != NULL);
2716 return ::GetCharWidth32(m_hDC, nFirstChar, nLastChar, lpBuffer);
2717 }
2718
2719 DWORD SetMapperFlags(DWORD dwFlag)
2720 {
2721 ATLASSERT(m_hDC != NULL);
2722 return ::SetMapperFlags(m_hDC, dwFlag);
2723 }
2724
2725 BOOL GetAspectRatioFilter(LPSIZE lpSize) const
2726 {
2727 ATLASSERT(m_hDC != NULL);
2728 return ::GetAspectRatioFilterEx(m_hDC, lpSize);
2729 }
2730
2731 BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABC lpabc) const
2732 {
2733 ATLASSERT(m_hDC != NULL);
2734 return ::GetCharABCWidths(m_hDC, nFirstChar, nLastChar, lpabc);
2735 }
2736
2737 DWORD GetFontData(DWORD dwTable, DWORD dwOffset, LPVOID lpData, DWORD cbData) const
2738 {
2739 ATLASSERT(m_hDC != NULL);
2740 return ::GetFontData(m_hDC, dwTable, dwOffset, lpData, cbData);
2741 }
2742
2743 int GetKerningPairs(int nPairs, LPKERNINGPAIR lpkrnpair) const
2744 {
2745 ATLASSERT(m_hDC != NULL);
2746 return ::GetKerningPairs(m_hDC, nPairs, lpkrnpair);
2747 }
2748
2749 UINT GetOutlineTextMetrics(UINT cbData, LPOUTLINETEXTMETRIC lpotm) const
2750 {
2751 ATLASSERT(m_hDC != NULL);
2752 return ::GetOutlineTextMetrics(m_hDC, cbData, lpotm);
2753 }
2754
2755 DWORD GetGlyphOutline(UINT nChar, UINT nFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2* lpmat2) const
2756 {
2757 ATLASSERT(m_hDC != NULL);
2758 return ::GetGlyphOutline(m_hDC, nChar, nFormat, lpgm, cbBuffer, lpBuffer, lpmat2);
2759 }
2760
2761 BOOL GetCharABCWidths(UINT nFirstChar, UINT nLastChar, LPABCFLOAT lpABCF) const
2762 {
2763 ATLASSERT(m_hDC != NULL);
2764 return ::GetCharABCWidthsFloat(m_hDC, nFirstChar, nLastChar, lpABCF);
2765 }
2766
2767 BOOL GetCharWidth(UINT nFirstChar, UINT nLastChar, float* lpFloatBuffer) const
2768 {
2769 ATLASSERT(m_hDC != NULL);
2770 return ::GetCharWidthFloat(m_hDC, nFirstChar, nLastChar, lpFloatBuffer);
2771 }
2772 #endif // !_WIN32_WCE
2773
2774 // Printer/Device Escape Functions
2775 #ifndef _WIN32_WCE
2776 int Escape(int nEscape, int nCount, LPCSTR lpszInData, LPVOID lpOutData)
2777 {
2778 ATLASSERT(m_hDC != NULL);
2779 return ::Escape(m_hDC, nEscape, nCount, lpszInData, lpOutData);
2780 }
2781 #endif // !_WIN32_WCE
2782
2783 int Escape(int nEscape, int nInputSize, LPCSTR lpszInputData,
2784 int nOutputSize, LPSTR lpszOutputData)
2785 {
2786 ATLASSERT(m_hDC != NULL);
2787 return ::ExtEscape(m_hDC, nEscape, nInputSize, lpszInputData, nOutputSize, lpszOutputData);
2788 }
2789
2790 #ifndef _WIN32_WCE
2791 int DrawEscape(int nEscape, int nInputSize, LPCSTR lpszInputData)
2792 {
2793 ATLASSERT(m_hDC != NULL);
2794 return ::DrawEscape(m_hDC, nEscape, nInputSize, lpszInputData);
2795 }
2796 #endif // !_WIN32_WCE
2797
2798 // Escape helpers
2799 #if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc))
2800 int StartDoc(LPCTSTR lpszDocName) // old Win3.0 version
2801 {
2802 DOCINFO di = { 0 };
2803 di.cbSize = sizeof(DOCINFO);
2804 di.lpszDocName = lpszDocName;
2805 return StartDoc(&di);
2806 }
2807
2808 int StartDoc(LPDOCINFO lpDocInfo)
2809 {
2810 ATLASSERT(m_hDC != NULL);
2811 return ::StartDoc(m_hDC, lpDocInfo);
2812 }
2813
2814 int StartPage()
2815 {
2816 ATLASSERT(m_hDC != NULL);
2817 return ::StartPage(m_hDC);
2818 }
2819
2820 int EndPage()
2821 {
2822 ATLASSERT(m_hDC != NULL);
2823 return ::EndPage(m_hDC);
2824 }
2825
2826 int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int))
2827 {
2828 ATLASSERT(m_hDC != NULL);
2829 return ::SetAbortProc(m_hDC, (ABORTPROC)lpfn);
2830 }
2831
2832 int AbortDoc()
2833 {
2834 ATLASSERT(m_hDC != NULL);
2835 return ::AbortDoc(m_hDC);
2836 }
2837
2838 int EndDoc()
2839 {
2840 ATLASSERT(m_hDC != NULL);
2841 return ::EndDoc(m_hDC);
2842 }
2843 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 200) && defined(StartDoc))
2844
2845 // MetaFile Functions
2846 #ifndef _WIN32_WCE
2847 BOOL PlayMetaFile(HMETAFILE hMF)
2848 {
2849 ATLASSERT(m_hDC != NULL);
2850 if(::GetDeviceCaps(m_hDC, TECHNOLOGY) == DT_METAFILE)
2851 {
2852 // playing metafile in metafile, just use core windows API
2853 return ::PlayMetaFile(m_hDC, hMF);
2854 }
2855
2856 // for special playback, lParam == pDC
2857 return ::EnumMetaFile(m_hDC, hMF, EnumMetaFileProc, (LPARAM)this);
2858 }
2859
2860 BOOL PlayMetaFile(HENHMETAFILE hEnhMetaFile, LPCRECT lpBounds)
2861 {
2862 ATLASSERT(m_hDC != NULL);
2863 return ::PlayEnhMetaFile(m_hDC, hEnhMetaFile, lpBounds);
2864 }
2865
2866 BOOL AddMetaFileComment(UINT nDataSize, const BYTE* pCommentData) // can be used for enhanced metafiles only
2867 {
2868 ATLASSERT(m_hDC != NULL);
2869 return ::GdiComment(m_hDC, nDataSize, pCommentData);
2870 }
2871
2872 // Special handling for metafile playback
2873 static int CALLBACK EnumMetaFileProc(HDC hDC, HANDLETABLE* pHandleTable, METARECORD* pMetaRec, int nHandles, LPARAM lParam)
2874 {
2875 CDCHandle* pDC = (CDCHandle*)lParam;
2876
2877 switch (pMetaRec->rdFunction)
2878 {
2879 case META_SETMAPMODE:
2880 pDC->SetMapMode((int)(short)pMetaRec->rdParm[0]);
2881 break;
2882 case META_SETWINDOWEXT:
2883 pDC->SetWindowExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2884 break;
2885 case META_SETWINDOWORG:
2886 pDC->SetWindowOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2887 break;
2888 case META_SETVIEWPORTEXT:
2889 pDC->SetViewportExt((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2890 break;
2891 case META_SETVIEWPORTORG:
2892 pDC->SetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2893 break;
2894 case META_SCALEWINDOWEXT:
2895 pDC->ScaleWindowExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
2896 (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2897 break;
2898 case META_SCALEVIEWPORTEXT:
2899 pDC->ScaleViewportExt((int)(short)pMetaRec->rdParm[3], (int)(short)pMetaRec->rdParm[2],
2900 (int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2901 break;
2902 case META_OFFSETVIEWPORTORG:
2903 pDC->OffsetViewportOrg((int)(short)pMetaRec->rdParm[1], (int)(short)pMetaRec->rdParm[0]);
2904 break;
2905 case META_SAVEDC:
2906 pDC->SaveDC();
2907 break;
2908 case META_RESTOREDC:
2909 pDC->RestoreDC((int)(short)pMetaRec->rdParm[0]);
2910 break;
2911 case META_SETBKCOLOR:
2912 pDC->SetBkColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
2913 break;
2914 case META_SETTEXTCOLOR:
2915 pDC->SetTextColor(*(UNALIGNED COLORREF*)&pMetaRec->rdParm[0]);
2916 break;
2917
2918 // need to watch out for SelectObject(HFONT), for custom font mapping
2919 case META_SELECTOBJECT:
2920 {
2921 HGDIOBJ hObject = pHandleTable->objectHandle[pMetaRec->rdParm[0]];
2922 UINT nObjType = ::GetObjectType(hObject);
2923 if(nObjType == 0)
2924 {
2925 // object type is unknown, determine if it is a font
2926 HFONT hStockFont = (HFONT)::GetStockObject(SYSTEM_FONT);
2927 HFONT hFontOld = (HFONT)::SelectObject(pDC->m_hDC, hStockFont);
2928 HGDIOBJ hObjOld = ::SelectObject(pDC->m_hDC, hObject);
2929 if(hObjOld == hStockFont)
2930 {
2931 // got the stock object back, so must be selecting a font
2932 pDC->SelectFont((HFONT)hObject);
2933 break; // don't play the default record
2934 }
2935 else
2936 {
2937 // didn't get the stock object back, so restore everything
2938 ::SelectObject(pDC->m_hDC, hFontOld);
2939 ::SelectObject(pDC->m_hDC, hObjOld);
2940 }
2941 // and fall through to PlayMetaFileRecord...
2942 }
2943 else if(nObjType == OBJ_FONT)
2944 {
2945 // play back as CDCHandle::SelectFont(HFONT)
2946 pDC->SelectFont((HFONT)hObject);
2947 break; // don't play the default record
2948 }
2949 }
2950 // fall through...
2951
2952 default:
2953 ::PlayMetaFileRecord(hDC, pHandleTable, pMetaRec, nHandles);
2954 break;
2955 }
2956
2957 return 1;
2958 }
2959 #endif // !_WIN32_WCE
2960
2961 // Path Functions
2962 #ifndef _WIN32_WCE
2963 BOOL AbortPath()
2964 {
2965 ATLASSERT(m_hDC != NULL);
2966 return ::AbortPath(m_hDC);
2967 }
2968
2969 BOOL BeginPath()
2970 {
2971 ATLASSERT(m_hDC != NULL);
2972 return ::BeginPath(m_hDC);
2973 }
2974
2975 BOOL CloseFigure()
2976 {
2977 ATLASSERT(m_hDC != NULL);
2978 return ::CloseFigure(m_hDC);
2979 }
2980
2981 BOOL EndPath()
2982 {
2983 ATLASSERT(m_hDC != NULL);
2984 return ::EndPath(m_hDC);
2985 }
2986
2987 BOOL FillPath()
2988 {
2989 ATLASSERT(m_hDC != NULL);
2990 return ::FillPath(m_hDC);
2991 }
2992
2993 BOOL FlattenPath()
2994 {
2995 ATLASSERT(m_hDC != NULL);
2996 return ::FlattenPath(m_hDC);
2997 }
2998
2999 BOOL StrokeAndFillPath()
3000 {
3001 ATLASSERT(m_hDC != NULL);
3002 return ::StrokeAndFillPath(m_hDC);
3003 }
3004
3005 BOOL StrokePath()
3006 {
3007 ATLASSERT(m_hDC != NULL);
3008 return ::StrokePath(m_hDC);
3009 }
3010
3011 BOOL WidenPath()
3012 {
3013 ATLASSERT(m_hDC != NULL);
3014 return ::WidenPath(m_hDC);
3015 }
3016
3017 BOOL GetMiterLimit(PFLOAT pfMiterLimit) const
3018 {
3019 ATLASSERT(m_hDC != NULL);
3020 return ::GetMiterLimit(m_hDC, pfMiterLimit);
3021 }
3022
3023 BOOL SetMiterLimit(float fMiterLimit)
3024 {
3025 ATLASSERT(m_hDC != NULL);
3026 return ::SetMiterLimit(m_hDC, fMiterLimit, NULL);
3027 }
3028
3029 int GetPath(LPPOINT lpPoints, LPBYTE lpTypes, int nCount) const
3030 {
3031 ATLASSERT(m_hDC != NULL);
3032 return ::GetPath(m_hDC, lpPoints, lpTypes, nCount);
3033 }
3034
3035 BOOL SelectClipPath(int nMode)
3036 {
3037 ATLASSERT(m_hDC != NULL);
3038 return ::SelectClipPath(m_hDC, nMode);
3039 }
3040 #endif // !_WIN32_WCE
3041
3042 // Misc Helper Functions
3043 static CBrushHandle PASCAL GetHalftoneBrush()
3044 {
3045 HBRUSH halftoneBrush = NULL;
3046 WORD grayPattern[8] = { 0 };
3047 for(int i = 0; i < 8; i++)
3048 grayPattern[i] = (WORD)(0x5555 << (i & 1));
3049 HBITMAP grayBitmap = CreateBitmap(8, 8, 1, 1, &grayPattern);
3050 if(grayBitmap != NULL)
3051 {
3052 halftoneBrush = ::CreatePatternBrush(grayBitmap);
3053 DeleteObject(grayBitmap);
3054 }
3055 return CBrushHandle(halftoneBrush);
3056 }
3057
3058 void DrawDragRect(LPCRECT lpRect, SIZE size, LPCRECT lpRectLast, SIZE sizeLast, HBRUSH hBrush = NULL, HBRUSH hBrushLast = NULL)
3059 {
3060 // first, determine the update region and select it
3061 CRgn rgnOutside;
3062 rgnOutside.CreateRectRgnIndirect(lpRect);
3063 RECT rect = *lpRect;
3064 ::InflateRect(&rect, -size.cx, -size.cy);
3065 ::IntersectRect(&rect, &rect, lpRect);
3066 CRgn rgnInside;
3067 rgnInside.CreateRectRgnIndirect(&rect);
3068 CRgn rgnNew;
3069 rgnNew.CreateRectRgn(0, 0, 0, 0);
3070 rgnNew.CombineRgn(rgnOutside, rgnInside, RGN_XOR);
3071
3072 HBRUSH hBrushOld = NULL;
3073 CBrush brushHalftone;
3074 if(hBrush == NULL)
3075 brushHalftone = hBrush = CDCHandle::GetHalftoneBrush();
3076 if(hBrushLast == NULL)
3077 hBrushLast = hBrush;
3078
3079 CRgn rgnLast;
3080 CRgn rgnUpdate;
3081 if(lpRectLast != NULL)
3082 {
3083 // find difference between new region and old region
3084 rgnLast.CreateRectRgn(0, 0, 0, 0);
3085 rgnOutside.SetRectRgn(lpRectLast->left, lpRectLast->top, lpRectLast->right, lpRectLast->bottom);
3086 rect = *lpRectLast;
3087 ::InflateRect(&rect, -sizeLast.cx, -sizeLast.cy);
3088 ::IntersectRect(&rect, &rect, lpRectLast);
3089 rgnInside.SetRectRgn(rect.left, rect.top, rect.right, rect.bottom);
3090 rgnLast.CombineRgn(rgnOutside, rgnInside, RGN_XOR);
3091
3092 // only diff them if brushes are the same
3093 if(hBrush == hBrushLast)
3094 {
3095 rgnUpdate.CreateRectRgn(0, 0, 0, 0);
3096 rgnUpdate.CombineRgn(rgnLast, rgnNew, RGN_XOR);
3097 }
3098 }
3099 if(hBrush != hBrushLast && lpRectLast != NULL)
3100 {
3101 // brushes are different -- erase old region first
3102 SelectClipRgn(rgnLast);
3103 GetClipBox(&rect);
3104 hBrushOld = SelectBrush(hBrushLast);
3105 PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
3106 SelectBrush(hBrushOld);
3107 hBrushOld = NULL;
3108 }
3109
3110 // draw into the update/new region
3111 SelectClipRgn(rgnUpdate.IsNull() ? rgnNew : rgnUpdate);
3112 GetClipBox(&rect);
3113 hBrushOld = SelectBrush(hBrush);
3114 PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
3115
3116 // cleanup DC
3117 if(hBrushOld != NULL)
3118 SelectBrush(hBrushOld);
3119 SelectClipRgn(NULL);
3120 }
3121
3122 void FillSolidRect(LPCRECT lpRect, COLORREF clr)
3123 {
3124 ATLASSERT(m_hDC != NULL);
3125
3126 COLORREF clrOld = ::SetBkColor(m_hDC, clr);
3127 ATLASSERT(clrOld != CLR_INVALID);
3128 if(clrOld != CLR_INVALID)
3129 {
3130 ::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
3131 ::SetBkColor(m_hDC, clrOld);
3132 }
3133 }
3134
3135 void FillSolidRect(int x, int y, int cx, int cy, COLORREF clr)
3136 {
3137 ATLASSERT(m_hDC != NULL);
3138
3139 RECT rect = { x, y, x + cx, y + cy };
3140 FillSolidRect(&rect, clr);
3141 }
3142
3143 void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
3144 {
3145 Draw3dRect(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
3146 lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
3147 }
3148
3149 void Draw3dRect(int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
3150 {
3151 FillSolidRect(x, y, cx - 1, 1, clrTopLeft);
3152 FillSolidRect(x, y, 1, cy - 1, clrTopLeft);
3153 FillSolidRect(x + cx, y, -1, cy, clrBottomRight);
3154 FillSolidRect(x, y + cy, cx, -1, clrBottomRight);
3155 }
3156
3157 // DIB support
3158 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
3159 int SetDIBitsToDevice(int x, int y, DWORD dwWidth, DWORD dwHeight, int xSrc, int ySrc, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
3160 {
3161 ATLASSERT(m_hDC != NULL);
3162 return ::SetDIBitsToDevice(m_hDC, x, y, dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
3163 }
3164 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 410)
3165
3166 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
3167 int StretchDIBits(int x, int y, int nWidth, int nHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse, DWORD dwRop)
3168 {
3169 ATLASSERT(m_hDC != NULL);
3170 return ::StretchDIBits(m_hDC, x, y, nWidth, nHeight, xSrc, ySrc, nSrcWidth, nSrcHeight, lpvBits, lpbmi, uColorUse, dwRop);
3171 }
3172
3173 UINT GetDIBColorTable(UINT uStartIndex, UINT cEntries, RGBQUAD* pColors) const
3174 {
3175 ATLASSERT(m_hDC != NULL);
3176 return ::GetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors);
3177 }
3178
3179 UINT SetDIBColorTable(UINT uStartIndex, UINT cEntries, CONST RGBQUAD* pColors)
3180 {
3181 ATLASSERT(m_hDC != NULL);
3182 return ::SetDIBColorTable(m_hDC, uStartIndex, cEntries, pColors);
3183 }
3184 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
3185
3186 // OpenGL support
3187 #if !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
3188 int ChoosePixelFormat(CONST PIXELFORMATDESCRIPTOR* ppfd)
3189 {
3190 ATLASSERT(m_hDC != NULL);
3191 return ::ChoosePixelFormat(m_hDC, ppfd);
3192 }
3193
3194 int DescribePixelFormat(int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd)
3195 {
3196 ATLASSERT(m_hDC != NULL);
3197 return ::DescribePixelFormat(m_hDC, iPixelFormat, nBytes, ppfd);
3198 }
3199
3200 int GetPixelFormat() const
3201 {
3202 ATLASSERT(m_hDC != NULL);
3203 return ::GetPixelFormat(m_hDC);
3204 }
3205
3206 BOOL SetPixelFormat(int iPixelFormat, CONST PIXELFORMATDESCRIPTOR* ppfd)
3207 {
3208 ATLASSERT(m_hDC != NULL);
3209 return ::SetPixelFormat(m_hDC, iPixelFormat, ppfd);
3210 }
3211
3212 BOOL SwapBuffers()
3213 {
3214 ATLASSERT(m_hDC != NULL);
3215 return ::SwapBuffers(m_hDC);
3216 }
3217
3218 HGLRC wglCreateContext()
3219 {
3220 ATLASSERT(m_hDC != NULL);
3221 return ::wglCreateContext(m_hDC);
3222 }
3223
3224 HGLRC wglCreateLayerContext(int iLayerPlane)
3225 {
3226 ATLASSERT(m_hDC != NULL);
3227 return ::wglCreateLayerContext(m_hDC, iLayerPlane);
3228 }
3229
3230 BOOL wglMakeCurrent(HGLRC hglrc)
3231 {
3232 ATLASSERT(m_hDC != NULL);
3233 return ::wglMakeCurrent(m_hDC, hglrc);
3234 }
3235
3236 BOOL wglUseFontBitmaps(DWORD dwFirst, DWORD dwCount, DWORD listBase)
3237 {
3238 ATLASSERT(m_hDC != NULL);
3239 return ::wglUseFontBitmaps(m_hDC, dwFirst, dwCount, listBase);
3240 }
3241
3242 BOOL wglUseFontOutlines(DWORD dwFirst, DWORD dwCount, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
3243 {
3244 ATLASSERT(m_hDC != NULL);
3245 return ::wglUseFontOutlines(m_hDC, dwFirst, dwCount, listBase, deviation, extrusion, format, lpgmf);
3246 }
3247
3248 BOOL wglDescribeLayerPlane(int iPixelFormat, int iLayerPlane, UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
3249 {
3250 ATLASSERT(m_hDC != NULL);
3251 return ::wglDescribeLayerPlane(m_hDC, iPixelFormat, iLayerPlane, nBytes, plpd);
3252 }
3253
3254 int wglSetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, CONST COLORREF* pclr)
3255 {
3256 ATLASSERT(m_hDC != NULL);
3257 return ::wglSetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr);
3258 }
3259
3260 int wglGetLayerPaletteEntries(int iLayerPlane, int iStart, int cEntries, COLORREF* pclr)
3261 {
3262 ATLASSERT(m_hDC != NULL);
3263 return ::wglGetLayerPaletteEntries(m_hDC, iLayerPlane, iStart, cEntries, pclr);
3264 }
3265
3266 BOOL wglRealizeLayerPalette(int iLayerPlane, BOOL bRealize)
3267 {
3268 ATLASSERT(m_hDC != NULL);
3269 return ::wglRealizeLayerPalette(m_hDC, iLayerPlane, bRealize);
3270 }
3271
3272 BOOL wglSwapLayerBuffers(UINT uPlanes)
3273 {
3274 ATLASSERT(m_hDC != NULL);
3275 return ::wglSwapLayerBuffers(m_hDC, uPlanes);
3276 }
3277 #endif // !defined(_ATL_NO_OPENGL) && !defined(_WIN32_WCE)
3278
3279 // New for Windows 2000 only
3280 #if (_WIN32_WINNT >= 0x0500)
3281 COLORREF GetDCPenColor() const
3282 {
3283 ATLASSERT(m_hDC != NULL);
3284 return ::GetDCPenColor(m_hDC);
3285 }
3286
3287 COLORREF SetDCPenColor(COLORREF clr)
3288 {
3289 ATLASSERT(m_hDC != NULL);
3290 return ::SetDCPenColor(m_hDC, clr);
3291 }
3292
3293 COLORREF GetDCBrushColor() const
3294 {
3295 ATLASSERT(m_hDC != NULL);
3296 return ::GetDCBrushColor(m_hDC);
3297 }
3298
3299 COLORREF SetDCBrushColor(COLORREF clr)
3300 {
3301 ATLASSERT(m_hDC != NULL);
3302 return ::SetDCBrushColor(m_hDC, clr);
3303 }
3304
3305 #ifndef _WIN32_WCE
3306 DWORD GetFontUnicodeRanges(LPGLYPHSET lpgs) const
3307 {
3308 ATLASSERT(m_hDC != NULL);
3309 return ::GetFontUnicodeRanges(m_hDC, lpgs);
3310 }
3311 #endif // !_WIN32_WCE
3312
3313 DWORD GetGlyphIndices(LPCTSTR lpstr, int cch, LPWORD pgi, DWORD dwFlags) const
3314 {
3315 ATLASSERT(m_hDC != NULL);
3316 return ::GetGlyphIndices(m_hDC, lpstr, cch, pgi, dwFlags);
3317 }
3318
3319 BOOL GetTextExtentPointI(LPWORD pgiIn, int cgi, LPSIZE lpSize) const
3320 {
3321 ATLASSERT(m_hDC != NULL);
3322 return ::GetTextExtentPointI(m_hDC, pgiIn, cgi, lpSize);
3323 }
3324
3325 BOOL GetTextExtentExPointI(LPWORD pgiIn, int cgi, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize) const
3326 {
3327 ATLASSERT(m_hDC != NULL);
3328 return ::GetTextExtentExPointI(m_hDC, pgiIn, cgi, nMaxExtent, lpnFit, alpDx, lpSize);
3329 }
3330
3331 BOOL GetCharWidthI(UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer) const
3332 {
3333 ATLASSERT(m_hDC != NULL);
3334 return ::GetCharWidthI(m_hDC, giFirst, cgi, pgi, lpBuffer);
3335 }
3336
3337 BOOL GetCharABCWidthsI(UINT giFirst, UINT cgi, LPWORD pgi, LPABC lpabc) const
3338 {
3339 ATLASSERT(m_hDC != NULL);
3340 return ::GetCharABCWidthsI(m_hDC, giFirst, cgi, pgi, lpabc);
3341 }
3342 #endif // (_WIN32_WINNT >= 0x0500)
3343
3344 // New for Windows 2000 and Windows 98
3345 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
3346 BOOL ColorCorrectPalette(HPALETTE hPalette, DWORD dwFirstEntry, DWORD dwNumOfEntries)
3347 {
3348 ATLASSERT(m_hDC != NULL);
3349 return ::ColorCorrectPalette(m_hDC, hPalette, dwFirstEntry, dwNumOfEntries);
3350 }
3351 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
3352 };
3353
3354 typedef CDCT<false> CDCHandle;
3355 typedef CDCT<true> CDC;
3356
3357
3358 ///////////////////////////////////////////////////////////////////////////////
3359 // CDC Helpers
3360
3361 class CPaintDC : public CDC
3362 {
3363 public:
3364 // Data members
3365 HWND m_hWnd;
3366 PAINTSTRUCT m_ps;
3367
3368 // Constructor/destructor
3369 CPaintDC(HWND hWnd)
3370 {
3371 ATLASSERT(::IsWindow(hWnd));
3372 m_hWnd = hWnd;
3373 m_hDC = ::BeginPaint(hWnd, &m_ps);
3374 }
3375
3376 ~CPaintDC()
3377 {
3378 ATLASSERT(m_hDC != NULL);
3379 ATLASSERT(::IsWindow(m_hWnd));
3380 ::EndPaint(m_hWnd, &m_ps);
3381 Detach();
3382 }
3383 };
3384
3385 class CClientDC : public CDC
3386 {
3387 public:
3388 // Data members
3389 HWND m_hWnd;
3390
3391 // Constructor/destructor
3392 CClientDC(HWND hWnd)
3393 {
3394 ATLASSERT(hWnd == NULL || ::IsWindow(hWnd));
3395 m_hWnd = hWnd;
3396 m_hDC = ::GetDC(hWnd);
3397 }
3398
3399 ~CClientDC()
3400 {
3401 ATLASSERT(m_hDC != NULL);
3402 ::ReleaseDC(m_hWnd, Detach());
3403 }
3404 };
3405
3406 class CWindowDC : public CDC
3407 {
3408 public:
3409 // Data members
3410 HWND m_hWnd;
3411
3412 // Constructor/destructor
3413 CWindowDC(HWND hWnd)
3414 {
3415 ATLASSERT(hWnd == NULL || ::IsWindow(hWnd));
3416 m_hWnd = hWnd;
3417 m_hDC = ::GetWindowDC(hWnd);
3418 }
3419
3420 ~CWindowDC()
3421 {
3422 ATLASSERT(m_hDC != NULL);
3423 ::ReleaseDC(m_hWnd, Detach());
3424 }
3425 };
3426
3427 class CMemoryDC : public CDC
3428 {
3429 public:
3430 // Data members
3431 HDC m_hDCOriginal;
3432 RECT m_rcPaint;
3433 CBitmap m_bmp;
3434 HBITMAP m_hBmpOld;
3435
3436 // Constructor/destructor
3437 CMemoryDC(HDC hDC, const RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL)
3438 {
3439 m_rcPaint = rcPaint;
3440 CreateCompatibleDC(m_hDCOriginal);
3441 ATLASSERT(m_hDC != NULL);
3442 m_bmp.CreateCompatibleBitmap(m_hDCOriginal, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top);
3443 ATLASSERT(m_bmp.m_hBitmap != NULL);
3444 m_hBmpOld = SelectBitmap(m_bmp);
3445 SetViewportOrg(-m_rcPaint.left, -m_rcPaint.top);
3446 }
3447
3448 ~CMemoryDC()
3449 {
3450 ::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top, m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top, m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY);
3451 SelectBitmap(m_hBmpOld);
3452 }
3453 };
3454
3455
3456 ///////////////////////////////////////////////////////////////////////////////
3457 // Enhanced metafile support
3458
3459 #ifndef _WIN32_WCE
3460
3461 class CEnhMetaFileInfo
3462 {
3463 public:
3464 // Data members
3465 HENHMETAFILE m_hEMF;
3466 BYTE* m_pBits;
3467 TCHAR* m_pDesc;
3468 ENHMETAHEADER m_header;
3469 PIXELFORMATDESCRIPTOR m_pfd;
3470
3471 // Constructor/destructor
3472 CEnhMetaFileInfo(HENHMETAFILE hEMF) : m_pBits(NULL), m_pDesc(NULL), m_hEMF(hEMF)
3473 { }
3474
3475 ~CEnhMetaFileInfo()
3476 {
3477 delete [] m_pBits;
3478 delete [] m_pDesc;
3479 }
3480
3481 // Operations
3482 BYTE* GetEnhMetaFileBits()
3483 {
3484 ATLASSERT(m_hEMF != NULL);
3485 UINT nBytes = ::GetEnhMetaFileBits(m_hEMF, 0, NULL);
3486 delete [] m_pBits;
3487 m_pBits = NULL;
3488 ATLTRY(m_pBits = new BYTE[nBytes]);
3489 if (m_pBits != NULL)
3490 ::GetEnhMetaFileBits(m_hEMF, nBytes, m_pBits);
3491 return m_pBits;
3492 }
3493
3494 LPTSTR GetEnhMetaFileDescription()
3495 {
3496 ATLASSERT(m_hEMF != NULL);
3497 UINT nLen = ::GetEnhMetaFileDescription(m_hEMF, 0, NULL);
3498 delete [] m_pDesc;
3499 m_pDesc = NULL;
3500 ATLTRY(m_pDesc = new TCHAR[nLen]);
3501 if (m_pDesc != NULL)
3502 nLen = ::GetEnhMetaFileDescription(m_hEMF, nLen, m_pDesc);
3503 return m_pDesc;
3504 }
3505
3506 ENHMETAHEADER* GetEnhMetaFileHeader()
3507 {
3508 ATLASSERT(m_hEMF != NULL);
3509 memset(&m_header, 0, sizeof(m_header));
3510 m_header.iType = EMR_HEADER;
3511 m_header.nSize = sizeof(ENHMETAHEADER);
3512 UINT n = ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), &m_header);
3513 return (n != 0) ? &m_header : NULL;
3514 }
3515
3516 PIXELFORMATDESCRIPTOR* GetEnhMetaFilePixelFormat()
3517 {
3518 ATLASSERT(m_hEMF != NULL);
3519 memset(&m_pfd, 0, sizeof(m_pfd));
3520 UINT n = ::GetEnhMetaFilePixelFormat(m_hEMF, sizeof(m_pfd), &m_pfd);
3521 return (n != 0) ? &m_pfd : NULL;
3522 }
3523 };
3524
3525
3526 template <bool t_bManaged>
3527 class CEnhMetaFileT
3528 {
3529 public:
3530 // Data members
3531 HENHMETAFILE m_hEMF;
3532
3533 // Constructor/destructor
3534 CEnhMetaFileT(HENHMETAFILE hEMF = NULL) : m_hEMF(hEMF)
3535 {
3536 }
3537
3538 ~CEnhMetaFileT()
3539 {
3540 if(t_bManaged && m_hEMF != NULL)
3541 DeleteObject();
3542 }
3543
3544 // Operations
3545 CEnhMetaFileT<t_bManaged>& operator =(HENHMETAFILE hEMF)
3546 {
3547 Attach(hEMF);
3548 return *this;
3549 }
3550
3551 void Attach(HENHMETAFILE hEMF)
3552 {
3553 if(t_bManaged && m_hEMF != NULL && m_hEMF != hEMF)
3554 DeleteObject();
3555 m_hEMF = hEMF;
3556 }
3557
3558 HENHMETAFILE Detach()
3559 {
3560 HENHMETAFILE hEMF = m_hEMF;
3561 m_hEMF = NULL;
3562 return hEMF;
3563 }
3564
3565 operator HENHMETAFILE() const { return m_hEMF; }
3566
3567 bool IsNull() const { return (m_hEMF == NULL); }
3568
3569 BOOL DeleteObject()
3570 {
3571 ATLASSERT(m_hEMF != NULL);
3572 BOOL bRet = ::DeleteEnhMetaFile(m_hEMF);
3573 m_hEMF = NULL;
3574 return bRet;
3575 }
3576
3577 UINT GetEnhMetaFileBits(UINT cbBuffer, LPBYTE lpbBuffer) const
3578 {
3579 ATLASSERT(m_hEMF != NULL);
3580 return ::GetEnhMetaFileBits(m_hEMF, cbBuffer, lpbBuffer);
3581 }
3582
3583 UINT GetEnhMetaFileDescription(UINT cchBuffer, LPTSTR lpszDescription) const
3584 {
3585 ATLASSERT(m_hEMF != NULL);
3586 return ::GetEnhMetaFileDescription(m_hEMF, cchBuffer, lpszDescription);
3587 }
3588
3589 UINT GetEnhMetaFileHeader(LPENHMETAHEADER lpemh) const
3590 {
3591 ATLASSERT(m_hEMF != NULL);
3592 lpemh->iType = EMR_HEADER;
3593 lpemh->nSize = sizeof(ENHMETAHEADER);
3594 return ::GetEnhMetaFileHeader(m_hEMF, sizeof(ENHMETAHEADER), lpemh);
3595 }
3596
3597 UINT GetEnhMetaFilePaletteEntries(UINT cEntries, LPPALETTEENTRY lppe) const
3598 {
3599 ATLASSERT(m_hEMF != NULL);
3600 return ::GetEnhMetaFilePaletteEntries(m_hEMF, cEntries, lppe);
3601 }
3602
3603 UINT GetEnhMetaFilePixelFormat(DWORD cbBuffer, PIXELFORMATDESCRIPTOR* ppfd) const
3604 {
3605 ATLASSERT(m_hEMF != NULL);
3606 return ::GetEnhMetaFilePixelFormat(m_hEMF, cbBuffer, ppfd);
3607 }
3608 };
3609
3610 typedef CEnhMetaFileT<false> CEnhMetaFileHandle;
3611 typedef CEnhMetaFileT<true> CEnhMetaFile;
3612
3613
3614 class CEnhMetaFileDC : public CDC
3615 {
3616 public:
3617 // Constructor/destructor
3618 CEnhMetaFileDC()
3619 {
3620 }
3621
3622 CEnhMetaFileDC(HDC hdc, LPCRECT lpRect)
3623 {
3624 Create(hdc, NULL, lpRect, NULL);
3625 ATLASSERT(m_hDC != NULL);
3626 }
3627
3628 CEnhMetaFileDC(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
3629 {
3630 Create(hdcRef, lpFilename, lpRect, lpDescription);
3631 ATLASSERT(m_hDC != NULL);
3632 }
3633
3634 ~CEnhMetaFileDC()
3635 {
3636 HENHMETAFILE hEMF = Close();
3637 if (hEMF != NULL)
3638 ::DeleteEnhMetaFile(hEMF);
3639 }
3640
3641 // Operations
3642 void Create(HDC hdcRef, LPCTSTR lpFilename, LPCRECT lpRect, LPCTSTR lpDescription)
3643 {
3644 ATLASSERT(m_hDC == NULL);
3645 m_hDC = ::CreateEnhMetaFile(hdcRef, lpFilename, lpRect, lpDescription);
3646 }
3647
3648 HENHMETAFILE Close()
3649 {
3650 HENHMETAFILE hEMF = NULL;
3651 if (m_hDC != NULL)
3652 {
3653 hEMF = ::CloseEnhMetaFile(m_hDC);
3654 m_hDC = NULL;
3655 }
3656 return hEMF;
3657 }
3658 };
3659
3660 #endif // !_WIN32_WCE
3661
3662
3663 ///////////////////////////////////////////////////////////////////////////////
3664 // WinCE compatible clipboard CF_DIB format support functions
3665
3666 #ifndef _WTL_NO_DIB16
3667
3668 #define DIBINFO16_BITFIELDS { 31744, 992, 31 }
3669
3670 // DIBINFO16 - To avoid color table problems in WinCE we only create this type of Dib
3671 struct DIBINFO16 // a BITMAPINFO with 2 additional color bitfields
3672 {
3673 BITMAPINFOHEADER bmiHeader;
3674 RGBQUAD bmiColors[3];
3675
3676 DIBINFO16(SIZE size)
3677 {
3678 BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), size.cx, size.cy,
3679 1, 16, BI_BITFIELDS, (DWORD)(2 * size.cx * size.cy), 0, 0, 3 };
3680 DWORD dw[3] = DIBINFO16_BITFIELDS ;
3681
3682 bmiHeader = bmih;
3683 SecureHelper::memcpy_x(bmiColors, sizeof(bmiColors), dw, 3 * sizeof(DWORD));
3684 }
3685 };
3686
3687
3688 // AtlxxxDibxxx minimal packed DIB implementation and helpers to copy and paste CF_DIB
3689
3690 inline bool AtlIsDib16(LPBITMAPINFOHEADER pbmih)
3691 {
3692 return (pbmih->biBitCount == 16) && (pbmih->biCompression == BI_BITFIELDS);
3693 }
3694
3695 inline int AtlGetDibColorTableSize(LPBITMAPINFOHEADER pbmih)
3696 {
3697 switch (pbmih->biBitCount)
3698 {
3699 case 2:
3700 case 4:
3701 case 8:
3702 return pbmih->biClrUsed ? pbmih->biClrUsed : 1 << pbmih->biBitCount;
3703 case 24:
3704 break;
3705 case 16:
3706 case 32:
3707 return pbmih->biCompression == BI_BITFIELDS ? 3 : 0;
3708 default:
3709 ATLASSERT(FALSE); // should never come here
3710 }
3711
3712 return 0;
3713 }
3714
3715 inline int AtlGetDibNumColors(LPBITMAPINFOHEADER pbmih)
3716 {
3717 switch (pbmih->biBitCount)
3718 {
3719 case 2:
3720 case 4:
3721 case 8:
3722 if (pbmih->biClrUsed)
3723 return pbmih->biClrUsed;
3724 else
3725 break;
3726 case 16:
3727 if (pbmih->biCompression == BI_BITFIELDS )
3728 return 1 << 15;
3729 else
3730 break;
3731 case 24:
3732 break;
3733 case 32:
3734 if (pbmih->biCompression == BI_BITFIELDS )
3735 return 1 << 24;
3736 else
3737 break;
3738 default:
3739 ATLASSERT(FALSE);
3740 }
3741
3742 return 1 << pbmih->biBitCount;
3743 }
3744
3745 inline HBITMAP AtlGetDibBitmap(LPBITMAPINFO pbmi)
3746 {
3747 CDC dc(NULL);
3748 void* pBits = NULL;
3749
3750 LPBYTE pDibBits = (LPBYTE)pbmi + sizeof(BITMAPINFOHEADER) + AtlGetDibColorTableSize(&pbmi->bmiHeader) * sizeof(RGBQUAD);
3751 HBITMAP hbm = CreateDIBSection(dc, pbmi, DIB_RGB_COLORS, &pBits, NULL, NULL);
3752 if (hbm != NULL)
3753 {
3754 int cbBits = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biHeight * pbmi->bmiHeader.biBitCount / 8;
3755 SecureHelper::memcpy_x(pBits, cbBits, pDibBits, pbmi->bmiHeader.biSizeImage);
3756 }
3757
3758 return hbm;
3759 }
3760
3761 inline HBITMAP AtlCopyBitmap(HBITMAP hbm, SIZE sizeDst, bool bAsBitmap = false)
3762 {
3763 CDC hdcSrc = CreateCompatibleDC(NULL);
3764 CDC hdcDst = CreateCompatibleDC(NULL);
3765
3766 CBitmapHandle hbmOld = NULL, hbmOld2 = NULL, bmSrc = hbm;
3767
3768 CBitmap bmNew = NULL;
3769
3770 SIZE sizeSrc = { 0 };
3771 bmSrc.GetSize(sizeSrc);
3772
3773 hbmOld = hdcSrc.SelectBitmap(bmSrc);
3774
3775 if (bAsBitmap)
3776 {
3777 bmNew.CreateCompatibleBitmap(hdcSrc, sizeDst.cx, sizeDst.cy);
3778 }
3779 else
3780 {
3781 DIBINFO16 dib16(sizeDst);
3782 LPVOID pBits = NULL;
3783 bmNew = CreateDIBSection(hdcDst, (const BITMAPINFO*)&dib16, DIB_RGB_COLORS, &pBits, NULL, NULL);
3784 }
3785
3786 ATLASSERT(!bmNew.IsNull());
3787
3788 hbmOld2 = hdcDst.SelectBitmap(bmNew);
3789 BOOL bOK = FALSE;
3790
3791 if ((sizeDst.cx == sizeSrc.cx) && (sizeDst.cy == sizeSrc.cy))
3792 bOK = hdcDst.BitBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, SRCCOPY);
3793 else
3794 bOK = hdcDst.StretchBlt(0, 0, sizeDst.cx, sizeDst.cy, hdcSrc, 0, 0, sizeSrc.cx, sizeSrc.cy, SRCCOPY);
3795
3796 hdcSrc.SelectBitmap(hbmOld);
3797 hdcDst.SelectBitmap(hbmOld2);
3798
3799 if (bOK == FALSE)
3800 bmNew.DeleteObject();
3801
3802 return bmNew.Detach();
3803 }
3804
3805 inline HLOCAL AtlCreatePackedDib16(HBITMAP hbm, SIZE size)
3806 {
3807 DIBSECTION ds = { 0 };
3808 LPBYTE pDib = NULL;
3809 bool bCopied = false;
3810
3811 bool bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds);
3812 if ((bOK == FALSE) || (ds.dsBm.bmBits == NULL) || (AtlIsDib16(&ds.dsBmih) == FALSE) ||
3813 (ds.dsBmih.biWidth != size.cx ) || (ds.dsBmih.biHeight != size.cy ))
3814 {
3815 if ((hbm = AtlCopyBitmap(hbm, size)) != NULL)
3816 {
3817 bCopied = true;
3818 bOK = GetObject(hbm, sizeof(ds), &ds) == sizeof(ds);
3819 }
3820 else
3821 {
3822 bOK = FALSE;
3823 }
3824 }
3825
3826 if((bOK != FALSE) && (AtlIsDib16(&ds.dsBmih) != FALSE) && (ds.dsBm.bmBits != NULL))
3827 {
3828 pDib = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeof(DIBINFO16) + ds.dsBmih.biSizeImage);
3829 if (pDib != NULL)
3830 {
3831 SecureHelper::memcpy_x(pDib, sizeof(DIBINFO16) + ds.dsBmih.biSizeImage, &ds.dsBmih, sizeof(DIBINFO16));
3832 SecureHelper::memcpy_x(pDib + sizeof(DIBINFO16), ds.dsBmih.biSizeImage, ds.dsBm.bmBits, ds.dsBmih.biSizeImage);
3833 }
3834 }
3835
3836 if (bCopied == true)
3837 DeleteObject(hbm);
3838
3839 return (HLOCAL)pDib;
3840 }
3841
3842 inline bool AtlSetClipboardDib16(HBITMAP hbm, SIZE size, HWND hWnd)
3843 {
3844 ATLASSERT(::IsWindow(hWnd));
3845 BOOL bOK = OpenClipboard(hWnd);
3846 if (bOK != FALSE)
3847 {
3848 bOK = EmptyClipboard();
3849 if (bOK != FALSE)
3850 {
3851 HLOCAL hDib = AtlCreatePackedDib16(hbm, size);
3852 if (hDib != NULL)
3853 {
3854 bOK = SetClipboardData(CF_DIB, hDib) != NULL;
3855 if (bOK == FALSE)
3856 LocalFree(hDib);
3857 }
3858 else
3859 {
3860 bOK = FALSE;
3861 }
3862 }
3863 CloseClipboard();
3864 }
3865
3866 return (bOK != FALSE);
3867 }
3868
3869 inline HBITMAP AtlGetClipboardDib(HWND hWnd)
3870 {
3871 ATLASSERT(::IsWindow(hWnd) != FALSE);
3872 HBITMAP hbm = NULL;
3873 if (OpenClipboard(hWnd) != FALSE)
3874 {
3875 LPBITMAPINFO pbmi = (LPBITMAPINFO)GetClipboardData(CF_DIB);
3876 if (pbmi != NULL)
3877 hbm = AtlGetDibBitmap(pbmi);
3878 CloseClipboard();
3879 }
3880
3881 return hbm;
3882 }
3883
3884 #endif // _WTL_NO_DIB16
3885
3886 }; // namespace WTL
3887
3888 #endif // __ATLGDI_H__
+0
-3756
src/third_party/wtl/Include/atlmisc.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLMISC_H__
9 #define __ATLMISC_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlmisc.h requires atlapp.h to be included first
15 #endif
16
17
18 #ifdef _ATL_TMP_NO_CSTRING
19 #define _WTL_NO_CSTRING
20 #endif
21
22 #if defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING)
23 #error Conflicting options - both _WTL_USE_CSTRING and _WTL_NO_CSTRING are defined
24 #endif // defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING)
25
26 #if !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING)
27 #define _WTL_USE_CSTRING
28 #endif // !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING)
29
30 #ifndef _WTL_NO_CSTRING
31 #if defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT)
32 #error Cannot use CString floating point formatting with _ATL_MIN_CRT defined
33 #endif // defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT)
34 #endif // !_WTL_NO_CSTRING
35
36
37 ///////////////////////////////////////////////////////////////////////////////
38 // Classes in this file:
39 //
40 // CSize
41 // CPoint
42 // CRect
43 // CString
44 //
45 // CRecentDocumentListBase<T, t_cchItemLen, t_nFirstID, t_nLastID>
46 // CRecentDocumentList
47 // CFindFile
48 //
49 // Global functions:
50 // AtlGetStockPen()
51 // AtlGetStockBrush()
52 // AtlGetStockFont()
53 // AtlGetStockPalette()
54 //
55 // AtlCompactPath()
56
57
58 namespace WTL
59 {
60
61 #ifndef _WTL_NO_WTYPES
62
63 // forward declarations
64 class CSize;
65 class CPoint;
66 class CRect;
67
68 ///////////////////////////////////////////////////////////////////////////////
69 // CSize - Wrapper for Windows SIZE structure.
70
71 class CSize : public SIZE
72 {
73 public:
74 // Constructors
75 CSize()
76 {
77 cx = 0;
78 cy = 0;
79 }
80
81 CSize(int initCX, int initCY)
82 {
83 cx = initCX;
84 cy = initCY;
85 }
86
87 CSize(SIZE initSize)
88 {
89 *(SIZE*)this = initSize;
90 }
91
92 CSize(POINT initPt)
93 {
94 *(POINT*)this = initPt;
95 }
96
97 CSize(DWORD dwSize)
98 {
99 cx = (short)LOWORD(dwSize);
100 cy = (short)HIWORD(dwSize);
101 }
102
103 // Operations
104 BOOL operator ==(SIZE size) const
105 {
106 return (cx == size.cx && cy == size.cy);
107 }
108
109 BOOL operator !=(SIZE size) const
110 {
111 return (cx != size.cx || cy != size.cy);
112 }
113
114 void operator +=(SIZE size)
115 {
116 cx += size.cx;
117 cy += size.cy;
118 }
119
120 void operator -=(SIZE size)
121 {
122 cx -= size.cx;
123 cy -= size.cy;
124 }
125
126 void SetSize(int CX, int CY)
127 {
128 cx = CX;
129 cy = CY;
130 }
131
132 // Operators returning CSize values
133 CSize operator +(SIZE size) const
134 {
135 return CSize(cx + size.cx, cy + size.cy);
136 }
137
138 CSize operator -(SIZE size) const
139 {
140 return CSize(cx - size.cx, cy - size.cy);
141 }
142
143 CSize operator -() const
144 {
145 return CSize(-cx, -cy);
146 }
147
148 // Operators returning CPoint values
149 CPoint operator +(POINT point) const;
150 CPoint operator -(POINT point) const;
151
152 // Operators returning CRect values
153 CRect operator +(const RECT* lpRect) const;
154 CRect operator -(const RECT* lpRect) const;
155 };
156
157
158 ///////////////////////////////////////////////////////////////////////////////
159 // CPoint - Wrapper for Windows POINT structure.
160
161 class CPoint : public POINT
162 {
163 public:
164 // Constructors
165 CPoint()
166 {
167 x = 0;
168 y = 0;
169 }
170
171 CPoint(int initX, int initY)
172 {
173 x = initX;
174 y = initY;
175 }
176
177 CPoint(POINT initPt)
178 {
179 *(POINT*)this = initPt;
180 }
181
182 CPoint(SIZE initSize)
183 {
184 *(SIZE*)this = initSize;
185 }
186
187 CPoint(DWORD dwPoint)
188 {
189 x = (short)LOWORD(dwPoint);
190 y = (short)HIWORD(dwPoint);
191 }
192
193 // Operations
194 void Offset(int xOffset, int yOffset)
195 {
196 x += xOffset;
197 y += yOffset;
198 }
199
200 void Offset(POINT point)
201 {
202 x += point.x;
203 y += point.y;
204 }
205
206 void Offset(SIZE size)
207 {
208 x += size.cx;
209 y += size.cy;
210 }
211
212 BOOL operator ==(POINT point) const
213 {
214 return (x == point.x && y == point.y);
215 }
216
217 BOOL operator !=(POINT point) const
218 {
219 return (x != point.x || y != point.y);
220 }
221
222 void operator +=(SIZE size)
223 {
224 x += size.cx;
225 y += size.cy;
226 }
227
228 void operator -=(SIZE size)
229 {
230 x -= size.cx;
231 y -= size.cy;
232 }
233
234 void operator +=(POINT point)
235 {
236 x += point.x;
237 y += point.y;
238 }
239
240 void operator -=(POINT point)
241 {
242 x -= point.x;
243 y -= point.y;
244 }
245
246 void SetPoint(int X, int Y)
247 {
248 x = X;
249 y = Y;
250 }
251
252 // Operators returning CPoint values
253 CPoint operator +(SIZE size) const
254 {
255 return CPoint(x + size.cx, y + size.cy);
256 }
257
258 CPoint operator -(SIZE size) const
259 {
260 return CPoint(x - size.cx, y - size.cy);
261 }
262
263 CPoint operator -() const
264 {
265 return CPoint(-x, -y);
266 }
267
268 CPoint operator +(POINT point) const
269 {
270 return CPoint(x + point.x, y + point.y);
271 }
272
273 // Operators returning CSize values
274 CSize operator -(POINT point) const
275 {
276 return CSize(x - point.x, y - point.y);
277 }
278
279 // Operators returning CRect values
280 CRect operator +(const RECT* lpRect) const;
281 CRect operator -(const RECT* lpRect) const;
282 };
283
284
285 ///////////////////////////////////////////////////////////////////////////////
286 // CRect - Wrapper for Windows RECT structure.
287
288 class CRect : public RECT
289 {
290 public:
291 // Constructors
292 CRect()
293 {
294 left = 0;
295 top = 0;
296 right = 0;
297 bottom = 0;
298 }
299
300 CRect(int l, int t, int r, int b)
301 {
302 left = l;
303 top = t;
304 right = r;
305 bottom = b;
306 }
307
308 CRect(const RECT& srcRect)
309 {
310 ::CopyRect(this, &srcRect);
311 }
312
313 CRect(LPCRECT lpSrcRect)
314 {
315 ::CopyRect(this, lpSrcRect);
316 }
317
318 CRect(POINT point, SIZE size)
319 {
320 right = (left = point.x) + size.cx;
321 bottom = (top = point.y) + size.cy;
322 }
323
324 CRect(POINT topLeft, POINT bottomRight)
325 {
326 left = topLeft.x;
327 top = topLeft.y;
328 right = bottomRight.x;
329 bottom = bottomRight.y;
330 }
331
332 // Attributes (in addition to RECT members)
333 int Width() const
334 {
335 return right - left;
336 }
337
338 int Height() const
339 {
340 return bottom - top;
341 }
342
343 CSize Size() const
344 {
345 return CSize(right - left, bottom - top);
346 }
347
348 CPoint& TopLeft()
349 {
350 return *((CPoint*)this);
351 }
352
353 CPoint& BottomRight()
354 {
355 return *((CPoint*)this + 1);
356 }
357
358 const CPoint& TopLeft() const
359 {
360 return *((CPoint*)this);
361 }
362
363 const CPoint& BottomRight() const
364 {
365 return *((CPoint*)this + 1);
366 }
367
368 CPoint CenterPoint() const
369 {
370 return CPoint((left + right) / 2, (top + bottom) / 2);
371 }
372
373 // convert between CRect and LPRECT/LPCRECT (no need for &)
374 operator LPRECT()
375 {
376 return this;
377 }
378
379 operator LPCRECT() const
380 {
381 return this;
382 }
383
384 BOOL IsRectEmpty() const
385 {
386 return ::IsRectEmpty(this);
387 }
388
389 BOOL IsRectNull() const
390 {
391 return (left == 0 && right == 0 && top == 0 && bottom == 0);
392 }
393
394 BOOL PtInRect(POINT point) const
395 {
396 return ::PtInRect(this, point);
397 }
398
399 // Operations
400 void SetRect(int x1, int y1, int x2, int y2)
401 {
402 ::SetRect(this, x1, y1, x2, y2);
403 }
404
405 void SetRect(POINT topLeft, POINT bottomRight)
406 {
407 ::SetRect(this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
408 }
409
410 void SetRectEmpty()
411 {
412 ::SetRectEmpty(this);
413 }
414
415 void CopyRect(LPCRECT lpSrcRect)
416 {
417 ::CopyRect(this, lpSrcRect);
418 }
419
420 BOOL EqualRect(LPCRECT lpRect) const
421 {
422 return ::EqualRect(this, lpRect);
423 }
424
425 void InflateRect(int x, int y)
426 {
427 ::InflateRect(this, x, y);
428 }
429
430 void InflateRect(SIZE size)
431 {
432 ::InflateRect(this, size.cx, size.cy);
433 }
434
435 void InflateRect(LPCRECT lpRect)
436 {
437 left -= lpRect->left;
438 top -= lpRect->top;
439 right += lpRect->right;
440 bottom += lpRect->bottom;
441 }
442
443 void InflateRect(int l, int t, int r, int b)
444 {
445 left -= l;
446 top -= t;
447 right += r;
448 bottom += b;
449 }
450
451 void DeflateRect(int x, int y)
452 {
453 ::InflateRect(this, -x, -y);
454 }
455
456 void DeflateRect(SIZE size)
457 {
458 ::InflateRect(this, -size.cx, -size.cy);
459 }
460
461 void DeflateRect(LPCRECT lpRect)
462 {
463 left += lpRect->left;
464 top += lpRect->top;
465 right -= lpRect->right;
466 bottom -= lpRect->bottom;
467 }
468
469 void DeflateRect(int l, int t, int r, int b)
470 {
471 left += l;
472 top += t;
473 right -= r;
474 bottom -= b;
475 }
476
477 void OffsetRect(int x, int y)
478 {
479 ::OffsetRect(this, x, y);
480 }
481 void OffsetRect(SIZE size)
482 {
483 ::OffsetRect(this, size.cx, size.cy);
484 }
485
486 void OffsetRect(POINT point)
487 {
488 ::OffsetRect(this, point.x, point.y);
489 }
490
491 void NormalizeRect()
492 {
493 int nTemp;
494 if (left > right)
495 {
496 nTemp = left;
497 left = right;
498 right = nTemp;
499 }
500 if (top > bottom)
501 {
502 nTemp = top;
503 top = bottom;
504 bottom = nTemp;
505 }
506 }
507
508 // absolute position of rectangle
509 void MoveToY(int y)
510 {
511 bottom = Height() + y;
512 top = y;
513 }
514
515 void MoveToX(int x)
516 {
517 right = Width() + x;
518 left = x;
519 }
520
521 void MoveToXY(int x, int y)
522 {
523 MoveToX(x);
524 MoveToY(y);
525 }
526
527 void MoveToXY(POINT pt)
528 {
529 MoveToX(pt.x);
530 MoveToY(pt.y);
531 }
532
533 // operations that fill '*this' with result
534 BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2)
535 {
536 return ::IntersectRect(this, lpRect1, lpRect2);
537 }
538
539 BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2)
540 {
541 return ::UnionRect(this, lpRect1, lpRect2);
542 }
543
544 BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2)
545 {
546 return ::SubtractRect(this, lpRectSrc1, lpRectSrc2);
547 }
548
549 // Additional Operations
550 void operator =(const RECT& srcRect)
551 {
552 ::CopyRect(this, &srcRect);
553 }
554
555 BOOL operator ==(const RECT& rect) const
556 {
557 return ::EqualRect(this, &rect);
558 }
559
560 BOOL operator !=(const RECT& rect) const
561 {
562 return !::EqualRect(this, &rect);
563 }
564
565 void operator +=(POINT point)
566 {
567 ::OffsetRect(this, point.x, point.y);
568 }
569
570 void operator +=(SIZE size)
571 {
572 ::OffsetRect(this, size.cx, size.cy);
573 }
574
575 void operator +=(LPCRECT lpRect)
576 {
577 InflateRect(lpRect);
578 }
579
580 void operator -=(POINT point)
581 {
582 ::OffsetRect(this, -point.x, -point.y);
583 }
584
585 void operator -=(SIZE size)
586 {
587 ::OffsetRect(this, -size.cx, -size.cy);
588 }
589
590 void operator -=(LPCRECT lpRect)
591 {
592 DeflateRect(lpRect);
593 }
594
595 void operator &=(const RECT& rect)
596 {
597 ::IntersectRect(this, this, &rect);
598 }
599
600 void operator |=(const RECT& rect)
601 {
602 ::UnionRect(this, this, &rect);
603 }
604
605 // Operators returning CRect values
606 CRect operator +(POINT pt) const
607 {
608 CRect rect(*this);
609 ::OffsetRect(&rect, pt.x, pt.y);
610 return rect;
611 }
612
613 CRect operator -(POINT pt) const
614 {
615 CRect rect(*this);
616 ::OffsetRect(&rect, -pt.x, -pt.y);
617 return rect;
618 }
619
620 CRect operator +(LPCRECT lpRect) const
621 {
622 CRect rect(this);
623 rect.InflateRect(lpRect);
624 return rect;
625 }
626
627 CRect operator +(SIZE size) const
628 {
629 CRect rect(*this);
630 ::OffsetRect(&rect, size.cx, size.cy);
631 return rect;
632 }
633
634 CRect operator -(SIZE size) const
635 {
636 CRect rect(*this);
637 ::OffsetRect(&rect, -size.cx, -size.cy);
638 return rect;
639 }
640
641 CRect operator -(LPCRECT lpRect) const
642 {
643 CRect rect(this);
644 rect.DeflateRect(lpRect);
645 return rect;
646 }
647
648 CRect operator &(const RECT& rect2) const
649 {
650 CRect rect;
651 ::IntersectRect(&rect, this, &rect2);
652 return rect;
653 }
654
655 CRect operator |(const RECT& rect2) const
656 {
657 CRect rect;
658 ::UnionRect(&rect, this, &rect2);
659 return rect;
660 }
661
662 CRect MulDiv(int nMultiplier, int nDivisor) const
663 {
664 return CRect(
665 ::MulDiv(left, nMultiplier, nDivisor),
666 ::MulDiv(top, nMultiplier, nDivisor),
667 ::MulDiv(right, nMultiplier, nDivisor),
668 ::MulDiv(bottom, nMultiplier, nDivisor));
669 }
670 };
671
672
673 // CSize implementation
674
675 inline CPoint CSize::operator +(POINT point) const
676 { return CPoint(cx + point.x, cy + point.y); }
677
678 inline CPoint CSize::operator -(POINT point) const
679 { return CPoint(cx - point.x, cy - point.y); }
680
681 inline CRect CSize::operator +(const RECT* lpRect) const
682 { return CRect(lpRect) + *this; }
683
684 inline CRect CSize::operator -(const RECT* lpRect) const
685 { return CRect(lpRect) - *this; }
686
687
688 // CPoint implementation
689
690 inline CRect CPoint::operator +(const RECT* lpRect) const
691 { return CRect(lpRect) + *this; }
692
693 inline CRect CPoint::operator -(const RECT* lpRect) const
694 { return CRect(lpRect) - *this; }
695
696 #endif // !_WTL_NO_WTYPES
697
698
699 // WTL::CSize or ATL::CSize scalar operators
700
701 #if !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__))
702
703 template <class Num>
704 inline CSize operator *(SIZE s, Num n)
705 {
706 return CSize((int)(s.cx * n), (int)(s.cy * n));
707 };
708
709 template <class Num>
710 inline void operator *=(SIZE & s, Num n)
711 {
712 s = s * n;
713 };
714
715 template <class Num>
716 inline CSize operator /(SIZE s, Num n)
717 {
718 return CSize((int)(s.cx / n), (int)(s.cy / n));
719 };
720
721 template <class Num>
722 inline void operator /=(SIZE & s, Num n)
723 {
724 s = s / n;
725 };
726
727 #endif // !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__))
728
729
730 ///////////////////////////////////////////////////////////////////////////////
731 // CString - String class
732
733 #ifndef _WTL_NO_CSTRING
734
735 struct CStringData
736 {
737 long nRefs; // reference count
738 int nDataLength;
739 int nAllocLength;
740 // TCHAR data[nAllocLength]
741
742 TCHAR* data()
743 { return (TCHAR*)(this + 1); }
744 };
745
746 // Globals
747
748 // For an empty string, m_pchData will point here
749 // (note: avoids special case of checking for NULL m_pchData)
750 // empty string data (and locked)
751 _declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 };
752 _declspec(selectany) CStringData* _atltmpDataNil = (CStringData*)&rgInitData;
753 _declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringData));
754
755
756 class CString
757 {
758 public:
759 // Constructors
760 CString()
761 {
762 Init();
763 }
764
765 CString(const CString& stringSrc)
766 {
767 ATLASSERT(stringSrc.GetData()->nRefs != 0);
768 if (stringSrc.GetData()->nRefs >= 0)
769 {
770 ATLASSERT(stringSrc.GetData() != _atltmpDataNil);
771 m_pchData = stringSrc.m_pchData;
772 InterlockedIncrement(&GetData()->nRefs);
773 }
774 else
775 {
776 Init();
777 *this = stringSrc.m_pchData;
778 }
779 }
780
781 CString(TCHAR ch, int nRepeat = 1)
782 {
783 ATLASSERT(!_istlead(ch)); // can't create a lead byte string
784 Init();
785 if (nRepeat >= 1)
786 {
787 if(AllocBuffer(nRepeat))
788 {
789 #ifdef _UNICODE
790 for (int i = 0; i < nRepeat; i++)
791 m_pchData[i] = ch;
792 #else
793 memset(m_pchData, ch, nRepeat);
794 #endif
795 }
796 }
797 }
798
799 CString(LPCTSTR lpsz)
800 {
801 Init();
802 if (lpsz != NULL && HIWORD(lpsz) == NULL)
803 {
804 UINT nID = LOWORD((DWORD_PTR)lpsz);
805 if (!LoadString(nID))
806 ATLTRACE2(atlTraceUI, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID);
807 }
808 else
809 {
810 int nLen = SafeStrlen(lpsz);
811 if (nLen != 0)
812 {
813 if(AllocBuffer(nLen))
814 SecureHelper::memcpy_x(m_pchData, (nLen + 1) * sizeof(TCHAR), lpsz, nLen * sizeof(TCHAR));
815 }
816 }
817 }
818
819 #ifdef _UNICODE
820 CString(LPCSTR lpsz)
821 {
822 Init();
823 #if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
824 int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0;
825 #else
826 int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0;
827 #endif
828 if (nSrcLen != 0)
829 {
830 if(AllocBuffer(nSrcLen))
831 {
832 _mbstowcsz(m_pchData, lpsz, nSrcLen + 1);
833 ReleaseBuffer();
834 }
835 }
836 }
837 #else // !_UNICODE
838 CString(LPCWSTR lpsz)
839 {
840 Init();
841 int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0;
842 if (nSrcLen != 0)
843 {
844 if(AllocBuffer(nSrcLen * 2))
845 {
846 _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1);
847 ReleaseBuffer();
848 }
849 }
850 }
851 #endif // !_UNICODE
852
853 CString(LPCTSTR lpch, int nLength)
854 {
855 Init();
856 if (nLength != 0)
857 {
858 if(AllocBuffer(nLength))
859 SecureHelper::memcpy_x(m_pchData, (nLength + 1) * sizeof(TCHAR), lpch, nLength * sizeof(TCHAR));
860 }
861 }
862
863 #ifdef _UNICODE
864 CString(LPCSTR lpsz, int nLength)
865 {
866 Init();
867 if (nLength != 0)
868 {
869 if(AllocBuffer(nLength))
870 {
871 int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength + 1);
872 ReleaseBuffer((n >= 0) ? n : -1);
873 }
874 }
875 }
876 #else // !_UNICODE
877 CString(LPCWSTR lpsz, int nLength)
878 {
879 Init();
880 if (nLength != 0)
881 {
882 if(((nLength * 2) > nLength) && AllocBuffer(nLength * 2))
883 {
884 int n = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nLength, m_pchData, (nLength * 2) + 1, NULL, NULL);
885 ReleaseBuffer((n >= 0) ? n : -1);
886 }
887 }
888 }
889 #endif // !_UNICODE
890
891 CString(const unsigned char* lpsz)
892 {
893 Init();
894 *this = (LPCSTR)lpsz;
895 }
896
897 // Attributes & Operations
898 int GetLength() const // as an array of characters
899 {
900 return GetData()->nDataLength;
901 }
902
903 BOOL IsEmpty() const
904 {
905 return GetData()->nDataLength == 0;
906 }
907
908 void Empty() // free up the data
909 {
910 if (GetData()->nDataLength == 0)
911 return;
912
913 if (GetData()->nRefs >= 0)
914 Release();
915 else
916 *this = _T("");
917
918 ATLASSERT(GetData()->nDataLength == 0);
919 ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
920 }
921
922 TCHAR GetAt(int nIndex) const // 0 based
923 {
924 ATLASSERT(nIndex >= 0);
925 ATLASSERT(nIndex < GetData()->nDataLength);
926 return m_pchData[nIndex];
927 }
928
929 TCHAR operator [](int nIndex) const // same as GetAt
930 {
931 // same as GetAt
932 ATLASSERT(nIndex >= 0);
933 ATLASSERT(nIndex < GetData()->nDataLength);
934 return m_pchData[nIndex];
935 }
936
937 void SetAt(int nIndex, TCHAR ch)
938 {
939 ATLASSERT(nIndex >= 0);
940 ATLASSERT(nIndex < GetData()->nDataLength);
941
942 CopyBeforeWrite();
943 m_pchData[nIndex] = ch;
944 }
945
946 operator LPCTSTR() const // as a C string
947 {
948 return m_pchData;
949 }
950
951 // overloaded assignment
952 CString& operator =(const CString& stringSrc)
953 {
954 if (m_pchData != stringSrc.m_pchData)
955 {
956 if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0)
957 {
958 // actual copy necessary since one of the strings is locked
959 AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
960 }
961 else
962 {
963 // can just copy references around
964 Release();
965 ATLASSERT(stringSrc.GetData() != _atltmpDataNil);
966 m_pchData = stringSrc.m_pchData;
967 InterlockedIncrement(&GetData()->nRefs);
968 }
969 }
970 return *this;
971 }
972
973 CString& operator =(TCHAR ch)
974 {
975 ATLASSERT(!_istlead(ch)); // can't set single lead byte
976 AssignCopy(1, &ch);
977 return *this;
978 }
979
980 #ifdef _UNICODE
981 CString& operator =(char ch)
982 {
983 *this = (TCHAR)ch;
984 return *this;
985 }
986 #endif
987
988 CString& operator =(LPCTSTR lpsz)
989 {
990 ATLASSERT(lpsz == NULL || _IsValidString(lpsz));
991 AssignCopy(SafeStrlen(lpsz), lpsz);
992 return *this;
993 }
994
995 #ifdef _UNICODE
996 CString& operator =(LPCSTR lpsz)
997 {
998 #if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
999 int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0;
1000 #else
1001 int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0;
1002 #endif
1003 if(AllocBeforeWrite(nSrcLen))
1004 {
1005 _mbstowcsz(m_pchData, lpsz, nSrcLen + 1);
1006 ReleaseBuffer();
1007 }
1008 return *this;
1009 }
1010 #else // !_UNICODE
1011 CString& operator =(LPCWSTR lpsz)
1012 {
1013 int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0;
1014 if(AllocBeforeWrite(nSrcLen * 2))
1015 {
1016 _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1);
1017 ReleaseBuffer();
1018 }
1019 return *this;
1020 }
1021 #endif // !_UNICODE
1022
1023 CString& operator =(const unsigned char* lpsz)
1024 {
1025 *this = (LPCSTR)lpsz;
1026 return *this;
1027 }
1028
1029 // string concatenation
1030 CString& operator +=(const CString& string)
1031 {
1032 ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
1033 return *this;
1034 }
1035
1036 CString& operator +=(TCHAR ch)
1037 {
1038 ConcatInPlace(1, &ch);
1039 return *this;
1040 }
1041
1042 #ifdef _UNICODE
1043 CString& operator +=(char ch)
1044 {
1045 *this += (TCHAR)ch;
1046 return *this;
1047 }
1048 #endif
1049
1050 CString& operator +=(LPCTSTR lpsz)
1051 {
1052 ATLASSERT(lpsz == NULL || _IsValidString(lpsz));
1053 ConcatInPlace(SafeStrlen(lpsz), lpsz);
1054 return *this;
1055 }
1056
1057 friend CString __stdcall operator +(const CString& string1, const CString& string2);
1058 friend CString __stdcall operator +(const CString& string, TCHAR ch);
1059 friend CString __stdcall operator +(TCHAR ch, const CString& string);
1060 #ifdef _UNICODE
1061 friend CString __stdcall operator +(const CString& string, char ch);
1062 friend CString __stdcall operator +(char ch, const CString& string);
1063 #endif
1064 friend CString __stdcall operator +(const CString& string, LPCTSTR lpsz);
1065 friend CString __stdcall operator +(LPCTSTR lpsz, const CString& string);
1066
1067 // string comparison
1068 int Compare(LPCTSTR lpsz) const // straight character (MBCS/Unicode aware)
1069 {
1070 return _cstrcmp(m_pchData, lpsz);
1071 }
1072
1073 int CompareNoCase(LPCTSTR lpsz) const // ignore case (MBCS/Unicode aware)
1074 {
1075 return _cstrcmpi(m_pchData, lpsz);
1076 }
1077
1078 #ifndef _WIN32_WCE
1079 // CString::Collate is often slower than Compare but is MBSC/Unicode
1080 // aware as well as locale-sensitive with respect to sort order.
1081 int Collate(LPCTSTR lpsz) const // NLS aware
1082 {
1083 return _cstrcoll(m_pchData, lpsz);
1084 }
1085
1086 int CollateNoCase(LPCTSTR lpsz) const // ignore case
1087 {
1088 return _cstrcolli(m_pchData, lpsz);
1089 }
1090 #endif // !_WIN32_WCE
1091
1092 // simple sub-string extraction
1093 CString Mid(int nFirst, int nCount) const
1094 {
1095 // out-of-bounds requests return sensible things
1096 if (nFirst < 0)
1097 nFirst = 0;
1098 if (nCount < 0)
1099 nCount = 0;
1100
1101 if (nFirst + nCount > GetData()->nDataLength)
1102 nCount = GetData()->nDataLength - nFirst;
1103 if (nFirst > GetData()->nDataLength)
1104 nCount = 0;
1105
1106 CString dest;
1107 AllocCopy(dest, nCount, nFirst, 0);
1108 return dest;
1109 }
1110
1111 CString Mid(int nFirst) const
1112 {
1113 return Mid(nFirst, GetData()->nDataLength - nFirst);
1114 }
1115
1116 CString Left(int nCount) const
1117 {
1118 if (nCount < 0)
1119 nCount = 0;
1120 else if (nCount > GetData()->nDataLength)
1121 nCount = GetData()->nDataLength;
1122
1123 CString dest;
1124 AllocCopy(dest, nCount, 0, 0);
1125 return dest;
1126 }
1127
1128 CString Right(int nCount) const
1129 {
1130 if (nCount < 0)
1131 nCount = 0;
1132 else if (nCount > GetData()->nDataLength)
1133 nCount = GetData()->nDataLength;
1134
1135 CString dest;
1136 AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
1137 return dest;
1138 }
1139
1140 CString SpanIncluding(LPCTSTR lpszCharSet) const // strspn equivalent
1141 {
1142 ATLASSERT(_IsValidString(lpszCharSet));
1143 return Left(_cstrspn(m_pchData, lpszCharSet));
1144 }
1145
1146 CString SpanExcluding(LPCTSTR lpszCharSet) const // strcspn equivalent
1147 {
1148 ATLASSERT(_IsValidString(lpszCharSet));
1149 return Left(_cstrcspn(m_pchData, lpszCharSet));
1150 }
1151
1152 // upper/lower/reverse conversion
1153 void MakeUpper()
1154 {
1155 CopyBeforeWrite();
1156 CharUpper(m_pchData);
1157 }
1158
1159 void MakeLower()
1160 {
1161 CopyBeforeWrite();
1162 CharLower(m_pchData);
1163 }
1164
1165 void MakeReverse()
1166 {
1167 CopyBeforeWrite();
1168 _cstrrev(m_pchData);
1169 }
1170
1171 // trimming whitespace (either side)
1172 void TrimRight()
1173 {
1174 CopyBeforeWrite();
1175
1176 // find beginning of trailing spaces by starting at beginning (DBCS aware)
1177 LPTSTR lpsz = m_pchData;
1178 LPTSTR lpszLast = NULL;
1179 while (*lpsz != _T('\0'))
1180 {
1181 if (_cstrisspace(*lpsz))
1182 {
1183 if (lpszLast == NULL)
1184 lpszLast = lpsz;
1185 }
1186 else
1187 {
1188 lpszLast = NULL;
1189 }
1190 lpsz = ::CharNext(lpsz);
1191 }
1192
1193 if (lpszLast != NULL)
1194 {
1195 // truncate at trailing space start
1196 *lpszLast = _T('\0');
1197 GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
1198 }
1199 }
1200
1201 void TrimLeft()
1202 {
1203 CopyBeforeWrite();
1204
1205 // find first non-space character
1206 LPCTSTR lpsz = m_pchData;
1207 while (_cstrisspace(*lpsz))
1208 lpsz = ::CharNext(lpsz);
1209
1210 // fix up data and length
1211 int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
1212 SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR));
1213 GetData()->nDataLength = nDataLength;
1214 }
1215
1216 // remove continuous occurrences of chTarget starting from right
1217 void TrimRight(TCHAR chTarget)
1218 {
1219 // find beginning of trailing matches
1220 // by starting at beginning (DBCS aware)
1221
1222 CopyBeforeWrite();
1223 LPTSTR lpsz = m_pchData;
1224 LPTSTR lpszLast = NULL;
1225
1226 while (*lpsz != _T('\0'))
1227 {
1228 if (*lpsz == chTarget)
1229 {
1230 if (lpszLast == NULL)
1231 lpszLast = lpsz;
1232 }
1233 else
1234 lpszLast = NULL;
1235 lpsz = ::CharNext(lpsz);
1236 }
1237
1238 if (lpszLast != NULL)
1239 {
1240 // truncate at left-most matching character
1241 *lpszLast = _T('\0');
1242 GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
1243 }
1244 }
1245
1246 // remove continuous occcurrences of characters in passed string, starting from right
1247 void TrimRight(LPCTSTR lpszTargetList)
1248 {
1249 // find beginning of trailing matches by starting at beginning (DBCS aware)
1250
1251 CopyBeforeWrite();
1252 LPTSTR lpsz = m_pchData;
1253 LPTSTR lpszLast = NULL;
1254
1255 while (*lpsz != _T('\0'))
1256 {
1257 TCHAR* pNext = ::CharNext(lpsz);
1258 if(pNext > lpsz + 1)
1259 {
1260 if (_cstrchr_db(lpszTargetList, *lpsz, *(lpsz + 1)) != NULL)
1261 {
1262 if (lpszLast == NULL)
1263 lpszLast = lpsz;
1264 }
1265 else
1266 {
1267 lpszLast = NULL;
1268 }
1269 }
1270 else
1271 {
1272 if (_cstrchr(lpszTargetList, *lpsz) != NULL)
1273 {
1274 if (lpszLast == NULL)
1275 lpszLast = lpsz;
1276 }
1277 else
1278 {
1279 lpszLast = NULL;
1280 }
1281 }
1282
1283 lpsz = pNext;
1284 }
1285
1286 if (lpszLast != NULL)
1287 {
1288 // truncate at left-most matching character
1289 *lpszLast = _T('\0');
1290 GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
1291 }
1292 }
1293
1294 // remove continuous occurrences of chTarget starting from left
1295 void TrimLeft(TCHAR chTarget)
1296 {
1297 // find first non-matching character
1298
1299 CopyBeforeWrite();
1300 LPCTSTR lpsz = m_pchData;
1301
1302 while (chTarget == *lpsz)
1303 lpsz = ::CharNext(lpsz);
1304
1305 if (lpsz != m_pchData)
1306 {
1307 // fix up data and length
1308 int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
1309 SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR));
1310 GetData()->nDataLength = nDataLength;
1311 }
1312 }
1313
1314 // remove continuous occcurrences of characters in passed string, starting from left
1315 void TrimLeft(LPCTSTR lpszTargets)
1316 {
1317 // if we're not trimming anything, we're not doing any work
1318 if (SafeStrlen(lpszTargets) == 0)
1319 return;
1320
1321 CopyBeforeWrite();
1322 LPCTSTR lpsz = m_pchData;
1323
1324 while (*lpsz != _T('\0'))
1325 {
1326 TCHAR* pNext = ::CharNext(lpsz);
1327 if(pNext > lpsz + 1)
1328 {
1329 if (_cstrchr_db(lpszTargets, *lpsz, *(lpsz + 1)) == NULL)
1330 break;
1331 }
1332 else
1333 {
1334 if (_cstrchr(lpszTargets, *lpsz) == NULL)
1335 break;
1336 }
1337 lpsz = pNext;
1338 }
1339
1340 if (lpsz != m_pchData)
1341 {
1342 // fix up data and length
1343 int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
1344 SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR));
1345 GetData()->nDataLength = nDataLength;
1346 }
1347 }
1348
1349 // advanced manipulation
1350 // replace occurrences of chOld with chNew
1351 int Replace(TCHAR chOld, TCHAR chNew)
1352 {
1353 int nCount = 0;
1354
1355 // short-circuit the nop case
1356 if (chOld != chNew)
1357 {
1358 // otherwise modify each character that matches in the string
1359 CopyBeforeWrite();
1360 LPTSTR psz = m_pchData;
1361 LPTSTR pszEnd = psz + GetData()->nDataLength;
1362 while (psz < pszEnd)
1363 {
1364 // replace instances of the specified character only
1365 if (*psz == chOld)
1366 {
1367 *psz = chNew;
1368 nCount++;
1369 }
1370 psz = ::CharNext(psz);
1371 }
1372 }
1373 return nCount;
1374 }
1375
1376 // replace occurrences of substring lpszOld with lpszNew;
1377 // empty lpszNew removes instances of lpszOld
1378 int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew)
1379 {
1380 // can't have empty or NULL lpszOld
1381
1382 int nSourceLen = SafeStrlen(lpszOld);
1383 if (nSourceLen == 0)
1384 return 0;
1385 int nReplacementLen = SafeStrlen(lpszNew);
1386
1387 // loop once to figure out the size of the result string
1388 int nCount = 0;
1389 LPTSTR lpszStart = m_pchData;
1390 LPTSTR lpszEnd = m_pchData + GetData()->nDataLength;
1391 LPTSTR lpszTarget = NULL;
1392 while (lpszStart < lpszEnd)
1393 {
1394 while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL)
1395 {
1396 nCount++;
1397 lpszStart = lpszTarget + nSourceLen;
1398 }
1399 lpszStart += lstrlen(lpszStart) + 1;
1400 }
1401
1402 // if any changes were made, make them
1403 if (nCount > 0)
1404 {
1405 CopyBeforeWrite();
1406
1407 // if the buffer is too small, just allocate a new buffer (slow but sure)
1408 int nOldLength = GetData()->nDataLength;
1409 int nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount;
1410 if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1)
1411 {
1412 CStringData* pOldData = GetData();
1413 LPTSTR pstr = m_pchData;
1414 if(!AllocBuffer(nNewLength))
1415 return -1;
1416 SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, pOldData->nDataLength * sizeof(TCHAR));
1417 CString::Release(pOldData);
1418 }
1419 // else, we just do it in-place
1420 lpszStart = m_pchData;
1421 lpszEnd = m_pchData + GetData()->nDataLength;
1422
1423 // loop again to actually do the work
1424 while (lpszStart < lpszEnd)
1425 {
1426 while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL)
1427 {
1428 int nBalance = nOldLength - ((int)(DWORD_PTR)(lpszTarget - m_pchData) + nSourceLen);
1429 int cchBuffLen = GetData()->nAllocLength - (int)(DWORD_PTR)(lpszTarget - m_pchData);
1430 SecureHelper::memmove_x(lpszTarget + nReplacementLen, (cchBuffLen - nReplacementLen + 1) * sizeof(TCHAR), lpszTarget + nSourceLen, nBalance * sizeof(TCHAR));
1431 SecureHelper::memcpy_x(lpszTarget, (cchBuffLen + 1) * sizeof(TCHAR), lpszNew, nReplacementLen * sizeof(TCHAR));
1432 lpszStart = lpszTarget + nReplacementLen;
1433 lpszStart[nBalance] = _T('\0');
1434 nOldLength += (nReplacementLen - nSourceLen);
1435 }
1436 lpszStart += lstrlen(lpszStart) + 1;
1437 }
1438 ATLASSERT(m_pchData[nNewLength] == _T('\0'));
1439 GetData()->nDataLength = nNewLength;
1440 }
1441
1442 return nCount;
1443 }
1444
1445 // remove occurrences of chRemove
1446 int Remove(TCHAR chRemove)
1447 {
1448 CopyBeforeWrite();
1449
1450 LPTSTR pstrSource = m_pchData;
1451 LPTSTR pstrDest = m_pchData;
1452 LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;
1453
1454 while (pstrSource < pstrEnd)
1455 {
1456 if (*pstrSource != chRemove)
1457 {
1458 *pstrDest = *pstrSource;
1459 pstrDest = ::CharNext(pstrDest);
1460 }
1461 pstrSource = ::CharNext(pstrSource);
1462 }
1463 *pstrDest = _T('\0');
1464 int nCount = (int)(DWORD_PTR)(pstrSource - pstrDest);
1465 GetData()->nDataLength -= nCount;
1466
1467 return nCount;
1468 }
1469
1470 // insert character at zero-based index; concatenates if index is past end of string
1471 int Insert(int nIndex, TCHAR ch)
1472 {
1473 CopyBeforeWrite();
1474
1475 if (nIndex < 0)
1476 nIndex = 0;
1477
1478 int nNewLength = GetData()->nDataLength;
1479 if (nIndex > nNewLength)
1480 nIndex = nNewLength;
1481 nNewLength++;
1482
1483 if (GetData()->nAllocLength < nNewLength)
1484 {
1485 CStringData* pOldData = GetData();
1486 LPTSTR pstr = m_pchData;
1487 if(!AllocBuffer(nNewLength))
1488 return -1;
1489 SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR));
1490 CString::Release(pOldData);
1491 }
1492
1493 // move existing bytes down
1494 SecureHelper::memmove_x(m_pchData + nIndex + 1, (GetData()->nAllocLength - nIndex) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex) * sizeof(TCHAR));
1495 m_pchData[nIndex] = ch;
1496 GetData()->nDataLength = nNewLength;
1497
1498 return nNewLength;
1499 }
1500
1501 // insert substring at zero-based index; concatenates if index is past end of string
1502 int Insert(int nIndex, LPCTSTR pstr)
1503 {
1504 if (nIndex < 0)
1505 nIndex = 0;
1506
1507 int nInsertLength = SafeStrlen(pstr);
1508 int nNewLength = GetData()->nDataLength;
1509 if (nInsertLength > 0)
1510 {
1511 CopyBeforeWrite();
1512 if (nIndex > nNewLength)
1513 nIndex = nNewLength;
1514 nNewLength += nInsertLength;
1515
1516 if (GetData()->nAllocLength < nNewLength)
1517 {
1518 CStringData* pOldData = GetData();
1519 LPTSTR pstrTmp = m_pchData;
1520 if(!AllocBuffer(nNewLength))
1521 return -1;
1522 SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstrTmp, (pOldData->nDataLength + 1) * sizeof(TCHAR));
1523 CString::Release(pOldData);
1524 }
1525
1526 // move existing bytes down
1527 SecureHelper::memmove_x(m_pchData + nIndex + nInsertLength, (GetData()->nAllocLength + 1 - nIndex - nInsertLength) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(TCHAR));
1528 SecureHelper::memcpy_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), pstr, nInsertLength * sizeof(TCHAR));
1529 GetData()->nDataLength = nNewLength;
1530 }
1531
1532 return nNewLength;
1533 }
1534
1535 // delete nCount characters starting at zero-based index
1536 int Delete(int nIndex, int nCount = 1)
1537 {
1538 if (nIndex < 0)
1539 nIndex = 0;
1540 int nLength = GetData()->nDataLength;
1541 if (nCount > 0 && nIndex < nLength)
1542 {
1543 if((nIndex + nCount) > nLength)
1544 nCount = nLength - nIndex;
1545 CopyBeforeWrite();
1546 int nBytesToCopy = nLength - (nIndex + nCount) + 1;
1547
1548 SecureHelper::memmove_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));
1549 nLength -= nCount;
1550 GetData()->nDataLength = nLength;
1551 }
1552
1553 return nLength;
1554 }
1555
1556 // searching (return starting index, or -1 if not found)
1557 // look for a single character match
1558 int Find(TCHAR ch) const // like "C" strchr
1559 {
1560 return Find(ch, 0);
1561 }
1562
1563 int ReverseFind(TCHAR ch) const
1564 {
1565 // find last single character
1566 LPCTSTR lpsz = _cstrrchr(m_pchData, (_TUCHAR)ch);
1567
1568 // return -1 if not found, distance from beginning otherwise
1569 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
1570 }
1571
1572 int Find(TCHAR ch, int nStart) const // starting at index
1573 {
1574 int nLength = GetData()->nDataLength;
1575 if (nStart < 0 || nStart >= nLength)
1576 return -1;
1577
1578 // find first single character
1579 LPCTSTR lpsz = _cstrchr(m_pchData + nStart, (_TUCHAR)ch);
1580
1581 // return -1 if not found and index otherwise
1582 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
1583 }
1584
1585 int FindOneOf(LPCTSTR lpszCharSet) const
1586 {
1587 ATLASSERT(_IsValidString(lpszCharSet));
1588 LPCTSTR lpsz = _cstrpbrk(m_pchData, lpszCharSet);
1589 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
1590 }
1591
1592 // look for a specific sub-string
1593 // find a sub-string (like strstr)
1594 int Find(LPCTSTR lpszSub) const // like "C" strstr
1595 {
1596 return Find(lpszSub, 0);
1597 }
1598
1599 int Find(LPCTSTR lpszSub, int nStart) const // starting at index
1600 {
1601 ATLASSERT(_IsValidString(lpszSub));
1602
1603 int nLength = GetData()->nDataLength;
1604 if (nStart < 0 || nStart > nLength)
1605 return -1;
1606
1607 // find first matching substring
1608 LPCTSTR lpsz = _cstrstr(m_pchData + nStart, lpszSub);
1609
1610 // return -1 for not found, distance from beginning otherwise
1611 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
1612 }
1613
1614 // Concatentation for non strings
1615 CString& Append(int n)
1616 {
1617 const int cchBuff = 12;
1618 TCHAR szBuffer[cchBuff] = { 0 };
1619 SecureHelper::wsprintf_x(szBuffer, cchBuff, _T("%d"), n);
1620 ConcatInPlace(SafeStrlen(szBuffer), szBuffer);
1621 return *this;
1622 }
1623
1624 // simple formatting
1625 // formatting (using wsprintf style formatting)
1626 BOOL __cdecl Format(LPCTSTR lpszFormat, ...)
1627 {
1628 ATLASSERT(_IsValidString(lpszFormat));
1629
1630 va_list argList;
1631 va_start(argList, lpszFormat);
1632 BOOL bRet = FormatV(lpszFormat, argList);
1633 va_end(argList);
1634 return bRet;
1635 }
1636
1637 BOOL __cdecl Format(UINT nFormatID, ...)
1638 {
1639 CString strFormat;
1640 BOOL bRet = strFormat.LoadString(nFormatID);
1641 ATLASSERT(bRet != 0);
1642
1643 va_list argList;
1644 va_start(argList, nFormatID);
1645 bRet = FormatV(strFormat, argList);
1646 va_end(argList);
1647 return bRet;
1648 }
1649
1650 BOOL FormatV(LPCTSTR lpszFormat, va_list argList)
1651 {
1652 ATLASSERT(_IsValidString(lpszFormat));
1653
1654 enum _FormatModifiers
1655 {
1656 FORCE_ANSI = 0x10000,
1657 FORCE_UNICODE = 0x20000,
1658 FORCE_INT64 = 0x40000
1659 };
1660
1661 va_list argListSave = argList;
1662
1663 // make a guess at the maximum length of the resulting string
1664 int nMaxLen = 0;
1665 for (LPCTSTR lpsz = lpszFormat; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz))
1666 {
1667 // handle '%' character, but watch out for '%%'
1668 if (*lpsz != _T('%') || *(lpsz = ::CharNext(lpsz)) == _T('%'))
1669 {
1670 nMaxLen += (int)(::CharNext(lpsz) - lpsz);
1671 continue;
1672 }
1673
1674 int nItemLen = 0;
1675
1676 // handle '%' character with format
1677 int nWidth = 0;
1678 for (; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz))
1679 {
1680 // check for valid flags
1681 if (*lpsz == _T('#'))
1682 nMaxLen += 2; // for '0x'
1683 else if (*lpsz == _T('*'))
1684 nWidth = va_arg(argList, int);
1685 else if (*lpsz == _T('-') || *lpsz == _T('+') || *lpsz == _T('0') || *lpsz == _T(' '))
1686 ;
1687 else // hit non-flag character
1688 break;
1689 }
1690 // get width and skip it
1691 if (nWidth == 0)
1692 {
1693 // width indicated by
1694 nWidth = _cstrtoi(lpsz);
1695 for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz))
1696 ;
1697 }
1698 ATLASSERT(nWidth >= 0);
1699
1700 int nPrecision = 0;
1701 if (*lpsz == _T('.'))
1702 {
1703 // skip past '.' separator (width.precision)
1704 lpsz = ::CharNext(lpsz);
1705
1706 // get precision and skip it
1707 if (*lpsz == _T('*'))
1708 {
1709 nPrecision = va_arg(argList, int);
1710 lpsz = ::CharNext(lpsz);
1711 }
1712 else
1713 {
1714 nPrecision = _cstrtoi(lpsz);
1715 for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz))
1716 ;
1717 }
1718 ATLASSERT(nPrecision >= 0);
1719 }
1720
1721 // should be on type modifier or specifier
1722 int nModifier = 0;
1723 if(lpsz[0] == _T('I'))
1724 {
1725 if((lpsz[1] == _T('6')) && (lpsz[2] == _T('4')))
1726 {
1727 lpsz += 3;
1728 nModifier = FORCE_INT64;
1729 }
1730 else if((lpsz[1] == _T('3')) && (lpsz[2] == _T('2')))
1731 {
1732 lpsz += 3;
1733 }
1734 else
1735 {
1736 lpsz++;
1737 if(sizeof(size_t) == 8)
1738 nModifier = FORCE_INT64;
1739 }
1740 }
1741 else
1742 {
1743 switch (*lpsz)
1744 {
1745 // modifiers that affect size
1746 case _T('h'):
1747 nModifier = FORCE_ANSI;
1748 lpsz = ::CharNext(lpsz);
1749 break;
1750 case _T('l'):
1751 nModifier = FORCE_UNICODE;
1752 lpsz = ::CharNext(lpsz);
1753 break;
1754
1755 // modifiers that do not affect size
1756 case _T('F'):
1757 case _T('N'):
1758 case _T('L'):
1759 lpsz = ::CharNext(lpsz);
1760 break;
1761 }
1762 }
1763
1764 // now should be on specifier
1765 switch (*lpsz | nModifier)
1766 {
1767 // single characters
1768 case _T('c'):
1769 case _T('C'):
1770 nItemLen = 2;
1771 va_arg(argList, TCHAR);
1772 break;
1773 case _T('c') | FORCE_ANSI:
1774 case _T('C') | FORCE_ANSI:
1775 nItemLen = 2;
1776 va_arg(argList, char);
1777 break;
1778 case _T('c') | FORCE_UNICODE:
1779 case _T('C') | FORCE_UNICODE:
1780 nItemLen = 2;
1781 va_arg(argList, WCHAR);
1782 break;
1783
1784 // strings
1785 case _T('s'):
1786 {
1787 LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
1788 if (pstrNextArg == NULL)
1789 {
1790 nItemLen = 6; // "(null)"
1791 }
1792 else
1793 {
1794 nItemLen = lstrlen(pstrNextArg);
1795 nItemLen = __max(1, nItemLen);
1796 }
1797 break;
1798 }
1799
1800 case _T('S'):
1801 {
1802 #ifndef _UNICODE
1803 LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
1804 if (pstrNextArg == NULL)
1805 {
1806 nItemLen = 6; // "(null)"
1807 }
1808 else
1809 {
1810 nItemLen = (int)wcslen(pstrNextArg);
1811 nItemLen = __max(1, nItemLen);
1812 }
1813 #else // _UNICODE
1814 LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
1815 if (pstrNextArg == NULL)
1816 {
1817 nItemLen = 6; // "(null)"
1818 }
1819 else
1820 {
1821 #if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
1822 nItemLen = ATL::lstrlenA(pstrNextArg);
1823 #else
1824 nItemLen = lstrlenA(pstrNextArg);
1825 #endif
1826 nItemLen = __max(1, nItemLen);
1827 }
1828 #endif // _UNICODE
1829 break;
1830 }
1831
1832 case _T('s') | FORCE_ANSI:
1833 case _T('S') | FORCE_ANSI:
1834 {
1835 LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
1836 if (pstrNextArg == NULL)
1837 {
1838 nItemLen = 6; // "(null)"
1839 }
1840 else
1841 {
1842 #if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800)
1843 nItemLen = ATL::lstrlenA(pstrNextArg);
1844 #else
1845 nItemLen = lstrlenA(pstrNextArg);
1846 #endif
1847 nItemLen = __max(1, nItemLen);
1848 }
1849 break;
1850 }
1851
1852 case _T('s') | FORCE_UNICODE:
1853 case _T('S') | FORCE_UNICODE:
1854 {
1855 LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
1856 if (pstrNextArg == NULL)
1857 {
1858 nItemLen = 6; // "(null)"
1859 }
1860 else
1861 {
1862 nItemLen = (int)wcslen(pstrNextArg);
1863 nItemLen = __max(1, nItemLen);
1864 }
1865 break;
1866 }
1867 }
1868
1869 // adjust nItemLen for strings
1870 if (nItemLen != 0)
1871 {
1872 nItemLen = __max(nItemLen, nWidth);
1873 if (nPrecision != 0)
1874 nItemLen = __min(nItemLen, nPrecision);
1875 }
1876 else
1877 {
1878 switch (*lpsz)
1879 {
1880 // integers
1881 case _T('d'):
1882 case _T('i'):
1883 case _T('u'):
1884 case _T('x'):
1885 case _T('X'):
1886 case _T('o'):
1887 if (nModifier & FORCE_INT64)
1888 va_arg(argList, __int64);
1889 else
1890 va_arg(argList, int);
1891 nItemLen = 32;
1892 nItemLen = __max(nItemLen, nWidth + nPrecision);
1893 break;
1894
1895 #ifndef _ATL_USE_CSTRING_FLOAT
1896 case _T('e'):
1897 case _T('E'):
1898 case _T('f'):
1899 case _T('g'):
1900 case _T('G'):
1901 ATLASSERT(!"Floating point (%%e, %%E, %%f, %%g, and %%G) is not supported by the WTL::CString class.");
1902 #ifndef _DEBUG
1903 ::OutputDebugString(_T("Floating point (%%e, %%f, %%g, and %%G) is not supported by the WTL::CString class."));
1904 #ifndef _WIN32_WCE
1905 ::DebugBreak();
1906 #else // CE specific
1907 DebugBreak();
1908 #endif // _WIN32_WCE
1909 #endif // !_DEBUG
1910 break;
1911 #else // _ATL_USE_CSTRING_FLOAT
1912 case _T('e'):
1913 case _T('E'):
1914 case _T('g'):
1915 case _T('G'):
1916 va_arg(argList, double);
1917 nItemLen = 128;
1918 nItemLen = __max(nItemLen, nWidth + nPrecision);
1919 break;
1920 case _T('f'):
1921 {
1922 double f = va_arg(argList, double);
1923 // 312 == strlen("-1+(309 zeroes).")
1924 // 309 zeroes == max precision of a double
1925 // 6 == adjustment in case precision is not specified,
1926 // which means that the precision defaults to 6
1927 int cchLen = __max(nWidth, 312 + nPrecision + 6);
1928 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
1929 LPTSTR pszTemp = buff.Allocate(cchLen);
1930 if(pszTemp != NULL)
1931 {
1932 SecureHelper::sprintf_x(pszTemp, cchLen, _T("%*.*f"), nWidth, nPrecision + 6, f);
1933 nItemLen = (int)_tcslen(pszTemp);
1934 }
1935 else
1936 {
1937 nItemLen = cchLen;
1938 }
1939 }
1940 break;
1941 #endif // _ATL_USE_CSTRING_FLOAT
1942
1943 case _T('p'):
1944 va_arg(argList, void*);
1945 nItemLen = 32;
1946 nItemLen = __max(nItemLen, nWidth + nPrecision);
1947 break;
1948
1949 // no output
1950 case _T('n'):
1951 va_arg(argList, int*);
1952 break;
1953
1954 default:
1955 ATLASSERT(FALSE); // unknown formatting option
1956 }
1957 }
1958
1959 // adjust nMaxLen for output nItemLen
1960 nMaxLen += nItemLen;
1961 }
1962
1963 if(GetBuffer(nMaxLen) == NULL)
1964 return FALSE;
1965 #ifndef _ATL_USE_CSTRING_FLOAT
1966 int nRet = SecureHelper::wvsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave);
1967 #else // _ATL_USE_CSTRING_FLOAT
1968 int nRet = SecureHelper::vsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave);
1969 #endif // _ATL_USE_CSTRING_FLOAT
1970 nRet; // ref
1971 ATLASSERT(nRet <= GetAllocLength());
1972 ReleaseBuffer();
1973
1974 va_end(argListSave);
1975 return TRUE;
1976 }
1977
1978 // formatting for localization (uses FormatMessage API)
1979 // formatting (using FormatMessage style formatting)
1980 BOOL __cdecl FormatMessage(LPCTSTR lpszFormat, ...)
1981 {
1982 // format message into temporary buffer lpszTemp
1983 va_list argList;
1984 va_start(argList, lpszFormat);
1985 LPTSTR lpszTemp = NULL;
1986 BOOL bRet = TRUE;
1987
1988 if ((::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
1989 lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0) || (lpszTemp == NULL))
1990 bRet = FALSE;
1991
1992 // assign lpszTemp into the resulting string and free the temporary
1993 *this = lpszTemp;
1994 LocalFree(lpszTemp);
1995 va_end(argList);
1996 return bRet;
1997 }
1998
1999 BOOL __cdecl FormatMessage(UINT nFormatID, ...)
2000 {
2001 // get format string from string table
2002 CString strFormat;
2003 BOOL bRetTmp = strFormat.LoadString(nFormatID);
2004 bRetTmp; // ref
2005 ATLASSERT(bRetTmp != 0);
2006
2007 // format message into temporary buffer lpszTemp
2008 va_list argList;
2009 va_start(argList, nFormatID);
2010 LPTSTR lpszTemp = NULL;
2011 BOOL bRet = TRUE;
2012
2013 if ((::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
2014 strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0) || (lpszTemp == NULL))
2015 bRet = FALSE;
2016
2017 // assign lpszTemp into the resulting string and free lpszTemp
2018 *this = lpszTemp;
2019 LocalFree(lpszTemp);
2020 va_end(argList);
2021 return bRet;
2022 }
2023
2024 // Windows support
2025 BOOL LoadString(UINT nID) // load from string resource (255 chars max.)
2026 {
2027 #ifdef _UNICODE
2028 const int CHAR_FUDGE = 1; // one TCHAR unused is good enough
2029 #else
2030 const int CHAR_FUDGE = 2; // two BYTES unused for case of DBC last char
2031 #endif
2032
2033 // try fixed buffer first (to avoid wasting space in the heap)
2034 TCHAR szTemp[256] = { 0 };
2035 int nCount = sizeof(szTemp) / sizeof(szTemp[0]);
2036 int nLen = _LoadString(nID, szTemp, nCount);
2037 if (nCount - nLen > CHAR_FUDGE)
2038 {
2039 *this = szTemp;
2040 return (nLen > 0);
2041 }
2042
2043 // try buffer size of 512, then larger size until entire string is retrieved
2044 int nSize = 256;
2045 do
2046 {
2047 nSize += 256;
2048 LPTSTR lpstr = GetBuffer(nSize - 1);
2049 if(lpstr == NULL)
2050 {
2051 nLen = 0;
2052 break;
2053 }
2054 nLen = _LoadString(nID, lpstr, nSize);
2055 } while (nSize - nLen <= CHAR_FUDGE);
2056 ReleaseBuffer();
2057
2058 return (nLen > 0);
2059 }
2060
2061 #ifndef _UNICODE
2062 // ANSI <-> OEM support (convert string in place)
2063 void AnsiToOem()
2064 {
2065 CopyBeforeWrite();
2066 ::AnsiToOem(m_pchData, m_pchData);
2067 }
2068
2069 void OemToAnsi()
2070 {
2071 CopyBeforeWrite();
2072 ::OemToAnsi(m_pchData, m_pchData);
2073 }
2074 #endif
2075
2076 #ifndef _ATL_NO_COM
2077 // OLE BSTR support (use for OLE automation)
2078 BSTR AllocSysString() const
2079 {
2080 #if defined(_UNICODE) || defined(OLE2ANSI)
2081 BSTR bstr = ::SysAllocStringLen(m_pchData, GetData()->nDataLength);
2082 #else
2083 int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData,
2084 GetData()->nDataLength, NULL, NULL);
2085 BSTR bstr = ::SysAllocStringLen(NULL, nLen);
2086 if(bstr != NULL)
2087 MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, bstr, nLen);
2088 #endif
2089 return bstr;
2090 }
2091
2092 BSTR SetSysString(BSTR* pbstr) const
2093 {
2094 #if defined(_UNICODE) || defined(OLE2ANSI)
2095 ::SysReAllocStringLen(pbstr, m_pchData, GetData()->nDataLength);
2096 #else
2097 int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData,
2098 GetData()->nDataLength, NULL, NULL);
2099 if(::SysReAllocStringLen(pbstr, NULL, nLen))
2100 MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, *pbstr, nLen);
2101 #endif
2102 ATLASSERT(*pbstr != NULL);
2103 return *pbstr;
2104 }
2105 #endif // !_ATL_NO_COM
2106
2107 // Access to string implementation buffer as "C" character array
2108 LPTSTR GetBuffer(int nMinBufLength)
2109 {
2110 ATLASSERT(nMinBufLength >= 0);
2111
2112 if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
2113 {
2114 // we have to grow the buffer
2115 CStringData* pOldData = GetData();
2116 int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
2117 if (nMinBufLength < nOldLen)
2118 nMinBufLength = nOldLen;
2119
2120 if(!AllocBuffer(nMinBufLength))
2121 return NULL;
2122
2123 SecureHelper::memcpy_x(m_pchData, (nMinBufLength + 1) * sizeof(TCHAR), pOldData->data(), (nOldLen + 1) * sizeof(TCHAR));
2124 GetData()->nDataLength = nOldLen;
2125 CString::Release(pOldData);
2126 }
2127 ATLASSERT(GetData()->nRefs <= 1);
2128
2129 // return a pointer to the character storage for this string
2130 ATLASSERT(m_pchData != NULL);
2131 return m_pchData;
2132 }
2133
2134 void ReleaseBuffer(int nNewLength = -1)
2135 {
2136 CopyBeforeWrite(); // just in case GetBuffer was not called
2137
2138 if (nNewLength == -1)
2139 nNewLength = lstrlen(m_pchData); // zero terminated
2140
2141 ATLASSERT(nNewLength <= GetData()->nAllocLength);
2142 GetData()->nDataLength = nNewLength;
2143 m_pchData[nNewLength] = _T('\0');
2144 }
2145
2146 LPTSTR GetBufferSetLength(int nNewLength)
2147 {
2148 ATLASSERT(nNewLength >= 0);
2149
2150 if(GetBuffer(nNewLength) == NULL)
2151 return NULL;
2152
2153 GetData()->nDataLength = nNewLength;
2154 m_pchData[nNewLength] = _T('\0');
2155 return m_pchData;
2156 }
2157
2158 void FreeExtra()
2159 {
2160 ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
2161 if (GetData()->nDataLength != GetData()->nAllocLength)
2162 {
2163 CStringData* pOldData = GetData();
2164 if(AllocBuffer(GetData()->nDataLength))
2165 {
2166 SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pOldData->data(), pOldData->nDataLength * sizeof(TCHAR));
2167 ATLASSERT(m_pchData[GetData()->nDataLength] == _T('\0'));
2168 CString::Release(pOldData);
2169 }
2170 }
2171 ATLASSERT(GetData() != NULL);
2172 }
2173
2174 // Use LockBuffer/UnlockBuffer to turn refcounting off
2175 LPTSTR LockBuffer()
2176 {
2177 LPTSTR lpsz = GetBuffer(0);
2178 if(lpsz != NULL)
2179 GetData()->nRefs = -1;
2180 return lpsz;
2181 }
2182
2183 void UnlockBuffer()
2184 {
2185 ATLASSERT(GetData()->nRefs == -1);
2186 if (GetData() != _atltmpDataNil)
2187 GetData()->nRefs = 1;
2188 }
2189
2190 // Implementation
2191 public:
2192 ~CString() // free any attached data
2193 {
2194 if (GetData() != _atltmpDataNil)
2195 {
2196 if (InterlockedDecrement(&GetData()->nRefs) <= 0)
2197 delete[] (BYTE*)GetData();
2198 }
2199 }
2200
2201 int GetAllocLength() const
2202 {
2203 return GetData()->nAllocLength;
2204 }
2205
2206 static BOOL __stdcall _IsValidString(LPCTSTR lpsz, int /*nLength*/ = -1)
2207 {
2208 return (lpsz != NULL) ? TRUE : FALSE;
2209 }
2210
2211 protected:
2212 LPTSTR m_pchData; // pointer to ref counted string data
2213
2214 // implementation helpers
2215 CStringData* GetData() const
2216 {
2217 ATLASSERT(m_pchData != NULL);
2218 return ((CStringData*)m_pchData) - 1;
2219 }
2220
2221 void Init()
2222 {
2223 m_pchData = _GetEmptyString().m_pchData;
2224 }
2225
2226 BOOL AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
2227 {
2228 // will clone the data attached to this string
2229 // allocating 'nExtraLen' characters
2230 // Places results in uninitialized string 'dest'
2231 // Will copy the part or all of original data to start of new string
2232
2233 BOOL bRet = FALSE;
2234 int nNewLen = nCopyLen + nExtraLen;
2235 if (nNewLen == 0)
2236 {
2237 dest.Init();
2238 bRet = TRUE;
2239 }
2240 else if(nNewLen >= nCopyLen)
2241 {
2242 if(dest.AllocBuffer(nNewLen))
2243 {
2244 SecureHelper::memcpy_x(dest.m_pchData, (nNewLen + 1) * sizeof(TCHAR), m_pchData + nCopyIndex, nCopyLen * sizeof(TCHAR));
2245 bRet = TRUE;
2246 }
2247 }
2248
2249 return bRet;
2250 }
2251
2252 // always allocate one extra character for '\0' termination
2253 // assumes [optimistically] that data length will equal allocation length
2254 BOOL AllocBuffer(int nLen)
2255 {
2256 ATLASSERT(nLen >= 0);
2257 ATLASSERT(nLen <= INT_MAX - 1); // max size (enough room for 1 extra)
2258
2259 if (nLen == 0)
2260 {
2261 Init();
2262 }
2263 else
2264 {
2265 CStringData* pData = NULL;
2266 ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen + 1) * sizeof(TCHAR)]);
2267 if(pData == NULL)
2268 return FALSE;
2269
2270 pData->nRefs = 1;
2271 pData->data()[nLen] = _T('\0');
2272 pData->nDataLength = nLen;
2273 pData->nAllocLength = nLen;
2274 m_pchData = pData->data();
2275 }
2276
2277 return TRUE;
2278 }
2279
2280 // Assignment operators
2281 // All assign a new value to the string
2282 // (a) first see if the buffer is big enough
2283 // (b) if enough room, copy on top of old buffer, set size and type
2284 // (c) otherwise free old string data, and create a new one
2285 //
2286 // All routines return the new string (but as a 'const CString&' so that
2287 // assigning it again will cause a copy, eg: s1 = s2 = "hi there".
2288 //
2289 void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
2290 {
2291 if(AllocBeforeWrite(nSrcLen))
2292 {
2293 SecureHelper::memcpy_x(m_pchData, (nSrcLen + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR));
2294 GetData()->nDataLength = nSrcLen;
2295 m_pchData[nSrcLen] = _T('\0');
2296 }
2297 }
2298
2299 // Concatenation
2300 // NOTE: "operator +" is done as friend functions for simplicity
2301 // There are three variants:
2302 // CString + CString
2303 // and for ? = TCHAR, LPCTSTR
2304 // CString + ?
2305 // ? + CString
2306 BOOL ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data)
2307 {
2308 // -- master concatenation routine
2309 // Concatenate two sources
2310 // -- assume that 'this' is a new CString object
2311
2312 BOOL bRet = TRUE;
2313 int nNewLen = nSrc1Len + nSrc2Len;
2314 if(nNewLen < nSrc1Len || nNewLen < nSrc2Len)
2315 {
2316 bRet = FALSE;
2317 }
2318 else if(nNewLen != 0)
2319 {
2320 bRet = AllocBuffer(nNewLen);
2321 if (bRet)
2322 {
2323 SecureHelper::memcpy_x(m_pchData, (nNewLen + 1) * sizeof(TCHAR), lpszSrc1Data, nSrc1Len * sizeof(TCHAR));
2324 SecureHelper::memcpy_x(m_pchData + nSrc1Len, (nNewLen + 1 - nSrc1Len) * sizeof(TCHAR), lpszSrc2Data, nSrc2Len * sizeof(TCHAR));
2325 }
2326 }
2327 return bRet;
2328 }
2329
2330 void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
2331 {
2332 // -- the main routine for += operators
2333
2334 // concatenating an empty string is a no-op!
2335 if (nSrcLen == 0)
2336 return;
2337
2338 // if the buffer is too small, or we have a width mis-match, just
2339 // allocate a new buffer (slow but sure)
2340 if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
2341 {
2342 // we have to grow the buffer, use the ConcatCopy routine
2343 CStringData* pOldData = GetData();
2344 if (ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData))
2345 {
2346 ATLASSERT(pOldData != NULL);
2347 CString::Release(pOldData);
2348 }
2349 }
2350 else
2351 {
2352 // fast concatenation when buffer big enough
2353 SecureHelper::memcpy_x(m_pchData + GetData()->nDataLength, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR));
2354 GetData()->nDataLength += nSrcLen;
2355 ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
2356 m_pchData[GetData()->nDataLength] = _T('\0');
2357 }
2358 }
2359
2360 void CopyBeforeWrite()
2361 {
2362 if (GetData()->nRefs > 1)
2363 {
2364 CStringData* pData = GetData();
2365 Release();
2366 if(AllocBuffer(pData->nDataLength))
2367 SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR));
2368 }
2369 ATLASSERT(GetData()->nRefs <= 1);
2370 }
2371
2372 BOOL AllocBeforeWrite(int nLen)
2373 {
2374 BOOL bRet = TRUE;
2375 if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
2376 {
2377 Release();
2378 bRet = AllocBuffer(nLen);
2379 }
2380 ATLASSERT(GetData()->nRefs <= 1);
2381 return bRet;
2382 }
2383
2384 void Release()
2385 {
2386 if (GetData() != _atltmpDataNil)
2387 {
2388 ATLASSERT(GetData()->nRefs != 0);
2389 if (InterlockedDecrement(&GetData()->nRefs) <= 0)
2390 delete[] (BYTE*)GetData();
2391 Init();
2392 }
2393 }
2394
2395 static void PASCAL Release(CStringData* pData)
2396 {
2397 if (pData != _atltmpDataNil)
2398 {
2399 ATLASSERT(pData->nRefs != 0);
2400 if (InterlockedDecrement(&pData->nRefs) <= 0)
2401 delete[] (BYTE*)pData;
2402 }
2403 }
2404
2405 static int PASCAL SafeStrlen(LPCTSTR lpsz)
2406 {
2407 return (lpsz == NULL) ? 0 : lstrlen(lpsz);
2408 }
2409
2410 static int __stdcall _LoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
2411 {
2412 #ifdef _DEBUG
2413 // LoadString without annoying warning from the Debug kernel if the
2414 // segment containing the string is not present
2415 if (::FindResource(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE((nID >> 4) + 1), RT_STRING) == NULL)
2416 {
2417 lpszBuf[0] = _T('\0');
2418 return 0; // not found
2419 }
2420 #endif // _DEBUG
2421
2422 int nLen = ::LoadString(ModuleHelper::GetResourceInstance(), nID, lpszBuf, nMaxBuf);
2423 if (nLen == 0)
2424 lpszBuf[0] = _T('\0');
2425
2426 return nLen;
2427 }
2428
2429 static const CString& __stdcall _GetEmptyString()
2430 {
2431 return *(CString*)&_atltmpPchNil;
2432 }
2433
2434 // CString conversion helpers
2435 static int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
2436 {
2437 if (count == 0 && mbstr != NULL)
2438 return 0;
2439
2440 int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1, mbstr, (int)count, NULL, NULL);
2441 ATLASSERT(mbstr == NULL || result <= (int)count);
2442 if ((mbstr != NULL) && (result > 0))
2443 mbstr[result - 1] = 0;
2444 return result;
2445 }
2446
2447 static int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count)
2448 {
2449 if (count == 0 && wcstr != NULL)
2450 return 0;
2451
2452 int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wcstr, (int)count);
2453 ATLASSERT(wcstr == NULL || result <= (int)count);
2454 if ((wcstr != NULL) && (result > 0))
2455 wcstr[result - 1] = 0;
2456 return result;
2457 }
2458
2459 // Helpers to avoid CRT startup code
2460 #ifdef _ATL_MIN_CRT
2461 static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch)
2462 {
2463 // strchr for '\0' should succeed
2464 while (*p != 0)
2465 {
2466 if (*p == ch)
2467 break;
2468 p = ::CharNext(p);
2469 }
2470 return (*p == ch) ? p : NULL;
2471 }
2472
2473 static TCHAR* _cstrrev(TCHAR* pStr)
2474 {
2475 // optimize NULL, zero-length, and single-char case
2476 if ((pStr == NULL) || (pStr[0] == _T('\0')) || (pStr[1] == _T('\0')))
2477 return pStr;
2478
2479 TCHAR* p = pStr;
2480
2481 while (*p != 0)
2482 {
2483 TCHAR* pNext = ::CharNext(p);
2484 if(pNext > p + 1)
2485 {
2486 char p1 = *(char*)p;
2487 *(char*)p = *(char*)(p + 1);
2488 *(char*)(p + 1) = p1;
2489 }
2490 p = pNext;
2491 }
2492
2493 p--;
2494 TCHAR* q = pStr;
2495
2496 while (q < p)
2497 {
2498 TCHAR t = *q;
2499 *q = *p;
2500 *p = t;
2501 q++;
2502 p--;
2503 }
2504 return pStr;
2505 }
2506
2507 static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet)
2508 {
2509 int nLen = lstrlen(pCharSet);
2510 if (nLen == 0)
2511 return (TCHAR*)pStr;
2512
2513 const TCHAR* pRet = NULL;
2514 const TCHAR* pCur = pStr;
2515 while((pCur = _cstrchr(pCur, *pCharSet)) != NULL)
2516 {
2517 if(memcmp(pCur, pCharSet, nLen * sizeof(TCHAR)) == 0)
2518 {
2519 pRet = pCur;
2520 break;
2521 }
2522 pCur = ::CharNext(pCur);
2523 }
2524 return pRet;
2525 }
2526
2527 static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet)
2528 {
2529 int nRet = 0;
2530 const TCHAR* p = pStr;
2531 while (*p != 0)
2532 {
2533 const TCHAR* pNext = ::CharNext(p);
2534 if(pNext > p + 1)
2535 {
2536 if(_cstrchr_db(pCharSet, *p, *(p + 1)) == NULL)
2537 break;
2538 nRet += 2;
2539 }
2540 else
2541 {
2542 if(_cstrchr(pCharSet, *p) == NULL)
2543 break;
2544 nRet++;
2545 }
2546 p = pNext;
2547 }
2548 return nRet;
2549 }
2550
2551 static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet)
2552 {
2553 int nRet = 0;
2554 TCHAR* p = (TCHAR*)pStr;
2555 while (*p != 0)
2556 {
2557 TCHAR* pNext = ::CharNext(p);
2558 if(pNext > p + 1)
2559 {
2560 if(_cstrchr_db(pCharSet, *p, *(p + 1)) != NULL)
2561 break;
2562 nRet += 2;
2563 }
2564 else
2565 {
2566 if(_cstrchr(pCharSet, *p) != NULL)
2567 break;
2568 nRet++;
2569 }
2570 p = pNext;
2571 }
2572 return nRet;
2573 }
2574
2575 static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet)
2576 {
2577 int n = _cstrcspn(p, lpszCharSet);
2578 return (p[n] != 0) ? &p[n] : NULL;
2579 }
2580
2581 static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther)
2582 {
2583 return lstrcmp(pstrOne, pstrOther);
2584 }
2585
2586 static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther)
2587 {
2588 return lstrcmpi(pstrOne, pstrOther);
2589 }
2590
2591 static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther)
2592 {
2593 int nRet = CompareString(GetThreadLocale(), 0, pstrOne, -1, pstrOther, -1);
2594 ATLASSERT(nRet != 0);
2595 return nRet - 2; // convert to strcmp convention
2596 }
2597
2598 static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther)
2599 {
2600 int nRet = CompareString(GetThreadLocale(), NORM_IGNORECASE, pstrOne, -1, pstrOther, -1);
2601 ATLASSERT(nRet != 0);
2602 return nRet - 2; // convert to strcmp convention
2603 }
2604 #else // !_ATL_MIN_CRT
2605 static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch)
2606 {
2607 return _tcschr(p, ch);
2608 }
2609
2610 static TCHAR* _cstrrev(TCHAR* pStr)
2611 {
2612 return _tcsrev(pStr);
2613 }
2614
2615 static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet)
2616 {
2617 return _tcsstr(pStr, pCharSet);
2618 }
2619
2620 static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet)
2621 {
2622 return (int)_tcsspn(pStr, pCharSet);
2623 }
2624
2625 static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet)
2626 {
2627 return (int)_tcscspn(pStr, pCharSet);
2628 }
2629
2630 static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet)
2631 {
2632 return _tcspbrk(p, lpszCharSet);
2633 }
2634
2635 static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther)
2636 {
2637 return _tcscmp(pstrOne, pstrOther);
2638 }
2639
2640 static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther)
2641 {
2642 return _tcsicmp(pstrOne, pstrOther);
2643 }
2644
2645 #ifndef _WIN32_WCE
2646 static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther)
2647 {
2648 return _tcscoll(pstrOne, pstrOther);
2649 }
2650
2651 static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther)
2652 {
2653 return _tcsicoll(pstrOne, pstrOther);
2654 }
2655 #endif // !_WIN32_WCE
2656 #endif // !_ATL_MIN_CRT
2657
2658 static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch)
2659 {
2660 return MinCrtHelper::_strrchr(p, ch);
2661 }
2662
2663 static int _cstrisdigit(TCHAR ch)
2664 {
2665 return MinCrtHelper::_isdigit(ch);
2666 }
2667
2668 static int _cstrisspace(TCHAR ch)
2669 {
2670 return MinCrtHelper::_isspace(ch);
2671 }
2672
2673 static int _cstrtoi(const TCHAR* nptr)
2674 {
2675 return MinCrtHelper::_atoi(nptr);
2676 }
2677
2678 static const TCHAR* _cstrchr_db(const TCHAR* p, TCHAR ch1, TCHAR ch2)
2679 {
2680 const TCHAR* lpsz = NULL;
2681 while (*p != 0)
2682 {
2683 if (*p == ch1 && *(p + 1) == ch2)
2684 {
2685 lpsz = p;
2686 break;
2687 }
2688 p = ::CharNext(p);
2689 }
2690 return lpsz;
2691 }
2692 };
2693
2694
2695 // Compare helpers
2696
2697 inline bool __stdcall operator ==(const CString& s1, const CString& s2)
2698 { return s1.Compare(s2) == 0; }
2699
2700 inline bool __stdcall operator ==(const CString& s1, LPCTSTR s2)
2701 { return s1.Compare(s2) == 0; }
2702
2703 inline bool __stdcall operator ==(LPCTSTR s1, const CString& s2)
2704 { return s2.Compare(s1) == 0; }
2705
2706 inline bool __stdcall operator !=(const CString& s1, const CString& s2)
2707 { return s1.Compare(s2) != 0; }
2708
2709 inline bool __stdcall operator !=(const CString& s1, LPCTSTR s2)
2710 { return s1.Compare(s2) != 0; }
2711
2712 inline bool __stdcall operator !=(LPCTSTR s1, const CString& s2)
2713 { return s2.Compare(s1) != 0; }
2714
2715 inline bool __stdcall operator <(const CString& s1, const CString& s2)
2716 { return s1.Compare(s2) < 0; }
2717
2718 inline bool __stdcall operator <(const CString& s1, LPCTSTR s2)
2719 { return s1.Compare(s2) < 0; }
2720
2721 inline bool __stdcall operator <(LPCTSTR s1, const CString& s2)
2722 { return s2.Compare(s1) > 0; }
2723
2724 inline bool __stdcall operator >(const CString& s1, const CString& s2)
2725 { return s1.Compare(s2) > 0; }
2726
2727 inline bool __stdcall operator >(const CString& s1, LPCTSTR s2)
2728 { return s1.Compare(s2) > 0; }
2729
2730 inline bool __stdcall operator >(LPCTSTR s1, const CString& s2)
2731 { return s2.Compare(s1) < 0; }
2732
2733 inline bool __stdcall operator <=(const CString& s1, const CString& s2)
2734 { return s1.Compare(s2) <= 0; }
2735
2736 inline bool __stdcall operator <=(const CString& s1, LPCTSTR s2)
2737 { return s1.Compare(s2) <= 0; }
2738
2739 inline bool __stdcall operator <=(LPCTSTR s1, const CString& s2)
2740 { return s2.Compare(s1) >= 0; }
2741
2742 inline bool __stdcall operator >=(const CString& s1, const CString& s2)
2743 { return s1.Compare(s2) >= 0; }
2744
2745 inline bool __stdcall operator >=(const CString& s1, LPCTSTR s2)
2746 { return s1.Compare(s2) >= 0; }
2747
2748 inline bool __stdcall operator >=(LPCTSTR s1, const CString& s2)
2749 { return s2.Compare(s1) <= 0; }
2750
2751
2752 // CString "operator +" functions
2753
2754 inline CString __stdcall operator +(const CString& string1, const CString& string2)
2755 {
2756 CString s;
2757 s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData);
2758 return s;
2759 }
2760
2761 inline CString __stdcall operator +(const CString& string, TCHAR ch)
2762 {
2763 CString s;
2764 s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch);
2765 return s;
2766 }
2767
2768 inline CString __stdcall operator +(TCHAR ch, const CString& string)
2769 {
2770 CString s;
2771 s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
2772 return s;
2773 }
2774
2775 #ifdef _UNICODE
2776 inline CString __stdcall operator +(const CString& string, char ch)
2777 {
2778 return string + (TCHAR)ch;
2779 }
2780
2781 inline CString __stdcall operator +(char ch, const CString& string)
2782 {
2783 return (TCHAR)ch + string;
2784 }
2785 #endif // _UNICODE
2786
2787 inline CString __stdcall operator +(const CString& string, LPCTSTR lpsz)
2788 {
2789 ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz));
2790 CString s;
2791 s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz);
2792 return s;
2793 }
2794
2795 inline CString __stdcall operator +(LPCTSTR lpsz, const CString& string)
2796 {
2797 ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz));
2798 CString s;
2799 s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData);
2800 return s;
2801 }
2802
2803 #endif // !_WTL_NO_CSTRING
2804
2805
2806 ///////////////////////////////////////////////////////////////////////////////
2807 // CRecentDocumentList - MRU List Support
2808
2809 #ifndef _WIN32_WCE
2810
2811 #ifndef _WTL_MRUEMPTY_TEXT
2812 #define _WTL_MRUEMPTY_TEXT _T("(empty)")
2813 #endif
2814
2815 // forward declaration
2816 inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen);
2817
2818 template <class T, int t_cchItemLen = MAX_PATH, int t_nFirstID = ID_FILE_MRU_FIRST, int t_nLastID = ID_FILE_MRU_LAST>
2819 class CRecentDocumentListBase
2820 {
2821 public:
2822 // Declarations
2823 struct _DocEntry
2824 {
2825 TCHAR szDocName[t_cchItemLen];
2826 bool operator ==(const _DocEntry& de) const
2827 { return (lstrcmpi(szDocName, de.szDocName) == 0); }
2828 };
2829
2830 enum
2831 {
2832 m_nMaxEntries_Min = 2,
2833 m_nMaxEntries_Max = t_nLastID - t_nFirstID + 1,
2834 m_cchMaxItemLen_Min = 6,
2835 m_cchMaxItemLen_Max = t_cchItemLen,
2836 m_cchItemNameLen = 11
2837 };
2838
2839 // Data members
2840 ATL::CSimpleArray<_DocEntry> m_arrDocs;
2841 int m_nMaxEntries; // default is 4
2842 HMENU m_hMenu;
2843
2844 TCHAR m_szNoEntries[t_cchItemLen];
2845
2846 int m_cchMaxItemLen;
2847
2848 // Constructor
2849 CRecentDocumentListBase() : m_hMenu(NULL), m_nMaxEntries(4), m_cchMaxItemLen(-1)
2850 {
2851 // These ASSERTs verify values of the template arguments
2852 ATLASSERT(t_cchItemLen > m_cchMaxItemLen_Min);
2853 ATLASSERT(m_nMaxEntries_Max > m_nMaxEntries_Min);
2854 }
2855
2856 // Attributes
2857 HMENU GetMenuHandle() const
2858 {
2859 return m_hMenu;
2860 }
2861
2862 void SetMenuHandle(HMENU hMenu)
2863 {
2864 ATLASSERT(hMenu == NULL || ::IsMenu(hMenu));
2865 m_hMenu = hMenu;
2866 if(m_hMenu == NULL || (::GetMenuString(m_hMenu, t_nFirstID, m_szNoEntries, t_cchItemLen, MF_BYCOMMAND) == 0))
2867 {
2868 T* pT = static_cast<T*>(this);
2869 pT; // avoid level 4 warning
2870 SecureHelper::strncpy_x(m_szNoEntries, _countof(m_szNoEntries), pT->GetMRUEmptyText(), _TRUNCATE);
2871 }
2872 }
2873
2874 int GetMaxEntries() const
2875 {
2876 return m_nMaxEntries;
2877 }
2878
2879 void SetMaxEntries(int nMaxEntries)
2880 {
2881 ATLASSERT(nMaxEntries >= m_nMaxEntries_Min && nMaxEntries <= m_nMaxEntries_Max);
2882 if(nMaxEntries < m_nMaxEntries_Min)
2883 nMaxEntries = m_nMaxEntries_Min;
2884 else if(nMaxEntries > m_nMaxEntries_Max)
2885 nMaxEntries = m_nMaxEntries_Max;
2886 m_nMaxEntries = nMaxEntries;
2887 }
2888
2889 int GetMaxItemLength() const
2890 {
2891 return m_cchMaxItemLen;
2892 }
2893
2894 void SetMaxItemLength(int cchMaxLen)
2895 {
2896 ATLASSERT((cchMaxLen >= m_cchMaxItemLen_Min && cchMaxLen <= m_cchMaxItemLen_Max) || cchMaxLen == -1);
2897 if(cchMaxLen != -1)
2898 {
2899 if(cchMaxLen < m_cchMaxItemLen_Min)
2900 cchMaxLen = m_cchMaxItemLen_Min;
2901 else if(cchMaxLen > m_cchMaxItemLen_Max)
2902 cchMaxLen = m_cchMaxItemLen_Max;
2903 }
2904 m_cchMaxItemLen = cchMaxLen;
2905 T* pT = static_cast<T*>(this);
2906 pT->UpdateMenu();
2907 }
2908
2909 // Operations
2910 BOOL AddToList(LPCTSTR lpstrDocName)
2911 {
2912 _DocEntry de;
2913 errno_t nRet = SecureHelper::strncpy_x(de.szDocName, _countof(de.szDocName), lpstrDocName, _TRUNCATE);
2914 if(nRet != 0 && nRet != STRUNCATE)
2915 return FALSE;
2916
2917 for(int i = 0; i < m_arrDocs.GetSize(); i++)
2918 {
2919 if(lstrcmpi(m_arrDocs[i].szDocName, lpstrDocName) == 0)
2920 {
2921 m_arrDocs.RemoveAt(i);
2922 break;
2923 }
2924 }
2925
2926 if(m_arrDocs.GetSize() == m_nMaxEntries)
2927 m_arrDocs.RemoveAt(0);
2928
2929 BOOL bRet = m_arrDocs.Add(de);
2930 if(bRet)
2931 {
2932 T* pT = static_cast<T*>(this);
2933 bRet = pT->UpdateMenu();
2934 }
2935 return bRet;
2936 }
2937
2938 // This function is deprecated because it is not safe.
2939 // Use the version below that accepts the buffer length.
2940 #if (_MSC_VER >= 1300)
2941 __declspec(deprecated)
2942 #endif
2943 BOOL GetFromList(int /*nItemID*/, LPTSTR /*lpstrDocName*/)
2944 {
2945 ATLASSERT(FALSE);
2946 return FALSE;
2947 }
2948
2949 BOOL GetFromList(int nItemID, LPTSTR lpstrDocName, int cchLength)
2950 {
2951 int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
2952 if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
2953 return FALSE;
2954 if(lstrlen(m_arrDocs[nIndex].szDocName) >= cchLength)
2955 return FALSE;
2956 SecureHelper::strcpy_x(lpstrDocName, cchLength, m_arrDocs[nIndex].szDocName);
2957
2958 return TRUE;
2959 }
2960
2961 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
2962 BOOL GetFromList(int nItemID, _CSTRING_NS::CString& strDocName)
2963 {
2964 int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
2965 if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
2966 return FALSE;
2967 strDocName = m_arrDocs[nIndex].szDocName;
2968 return TRUE;
2969 }
2970 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
2971
2972 BOOL RemoveFromList(int nItemID)
2973 {
2974 int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
2975 BOOL bRet = m_arrDocs.RemoveAt(nIndex);
2976 if(bRet)
2977 {
2978 T* pT = static_cast<T*>(this);
2979 bRet = pT->UpdateMenu();
2980 }
2981 return bRet;
2982 }
2983
2984 BOOL MoveToTop(int nItemID)
2985 {
2986 int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1;
2987 if(nIndex < 0 || nIndex >= m_arrDocs.GetSize())
2988 return FALSE;
2989 _DocEntry de;
2990 de = m_arrDocs[nIndex];
2991 m_arrDocs.RemoveAt(nIndex);
2992 BOOL bRet = m_arrDocs.Add(de);
2993 if(bRet)
2994 {
2995 T* pT = static_cast<T*>(this);
2996 bRet = pT->UpdateMenu();
2997 }
2998 return bRet;
2999 }
3000
3001 BOOL ReadFromRegistry(LPCTSTR lpstrRegKey)
3002 {
3003 T* pT = static_cast<T*>(this);
3004 CRegKeyEx rkParent;
3005 CRegKeyEx rk;
3006
3007 LONG lRet = rkParent.Open(HKEY_CURRENT_USER, lpstrRegKey);
3008 if(lRet != ERROR_SUCCESS)
3009 return FALSE;
3010 lRet = rk.Open(rkParent, pT->GetRegKeyName());
3011 if(lRet != ERROR_SUCCESS)
3012 return FALSE;
3013
3014 DWORD dwRet = 0;
3015 lRet = rk.QueryDWORDValue(pT->GetRegCountName(), dwRet);
3016 if(lRet != ERROR_SUCCESS)
3017 return FALSE;
3018 SetMaxEntries(dwRet);
3019
3020 m_arrDocs.RemoveAll();
3021
3022 TCHAR szRetString[t_cchItemLen] = { 0 };
3023 _DocEntry de;
3024
3025 for(int nItem = m_nMaxEntries; nItem > 0; nItem--)
3026 {
3027 TCHAR szBuff[m_cchItemNameLen] = { 0 };
3028 SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem);
3029 ULONG ulCount = t_cchItemLen;
3030 lRet = rk.QueryStringValue(szBuff, szRetString, &ulCount);
3031 if(lRet == ERROR_SUCCESS)
3032 {
3033 SecureHelper::strcpy_x(de.szDocName, _countof(de.szDocName), szRetString);
3034 m_arrDocs.Add(de);
3035 }
3036 }
3037
3038 rk.Close();
3039 rkParent.Close();
3040
3041 return pT->UpdateMenu();
3042 }
3043
3044 BOOL WriteToRegistry(LPCTSTR lpstrRegKey)
3045 {
3046 T* pT = static_cast<T*>(this);
3047 pT; // avoid level 4 warning
3048 CRegKeyEx rkParent;
3049 CRegKeyEx rk;
3050
3051 LONG lRet = rkParent.Create(HKEY_CURRENT_USER, lpstrRegKey);
3052 if(lRet != ERROR_SUCCESS)
3053 return FALSE;
3054 lRet = rk.Create(rkParent, pT->GetRegKeyName());
3055 if(lRet != ERROR_SUCCESS)
3056 return FALSE;
3057
3058 lRet = rk.SetDWORDValue(pT->GetRegCountName(), m_nMaxEntries);
3059 ATLASSERT(lRet == ERROR_SUCCESS);
3060
3061 // set new values
3062 int nItem;
3063 for(nItem = m_arrDocs.GetSize(); nItem > 0; nItem--)
3064 {
3065 TCHAR szBuff[m_cchItemNameLen] = { 0 };
3066 SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem);
3067 TCHAR szDocName[t_cchItemLen] = { 0 };
3068 GetFromList(t_nFirstID + nItem - 1, szDocName, t_cchItemLen);
3069 lRet = rk.SetStringValue(szBuff, szDocName);
3070 ATLASSERT(lRet == ERROR_SUCCESS);
3071 }
3072
3073 // delete unused keys
3074 for(nItem = m_arrDocs.GetSize() + 1; nItem <= m_nMaxEntries_Max; nItem++)
3075 {
3076 TCHAR szBuff[m_cchItemNameLen] = { 0 };
3077 SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem);
3078 rk.DeleteValue(szBuff);
3079 }
3080
3081 rk.Close();
3082 rkParent.Close();
3083
3084 return TRUE;
3085 }
3086
3087 // Implementation
3088 BOOL UpdateMenu()
3089 {
3090 if(m_hMenu == NULL)
3091 return FALSE;
3092 ATLASSERT(::IsMenu(m_hMenu));
3093
3094 int nItems = ::GetMenuItemCount(m_hMenu);
3095 int nInsertPoint = 0;
3096 for(int i = 0; i < nItems; i++)
3097 {
3098 CMenuItemInfo mi;
3099 mi.fMask = MIIM_ID;
3100 ::GetMenuItemInfo(m_hMenu, i, TRUE, &mi);
3101 if (mi.wID == t_nFirstID)
3102 {
3103 nInsertPoint = i;
3104 break;
3105 }
3106 }
3107
3108 ATLASSERT(nInsertPoint < nItems && "You need a menu item with an ID = t_nFirstID");
3109
3110 for(int j = t_nFirstID; j < (t_nFirstID + m_nMaxEntries); j++)
3111 {
3112 // keep the first one as an insertion point
3113 if (j != t_nFirstID)
3114 ::DeleteMenu(m_hMenu, j, MF_BYCOMMAND);
3115 }
3116
3117 TCHAR szItemText[t_cchItemLen + 6] = { 0 }; // add space for &, 2 digits, and a space
3118 int nSize = m_arrDocs.GetSize();
3119 int nItem = 0;
3120 if(nSize > 0)
3121 {
3122 for(nItem = 0; nItem < nSize; nItem++)
3123 {
3124 if(m_cchMaxItemLen == -1)
3125 {
3126 SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, m_arrDocs[nSize - 1 - nItem].szDocName);
3127 }
3128 else
3129 {
3130 TCHAR szBuff[t_cchItemLen] = { 0 };
3131 T* pT = static_cast<T*>(this);
3132 pT; // avoid level 4 warning
3133 bool bRet = pT->CompactDocumentName(szBuff, m_arrDocs[nSize - 1 - nItem].szDocName, m_cchMaxItemLen);
3134 bRet; // avoid level 4 warning
3135 ATLASSERT(bRet);
3136 SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, szBuff);
3137 }
3138
3139 ::InsertMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION | MF_STRING, t_nFirstID + nItem, szItemText);
3140 }
3141 }
3142 else // empty
3143 {
3144 ::InsertMenu(m_hMenu, nInsertPoint, MF_BYPOSITION | MF_STRING, t_nFirstID, m_szNoEntries);
3145 ::EnableMenuItem(m_hMenu, t_nFirstID, MF_GRAYED);
3146 nItem++;
3147 }
3148 ::DeleteMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION);
3149
3150 return TRUE;
3151 }
3152
3153 // Overrideables
3154 // override to provide a different method of compacting document names
3155 static bool CompactDocumentName(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen)
3156 {
3157 return AtlCompactPath(lpstrOut, lpstrIn, cchLen);
3158 }
3159
3160 static LPCTSTR GetRegKeyName()
3161 {
3162 return _T("Recent Document List");
3163 }
3164
3165 static LPCTSTR GetRegCountName()
3166 {
3167 return _T("DocumentCount");
3168 }
3169
3170 static LPCTSTR GetRegItemName()
3171 {
3172 // Note: This string is a format string used with wsprintf().
3173 // Resulting formatted string must be m_cchItemNameLen or less
3174 // characters long, including the terminating null character.
3175 return _T("Document%i");
3176 }
3177
3178 static LPCTSTR GetMRUEmptyText()
3179 {
3180 return _WTL_MRUEMPTY_TEXT;
3181 }
3182 };
3183
3184 class CRecentDocumentList : public CRecentDocumentListBase<CRecentDocumentList>
3185 {
3186 public:
3187 // nothing here
3188 };
3189
3190 #endif // _WIN32_WCE
3191
3192
3193 ///////////////////////////////////////////////////////////////////////////////
3194 // CFindFile - file search helper class
3195
3196 class CFindFile
3197 {
3198 public:
3199 // Data members
3200 WIN32_FIND_DATA m_fd;
3201 TCHAR m_lpszRoot[MAX_PATH];
3202 TCHAR m_chDirSeparator;
3203 HANDLE m_hFind;
3204 BOOL m_bFound;
3205
3206 // Constructor/destructor
3207 CFindFile() : m_hFind(NULL), m_chDirSeparator(_T('\\')), m_bFound(FALSE)
3208 { }
3209
3210 ~CFindFile()
3211 {
3212 Close();
3213 }
3214
3215 // Attributes
3216 ULONGLONG GetFileSize() const
3217 {
3218 ATLASSERT(m_hFind != NULL);
3219
3220 ULARGE_INTEGER nFileSize = { 0 };
3221
3222 if(m_bFound)
3223 {
3224 nFileSize.LowPart = m_fd.nFileSizeLow;
3225 nFileSize.HighPart = m_fd.nFileSizeHigh;
3226 }
3227 else
3228 {
3229 nFileSize.QuadPart = 0;
3230 }
3231
3232 return nFileSize.QuadPart;
3233 }
3234
3235 BOOL GetFileName(LPTSTR lpstrFileName, int cchLength) const
3236 {
3237 ATLASSERT(m_hFind != NULL);
3238 if(lstrlen(m_fd.cFileName) >= cchLength)
3239 return FALSE;
3240
3241 if(m_bFound)
3242 SecureHelper::strcpy_x(lpstrFileName, cchLength, m_fd.cFileName);
3243
3244 return m_bFound;
3245 }
3246
3247 BOOL GetFilePath(LPTSTR lpstrFilePath, int cchLength) const
3248 {
3249 ATLASSERT(m_hFind != NULL);
3250
3251 int nLen = lstrlen(m_lpszRoot);
3252 #ifndef _WIN32_WCE
3253 ATLASSERT(nLen > 0);
3254 if(nLen == 0)
3255 return FALSE;
3256
3257 bool bAddSep = (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/'));
3258 #else // CE specific
3259 // allow diskless devices (nLen == 0)
3260 bool bAddSep = ((nLen == 0) || (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/')));
3261 #endif // _WIN32_WCE
3262
3263 if((lstrlen(m_lpszRoot) + (bAddSep ? 1 : 0)) >= cchLength)
3264 return FALSE;
3265
3266 SecureHelper::strcpy_x(lpstrFilePath, cchLength, m_lpszRoot);
3267
3268 if(bAddSep)
3269 {
3270 TCHAR szSeparator[2] = { m_chDirSeparator, 0 };
3271 SecureHelper::strcat_x(lpstrFilePath, cchLength, szSeparator);
3272 }
3273
3274 SecureHelper::strcat_x(lpstrFilePath, cchLength, m_fd.cFileName);
3275
3276 return TRUE;
3277 }
3278
3279 #ifndef _WIN32_WCE
3280 BOOL GetFileTitle(LPTSTR lpstrFileTitle, int cchLength) const
3281 {
3282 ATLASSERT(m_hFind != NULL);
3283
3284 TCHAR szBuff[MAX_PATH] = { 0 };
3285 if(!GetFileName(szBuff, MAX_PATH))
3286 return FALSE;
3287
3288 if(lstrlen(szBuff) >= cchLength || cchLength < 1)
3289 return FALSE;
3290
3291 // find the last dot
3292 LPTSTR pstrDot = MinCrtHelper::_strrchr(szBuff, _T('.'));
3293 if(pstrDot != NULL)
3294 *pstrDot = 0;
3295
3296 SecureHelper::strcpy_x(lpstrFileTitle, cchLength, szBuff);
3297
3298 return TRUE;
3299 }
3300 #endif // !_WIN32_WCE
3301
3302 BOOL GetFileURL(LPTSTR lpstrFileURL, int cchLength) const
3303 {
3304 ATLASSERT(m_hFind != NULL);
3305
3306 TCHAR szBuff[MAX_PATH] = { 0 };
3307 if(!GetFilePath(szBuff, MAX_PATH))
3308 return FALSE;
3309 LPCTSTR lpstrFileURLPrefix = _T("file://");
3310 if(lstrlen(szBuff) + lstrlen(lpstrFileURLPrefix) >= cchLength)
3311 return FALSE;
3312 SecureHelper::strcpy_x(lpstrFileURL, cchLength, lpstrFileURLPrefix);
3313 SecureHelper::strcat_x(lpstrFileURL, cchLength, szBuff);
3314
3315 return TRUE;
3316 }
3317
3318 BOOL GetRoot(LPTSTR lpstrRoot, int cchLength) const
3319 {
3320 ATLASSERT(m_hFind != NULL);
3321 if(lstrlen(m_lpszRoot) >= cchLength)
3322 return FALSE;
3323
3324 SecureHelper::strcpy_x(lpstrRoot, cchLength, m_lpszRoot);
3325
3326 return TRUE;
3327 }
3328
3329 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
3330 _CSTRING_NS::CString GetFileName() const
3331 {
3332 ATLASSERT(m_hFind != NULL);
3333
3334 _CSTRING_NS::CString ret;
3335
3336 if(m_bFound)
3337 ret = m_fd.cFileName;
3338 return ret;
3339 }
3340
3341 _CSTRING_NS::CString GetFilePath() const
3342 {
3343 ATLASSERT(m_hFind != NULL);
3344
3345 _CSTRING_NS::CString strResult = m_lpszRoot;
3346 int nLen = strResult.GetLength();
3347 #ifndef _WIN32_WCE
3348 ATLASSERT(nLen > 0);
3349 if(nLen == 0)
3350 return strResult;
3351
3352 if((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/')))
3353 #else // CE specific
3354 // allow diskless devices (nLen == 0)
3355 if((nLen == 0) || ((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/'))))
3356 #endif // _WIN32_WCE
3357 strResult += m_chDirSeparator;
3358 strResult += GetFileName();
3359 return strResult;
3360 }
3361
3362 #ifndef _WIN32_WCE
3363 _CSTRING_NS::CString GetFileTitle() const
3364 {
3365 ATLASSERT(m_hFind != NULL);
3366
3367 _CSTRING_NS::CString strResult;
3368 GetFileTitle(strResult.GetBuffer(MAX_PATH), MAX_PATH);
3369 strResult.ReleaseBuffer();
3370
3371 return strResult;
3372 }
3373 #endif // !_WIN32_WCE
3374
3375 _CSTRING_NS::CString GetFileURL() const
3376 {
3377 ATLASSERT(m_hFind != NULL);
3378
3379 _CSTRING_NS::CString strResult("file://");
3380 strResult += GetFilePath();
3381 return strResult;
3382 }
3383
3384 _CSTRING_NS::CString GetRoot() const
3385 {
3386 ATLASSERT(m_hFind != NULL);
3387
3388 _CSTRING_NS::CString str = m_lpszRoot;
3389 return str;
3390 }
3391 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
3392
3393 BOOL GetLastWriteTime(FILETIME* pTimeStamp) const
3394 {
3395 ATLASSERT(m_hFind != NULL);
3396 ATLASSERT(pTimeStamp != NULL);
3397
3398 if(m_bFound && pTimeStamp != NULL)
3399 {
3400 *pTimeStamp = m_fd.ftLastWriteTime;
3401 return TRUE;
3402 }
3403
3404 return FALSE;
3405 }
3406
3407 BOOL GetLastAccessTime(FILETIME* pTimeStamp) const
3408 {
3409 ATLASSERT(m_hFind != NULL);
3410 ATLASSERT(pTimeStamp != NULL);
3411
3412 if(m_bFound && pTimeStamp != NULL)
3413 {
3414 *pTimeStamp = m_fd.ftLastAccessTime;
3415 return TRUE;
3416 }
3417
3418 return FALSE;
3419 }
3420
3421 BOOL GetCreationTime(FILETIME* pTimeStamp) const
3422 {
3423 ATLASSERT(m_hFind != NULL);
3424
3425 if(m_bFound && pTimeStamp != NULL)
3426 {
3427 *pTimeStamp = m_fd.ftCreationTime;
3428 return TRUE;
3429 }
3430
3431 return FALSE;
3432 }
3433
3434 BOOL MatchesMask(DWORD dwMask) const
3435 {
3436 ATLASSERT(m_hFind != NULL);
3437
3438 if(m_bFound)
3439 return ((m_fd.dwFileAttributes & dwMask) != 0);
3440
3441 return FALSE;
3442 }
3443
3444 BOOL IsDots() const
3445 {
3446 ATLASSERT(m_hFind != NULL);
3447
3448 // return TRUE if the file name is "." or ".." and
3449 // the file is a directory
3450
3451 BOOL bResult = FALSE;
3452 if(m_bFound && IsDirectory())
3453 {
3454 if(m_fd.cFileName[0] == _T('.') && (m_fd.cFileName[1] == _T('\0') || (m_fd.cFileName[1] == _T('.') && m_fd.cFileName[2] == _T('\0'))))
3455 bResult = TRUE;
3456 }
3457
3458 return bResult;
3459 }
3460
3461 BOOL IsReadOnly() const
3462 {
3463 return MatchesMask(FILE_ATTRIBUTE_READONLY);
3464 }
3465
3466 BOOL IsDirectory() const
3467 {
3468 return MatchesMask(FILE_ATTRIBUTE_DIRECTORY);
3469 }
3470
3471 BOOL IsCompressed() const
3472 {
3473 return MatchesMask(FILE_ATTRIBUTE_COMPRESSED);
3474 }
3475
3476 BOOL IsSystem() const
3477 {
3478 return MatchesMask(FILE_ATTRIBUTE_SYSTEM);
3479 }
3480
3481 BOOL IsHidden() const
3482 {
3483 return MatchesMask(FILE_ATTRIBUTE_HIDDEN);
3484 }
3485
3486 BOOL IsTemporary() const
3487 {
3488 return MatchesMask(FILE_ATTRIBUTE_TEMPORARY);
3489 }
3490
3491 BOOL IsNormal() const
3492 {
3493 return MatchesMask(FILE_ATTRIBUTE_NORMAL);
3494 }
3495
3496 BOOL IsArchived() const
3497 {
3498 return MatchesMask(FILE_ATTRIBUTE_ARCHIVE);
3499 }
3500
3501 // Operations
3502 BOOL FindFile(LPCTSTR pstrName = NULL)
3503 {
3504 Close();
3505
3506 if(pstrName == NULL)
3507 {
3508 pstrName = _T("*.*");
3509 }
3510 else if(lstrlen(pstrName) >= MAX_PATH)
3511 {
3512 ATLASSERT(FALSE);
3513 return FALSE;
3514 }
3515
3516 SecureHelper::strcpy_x(m_fd.cFileName, _countof(m_fd.cFileName), pstrName);
3517
3518 m_hFind = ::FindFirstFile(pstrName, &m_fd);
3519
3520 if(m_hFind == INVALID_HANDLE_VALUE)
3521 return FALSE;
3522
3523 #ifndef _WIN32_WCE
3524 bool bFullPath = (::GetFullPathName(pstrName, MAX_PATH, m_lpszRoot, NULL) != 0);
3525 #else // CE specific
3526 errno_t nRet = SecureHelper::strncpy_x(m_lpszRoot, _countof(m_lpszRoot), pstrName, _TRUNCATE);
3527 bool bFullPath = (nRet == 0 || nRet == STRUNCATE);
3528 #endif // _WIN32_WCE
3529
3530 // passed name isn't a valid path but was found by the API
3531 ATLASSERT(bFullPath);
3532 if(!bFullPath)
3533 {
3534 Close();
3535 ::SetLastError(ERROR_INVALID_NAME);
3536 return FALSE;
3537 }
3538 else
3539 {
3540 // find the last forward or backward whack
3541 LPTSTR pstrBack = MinCrtHelper::_strrchr(m_lpszRoot, _T('\\'));
3542 LPTSTR pstrFront = MinCrtHelper::_strrchr(m_lpszRoot, _T('/'));
3543
3544 if(pstrFront != NULL || pstrBack != NULL)
3545 {
3546 if(pstrFront == NULL)
3547 pstrFront = m_lpszRoot;
3548 if(pstrBack == NULL)
3549 pstrBack = m_lpszRoot;
3550
3551 // from the start to the last whack is the root
3552
3553 if(pstrFront >= pstrBack)
3554 *pstrFront = _T('\0');
3555 else
3556 *pstrBack = _T('\0');
3557 }
3558 }
3559
3560 m_bFound = TRUE;
3561
3562 return TRUE;
3563 }
3564
3565 BOOL FindNextFile()
3566 {
3567 ATLASSERT(m_hFind != NULL);
3568
3569 if(m_hFind == NULL)
3570 return FALSE;
3571
3572 if(!m_bFound)
3573 return FALSE;
3574
3575 m_bFound = ::FindNextFile(m_hFind, &m_fd);
3576
3577 return m_bFound;
3578 }
3579
3580 void Close()
3581 {
3582 m_bFound = FALSE;
3583
3584 if(m_hFind != NULL && m_hFind != INVALID_HANDLE_VALUE)
3585 {
3586 ::FindClose(m_hFind);
3587 m_hFind = NULL;
3588 }
3589 }
3590 };
3591
3592
3593 ///////////////////////////////////////////////////////////////////////////////
3594 // Global functions for stock GDI objects
3595
3596 inline HPEN AtlGetStockPen(int nPen)
3597 {
3598 #if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE)
3599 ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN);
3600 #else
3601 ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN);
3602 #endif
3603 return (HPEN)::GetStockObject(nPen);
3604 }
3605
3606 inline HBRUSH AtlGetStockBrush(int nBrush)
3607 {
3608 #if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE)
3609 ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH);
3610 #else
3611 ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH);
3612 #endif
3613 return (HBRUSH)::GetStockObject(nBrush);
3614 }
3615
3616 inline HFONT AtlGetStockFont(int nFont)
3617 {
3618 #ifndef _WIN32_WCE
3619 ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT);
3620 #else // CE specific
3621 ATLASSERT(nFont == SYSTEM_FONT);
3622 #endif // _WIN32_WCE
3623 return (HFONT)::GetStockObject(nFont);
3624 }
3625
3626 inline HPALETTE AtlGetStockPalette(int nPalette)
3627 {
3628 ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported
3629 return (HPALETTE)::GetStockObject(nPalette);
3630 }
3631
3632
3633 ///////////////////////////////////////////////////////////////////////////////
3634 // Global function for compacting a path by replacing parts with ellipsis
3635
3636 // helper for multi-byte character sets
3637 inline bool _IsDBCSTrailByte(LPCTSTR lpstr, int nChar)
3638 {
3639 #ifndef _UNICODE
3640 int i = nChar;
3641 for( ; i > 0; i--)
3642 {
3643 if(!::IsDBCSLeadByte(lpstr[i - 1]))
3644 break;
3645 }
3646 return ((nChar > 0) && (((nChar - i) & 1) != 0));
3647 #else // _UNICODE
3648 lpstr; nChar;
3649 return false;
3650 #endif // _UNICODE
3651 }
3652
3653 inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen)
3654 {
3655 ATLASSERT(lpstrOut != NULL);
3656 ATLASSERT(lpstrIn != NULL);
3657 ATLASSERT(cchLen > 0);
3658
3659 LPCTSTR szEllipsis = _T("...");
3660 const int cchEndEllipsis = 3;
3661 const int cchMidEllipsis = 4;
3662
3663 if(lstrlen(lpstrIn) < cchLen)
3664 {
3665 SecureHelper::strcpy_x(lpstrOut, cchLen, lpstrIn);
3666 return true;
3667 }
3668
3669 lpstrOut[0] = 0;
3670
3671 // check if the separator is a slash or a backslash
3672 TCHAR chSlash = _T('\\');
3673 for(LPTSTR lpstr = (LPTSTR)lpstrIn; *lpstr != 0; lpstr = ::CharNext(lpstr))
3674 {
3675 if((*lpstr == _T('/')) || (*lpstr == _T('\\')))
3676 chSlash = *lpstr;
3677 }
3678
3679 // find the filename portion of the path
3680 LPCTSTR lpstrFileName = lpstrIn;
3681 for(LPCTSTR pPath = lpstrIn; *pPath; pPath = ::CharNext(pPath))
3682 {
3683 if((pPath[0] == _T('\\') || pPath[0] == _T(':') || pPath[0] == _T('/'))
3684 && pPath[1] && pPath[1] != _T('\\') && pPath[1] != _T('/'))
3685 lpstrFileName = pPath + 1;
3686 }
3687 int cchFileName = lstrlen(lpstrFileName);
3688
3689 // handle just the filename without a path
3690 if(lpstrFileName == lpstrIn && cchLen > cchEndEllipsis)
3691 {
3692 bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchLen - cchEndEllipsis - 1) == 0);
3693 if(bRet)
3694 {
3695 #ifndef _UNICODE
3696 if(_IsDBCSTrailByte(lpstrIn, cchLen - cchEndEllipsis))
3697 lpstrOut[cchLen - cchEndEllipsis - 1] = 0;
3698 #endif // _UNICODE
3699 SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis);
3700 }
3701 return bRet;
3702 }
3703
3704 // handle just ellipsis
3705 if((cchLen < (cchMidEllipsis + cchEndEllipsis)))
3706 {
3707 for(int i = 0; i < cchLen - 1; i++)
3708 lpstrOut[i] = ((i + 1) == cchMidEllipsis) ? chSlash : _T('.');
3709 lpstrOut[cchLen - 1] = 0;
3710 return true;
3711 }
3712
3713 // calc how much we have to copy
3714 int cchToCopy = cchLen - (cchMidEllipsis + cchFileName) - 1;
3715
3716 if(cchToCopy < 0)
3717 cchToCopy = 0;
3718
3719 #ifndef _UNICODE
3720 if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrIn, cchToCopy))
3721 cchToCopy--;
3722 #endif // _UNICODE
3723
3724 bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchToCopy) == 0);
3725 if(!bRet)
3726 return false;
3727
3728 // add ellipsis
3729 SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis);
3730 TCHAR szSlash[2] = { chSlash, 0 };
3731 SecureHelper::strcat_x(lpstrOut, cchLen, szSlash);
3732
3733 // add filename (and ellipsis, if needed)
3734 if(cchLen > (cchMidEllipsis + cchFileName))
3735 {
3736 SecureHelper::strcat_x(lpstrOut, cchLen, lpstrFileName);
3737 }
3738 else
3739 {
3740 cchToCopy = cchLen - cchMidEllipsis - cchEndEllipsis - 1;
3741 #ifndef _UNICODE
3742 if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrFileName, cchToCopy))
3743 cchToCopy--;
3744 #endif // _UNICODE
3745 bRet = (SecureHelper::strncpy_x(&lpstrOut[cchMidEllipsis], cchLen - cchMidEllipsis, lpstrFileName, cchToCopy) == 0);
3746 if(bRet)
3747 SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis);
3748 }
3749
3750 return bRet;
3751 }
3752
3753 }; // namespace WTL
3754
3755 #endif // __ATLMISC_H__
+0
-1106
src/third_party/wtl/Include/atlprint.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLPRINT_H__
9 #define __ATLPRINT_H__
10
11 #pragma once
12
13 #ifdef _WIN32_WCE
14 #error atlprint.h is not supported on Windows CE
15 #endif
16
17 #ifndef __ATLAPP_H__
18 #error atlprint.h requires atlapp.h to be included first
19 #endif
20
21 #ifndef __ATLWIN_H__
22 #error atlprint.h requires atlwin.h to be included first
23 #endif
24
25
26 ///////////////////////////////////////////////////////////////////////////////
27 // Classes in this file:
28 //
29 // CPrinterInfo<t_nInfo>
30 // CPrinterT<t_bManaged>
31 // CDevModeT<t_bManaged>
32 // CPrinterDC
33 // CPrintJobInfo
34 // CPrintJob
35 // CPrintPreview
36 // CPrintPreviewWindowImpl<T, TBase, TWinTraits>
37 // CPrintPreviewWindow
38 // CZoomPrintPreviewWindowImpl<T, TBase, TWinTraits>
39 // CZoomPrintPreviewWindow
40
41 namespace WTL
42 {
43
44 ///////////////////////////////////////////////////////////////////////////////
45 // CPrinterInfo - This class wraps all of the PRINTER_INFO_* structures
46 // and provided by ::GetPrinter.
47
48 template <unsigned int t_nInfo>
49 class _printer_info
50 {
51 public:
52 typedef void infotype;
53 };
54
55 template <> class _printer_info<1> { public: typedef PRINTER_INFO_1 infotype; };
56 template <> class _printer_info<2> { public: typedef PRINTER_INFO_2 infotype; };
57 template <> class _printer_info<3> { public: typedef PRINTER_INFO_3 infotype; };
58 template <> class _printer_info<4> { public: typedef PRINTER_INFO_4 infotype; };
59 template <> class _printer_info<5> { public: typedef PRINTER_INFO_5 infotype; };
60 template <> class _printer_info<6> { public: typedef PRINTER_INFO_6 infotype; };
61 template <> class _printer_info<7> { public: typedef PRINTER_INFO_7 infotype; };
62 // these are not in the old (vc6.0) headers
63 #ifdef _ATL_USE_NEW_PRINTER_INFO
64 template <> class _printer_info<8> { public: typedef PRINTER_INFO_8 infotype; };
65 template <> class _printer_info<9> { public: typedef PRINTER_INFO_9 infotype; };
66 #endif // _ATL_USE_NEW_PRINTER_INFO
67
68
69 template <unsigned int t_nInfo>
70 class CPrinterInfo
71 {
72 public:
73 // Data members
74 typename _printer_info<t_nInfo>::infotype* m_pi;
75
76 // Constructor/destructor
77 CPrinterInfo() : m_pi(NULL)
78 { }
79
80 CPrinterInfo(HANDLE hPrinter) : m_pi(NULL)
81 {
82 GetPrinterInfo(hPrinter);
83 }
84
85 ~CPrinterInfo()
86 {
87 Cleanup();
88 }
89
90 // Operations
91 bool GetPrinterInfo(HANDLE hPrinter)
92 {
93 Cleanup();
94 return GetPrinterInfoHelper(hPrinter, (BYTE**)&m_pi, t_nInfo);
95 }
96
97 // Implementation
98 void Cleanup()
99 {
100 delete [] (BYTE*)m_pi;
101 m_pi = NULL;
102 }
103
104 static bool GetPrinterInfoHelper(HANDLE hPrinter, BYTE** pi, int nIndex)
105 {
106 ATLASSERT(pi != NULL);
107 DWORD dw = 0;
108 BYTE* pb = NULL;
109 ::GetPrinter(hPrinter, nIndex, NULL, 0, &dw);
110 if (dw > 0)
111 {
112 ATLTRY(pb = new BYTE[dw]);
113 if (pb != NULL)
114 {
115 memset(pb, 0, dw);
116 DWORD dwNew;
117 if (!::GetPrinter(hPrinter, nIndex, pb, dw, &dwNew))
118 {
119 delete [] pb;
120 pb = NULL;
121 }
122 }
123 }
124 *pi = pb;
125 return (pb != NULL);
126 }
127 };
128
129
130 ///////////////////////////////////////////////////////////////////////////////
131 // CPrinter - Wrapper class for a HANDLE to a printer
132
133 template <bool t_bManaged>
134 class CPrinterT
135 {
136 public:
137 // Data members
138 HANDLE m_hPrinter;
139
140 // Constructor/destructor
141 CPrinterT(HANDLE hPrinter = NULL) : m_hPrinter(hPrinter)
142 { }
143
144 ~CPrinterT()
145 {
146 ClosePrinter();
147 }
148
149 // Operations
150 CPrinterT& operator =(HANDLE hPrinter)
151 {
152 if (hPrinter != m_hPrinter)
153 {
154 ClosePrinter();
155 m_hPrinter = hPrinter;
156 }
157 return *this;
158 }
159
160 bool IsNull() const { return (m_hPrinter == NULL); }
161
162 bool OpenPrinter(HANDLE hDevNames, const DEVMODE* pDevMode = NULL)
163 {
164 bool b = false;
165 DEVNAMES* pdn = (DEVNAMES*)::GlobalLock(hDevNames);
166 if (pdn != NULL)
167 {
168 LPTSTR lpszPrinterName = (LPTSTR)pdn + pdn->wDeviceOffset;
169 b = OpenPrinter(lpszPrinterName, pDevMode);
170 ::GlobalUnlock(hDevNames);
171 }
172 return b;
173 }
174
175 bool OpenPrinter(LPCTSTR lpszPrinterName, const DEVMODE* pDevMode = NULL)
176 {
177 ClosePrinter();
178 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
179 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
180
181 return (m_hPrinter != NULL);
182 }
183
184 bool OpenPrinter(LPCTSTR lpszPrinterName, PRINTER_DEFAULTS* pprintdefs)
185 {
186 ClosePrinter();
187 ::OpenPrinter((LPTSTR) lpszPrinterName, &m_hPrinter, pprintdefs);
188 return (m_hPrinter != NULL);
189 }
190
191 bool OpenDefaultPrinter(const DEVMODE* pDevMode = NULL)
192 {
193 ClosePrinter();
194 const int cchBuff = 512;
195 TCHAR buffer[cchBuff] = { 0 };
196 ::GetProfileString(_T("windows"), _T("device"), _T(",,,"), buffer, cchBuff);
197 int nLen = lstrlen(buffer);
198 if (nLen != 0)
199 {
200 LPTSTR lpsz = buffer;
201 while (*lpsz)
202 {
203 if (*lpsz == _T(','))
204 {
205 *lpsz = 0;
206 break;
207 }
208 lpsz = CharNext(lpsz);
209 }
210 PRINTER_DEFAULTS pdefs = { NULL, (DEVMODE*)pDevMode, PRINTER_ACCESS_USE };
211 ::OpenPrinter(buffer, &m_hPrinter, (pDevMode == NULL) ? NULL : &pdefs);
212 }
213 return m_hPrinter != NULL;
214 }
215
216 void ClosePrinter()
217 {
218 if (m_hPrinter != NULL)
219 {
220 if (t_bManaged)
221 ::ClosePrinter(m_hPrinter);
222 m_hPrinter = NULL;
223 }
224 }
225
226 bool PrinterProperties(HWND hWnd = NULL)
227 {
228 if (hWnd == NULL)
229 hWnd = ::GetActiveWindow();
230 return !!::PrinterProperties(hWnd, m_hPrinter);
231 }
232
233 HANDLE CopyToHDEVNAMES() const
234 {
235 HANDLE h = NULL;
236 CPrinterInfo<5> pinfon5;
237 CPrinterInfo<2> pinfon2;
238 LPTSTR lpszPrinterName = NULL;
239 // Some printers fail for PRINTER_INFO_5 in some situations
240 if (pinfon5.GetPrinterInfo(m_hPrinter))
241 lpszPrinterName = pinfon5.m_pi->pPrinterName;
242 else if (pinfon2.GetPrinterInfo(m_hPrinter))
243 lpszPrinterName = pinfon2.m_pi->pPrinterName;
244 if (lpszPrinterName != NULL)
245 {
246 int nLen = sizeof(DEVNAMES) + (lstrlen(lpszPrinterName) + 1) * sizeof(TCHAR);
247 h = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
248 BYTE* pv = (BYTE*)::GlobalLock(h);
249 DEVNAMES* pdev = (DEVNAMES*)pv;
250 if (pv != NULL)
251 {
252 memset(pv, 0, nLen);
253 pdev->wDeviceOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
254 pv = pv + sizeof(DEVNAMES); // now points to end
255 SecureHelper::strcpy_x((LPTSTR)pv, lstrlen(lpszPrinterName) + 1, lpszPrinterName);
256 ::GlobalUnlock(h);
257 }
258 }
259 return h;
260 }
261
262 HDC CreatePrinterDC(const DEVMODE* pdm = NULL) const
263 {
264 CPrinterInfo<5> pinfo5;
265 CPrinterInfo<2> pinfo2;
266 HDC hDC = NULL;
267 LPTSTR lpszPrinterName = NULL;
268 // Some printers fail for PRINTER_INFO_5 in some situations
269 if (pinfo5.GetPrinterInfo(m_hPrinter))
270 lpszPrinterName = pinfo5.m_pi->pPrinterName;
271 else if (pinfo2.GetPrinterInfo(m_hPrinter))
272 lpszPrinterName = pinfo2.m_pi->pPrinterName;
273 if (lpszPrinterName != NULL)
274 hDC = ::CreateDC(NULL, lpszPrinterName, NULL, pdm);
275 return hDC;
276 }
277
278 HDC CreatePrinterIC(const DEVMODE* pdm = NULL) const
279 {
280 CPrinterInfo<5> pinfo5;
281 CPrinterInfo<2> pinfo2;
282 HDC hDC = NULL;
283 LPTSTR lpszPrinterName = NULL;
284 // Some printers fail for PRINTER_INFO_5 in some situations
285 if (pinfo5.GetPrinterInfo(m_hPrinter))
286 lpszPrinterName = pinfo5.m_pi->pPrinterName;
287 else if (pinfo2.GetPrinterInfo(m_hPrinter))
288 lpszPrinterName = pinfo2.m_pi->pPrinterName;
289 if (lpszPrinterName != NULL)
290 hDC = ::CreateIC(NULL, lpszPrinterName, NULL, pdm);
291 return hDC;
292 }
293
294 void Attach(HANDLE hPrinter)
295 {
296 ClosePrinter();
297 m_hPrinter = hPrinter;
298 }
299
300 HANDLE Detach()
301 {
302 HANDLE hPrinter = m_hPrinter;
303 m_hPrinter = NULL;
304 return hPrinter;
305 }
306
307 operator HANDLE() const { return m_hPrinter; }
308 };
309
310 typedef CPrinterT<false> CPrinterHandle;
311 typedef CPrinterT<true> CPrinter;
312
313
314 ///////////////////////////////////////////////////////////////////////////////
315 // CDevMode - Wrapper class for DEVMODE
316
317 template <bool t_bManaged>
318 class CDevModeT
319 {
320 public:
321 // Data members
322 HANDLE m_hDevMode;
323 DEVMODE* m_pDevMode;
324
325 // Constructor/destructor
326 CDevModeT(HANDLE hDevMode = NULL) : m_hDevMode(hDevMode)
327 {
328 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
329 }
330
331 ~CDevModeT()
332 {
333 Cleanup();
334 }
335
336 // Operations
337 CDevModeT<t_bManaged>& operator =(HANDLE hDevMode)
338 {
339 Attach(hDevMode);
340 return *this;
341 }
342
343 void Attach(HANDLE hDevModeNew)
344 {
345 Cleanup();
346 m_hDevMode = hDevModeNew;
347 m_pDevMode = (m_hDevMode != NULL) ? (DEVMODE*)::GlobalLock(m_hDevMode) : NULL;
348 }
349
350 HANDLE Detach()
351 {
352 if (m_hDevMode != NULL)
353 ::GlobalUnlock(m_hDevMode);
354 HANDLE hDevMode = m_hDevMode;
355 m_hDevMode = NULL;
356 return hDevMode;
357 }
358
359 bool IsNull() const { return (m_hDevMode == NULL); }
360
361 bool CopyFromPrinter(HANDLE hPrinter)
362 {
363 CPrinterInfo<2> pinfo;
364 bool b = pinfo.GetPrinterInfo(hPrinter);
365 if (b)
366 b = CopyFromDEVMODE(pinfo.m_pi->pDevMode);
367 return b;
368 }
369
370 bool CopyFromDEVMODE(const DEVMODE* pdm)
371 {
372 if (pdm == NULL)
373 return false;
374 int nSize = pdm->dmSize + pdm->dmDriverExtra;
375 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
376 if (h != NULL)
377 {
378 void* p = ::GlobalLock(h);
379 SecureHelper::memcpy_x(p, nSize, pdm, nSize);
380 ::GlobalUnlock(h);
381 }
382 Attach(h);
383 return (h != NULL);
384 }
385
386 bool CopyFromHDEVMODE(HANDLE hdm)
387 {
388 bool b = false;
389 if (hdm != NULL)
390 {
391 DEVMODE* pdm = (DEVMODE*)::GlobalLock(hdm);
392 b = CopyFromDEVMODE(pdm);
393 ::GlobalUnlock(hdm);
394 }
395 return b;
396 }
397
398 HANDLE CopyToHDEVMODE()
399 {
400 if ((m_hDevMode == NULL) || (m_pDevMode == NULL))
401 return NULL;
402 int nSize = m_pDevMode->dmSize + m_pDevMode->dmDriverExtra;
403 HANDLE h = ::GlobalAlloc(GMEM_MOVEABLE, nSize);
404 if (h != NULL)
405 {
406 void* p = ::GlobalLock(h);
407 SecureHelper::memcpy_x(p, nSize, m_pDevMode, nSize);
408 ::GlobalUnlock(h);
409 }
410 return h;
411 }
412
413 // If this devmode was for another printer, this will create a new devmode
414 // based on the existing devmode, but retargeted at the new printer
415 bool UpdateForNewPrinter(HANDLE hPrinter)
416 {
417 bool bRet = false;
418 LONG nLen = ::DocumentProperties(NULL, hPrinter, NULL, NULL, NULL, 0);
419 CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
420 DEVMODE* pdm = buff.AllocateBytes(nLen);
421 if(pdm != NULL)
422 {
423 memset(pdm, 0, nLen);
424 LONG l = ::DocumentProperties(NULL, hPrinter, NULL, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
425 if (l == IDOK)
426 bRet = CopyFromDEVMODE(pdm);
427 }
428
429 return bRet;
430 }
431
432 bool DocumentProperties(HANDLE hPrinter, HWND hWnd = NULL)
433 {
434 CPrinterInfo<1> pi;
435 pi.GetPrinterInfo(hPrinter);
436 if (hWnd == NULL)
437 hWnd = ::GetActiveWindow();
438
439 bool bRet = false;
440 LONG nLen = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, NULL, NULL, 0);
441 CTempBuffer<DEVMODE, _WTL_STACK_ALLOC_THRESHOLD> buff;
442 DEVMODE* pdm = buff.AllocateBytes(nLen);
443 if(pdm != NULL)
444 {
445 memset(pdm, 0, nLen);
446 LONG l = ::DocumentProperties(hWnd, hPrinter, pi.m_pi->pName, pdm, m_pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT);
447 if (l == IDOK)
448 bRet = CopyFromDEVMODE(pdm);
449 }
450
451 return bRet;
452 }
453
454 operator HANDLE() const { return m_hDevMode; }
455
456 operator DEVMODE*() const { return m_pDevMode; }
457
458 // Implementation
459 void Cleanup()
460 {
461 if (m_hDevMode != NULL)
462 {
463 ::GlobalUnlock(m_hDevMode);
464 if(t_bManaged)
465 ::GlobalFree(m_hDevMode);
466 m_hDevMode = NULL;
467 }
468 }
469 };
470
471 typedef CDevModeT<false> CDevModeHandle;
472 typedef CDevModeT<true> CDevMode;
473
474
475 ///////////////////////////////////////////////////////////////////////////////
476 // CPrinterDC
477
478 class CPrinterDC : public CDC
479 {
480 public:
481 // Constructors/destructor
482 CPrinterDC()
483 {
484 CPrinter printer;
485 printer.OpenDefaultPrinter();
486 Attach(printer.CreatePrinterDC());
487 ATLASSERT(m_hDC != NULL);
488 }
489
490 CPrinterDC(HANDLE hPrinter, const DEVMODE* pdm = NULL)
491 {
492 CPrinterHandle p;
493 p.Attach(hPrinter);
494 Attach(p.CreatePrinterDC(pdm));
495 ATLASSERT(m_hDC != NULL);
496 }
497
498 ~CPrinterDC()
499 {
500 DeleteDC();
501 }
502 };
503
504
505 ///////////////////////////////////////////////////////////////////////////////
506 // CPrintJob - Wraps a set of tasks for a specific printer (StartDoc/EndDoc)
507 // Handles aborting, background printing
508
509 // Defines callbacks used by CPrintJob (not a COM interface)
510 class ATL_NO_VTABLE IPrintJobInfo
511 {
512 public:
513 virtual void BeginPrintJob(HDC hDC) = 0; // allocate handles needed, etc.
514 virtual void EndPrintJob(HDC hDC, bool bAborted) = 0; // free handles, etc.
515 virtual void PrePrintPage(UINT nPage, HDC hDC) = 0;
516 virtual bool PrintPage(UINT nPage, HDC hDC) = 0;
517 virtual void PostPrintPage(UINT nPage, HDC hDC) = 0;
518 // If you want per page devmodes, return the DEVMODE* to use for nPage.
519 // You can optimize by only returning a new DEVMODE* when it is different
520 // from the one for nLastPage, otherwise return NULL.
521 // When nLastPage==0, the current DEVMODE* will be the default passed to
522 // StartPrintJob.
523 // Note: During print preview, nLastPage will always be "0".
524 virtual DEVMODE* GetNewDevModeForPage(UINT nLastPage, UINT nPage) = 0;
525 virtual bool IsValidPage(UINT nPage) = 0;
526 };
527
528 // Provides a default implementatin for IPrintJobInfo
529 // Typically, MI'd into a document or view class
530 class ATL_NO_VTABLE CPrintJobInfo : public IPrintJobInfo
531 {
532 public:
533 virtual void BeginPrintJob(HDC /*hDC*/) // allocate handles needed, etc
534 {
535 }
536
537 virtual void EndPrintJob(HDC /*hDC*/, bool /*bAborted*/) // free handles, etc
538 {
539 }
540
541 virtual void PrePrintPage(UINT /*nPage*/, HDC hDC)
542 {
543 m_nPJState = ::SaveDC(hDC);
544 }
545
546 virtual bool PrintPage(UINT /*nPage*/, HDC /*hDC*/) = 0;
547
548 virtual void PostPrintPage(UINT /*nPage*/, HDC hDC)
549 {
550 RestoreDC(hDC, m_nPJState);
551 }
552
553 virtual DEVMODE* GetNewDevModeForPage(UINT /*nLastPage*/, UINT /*nPage*/)
554 {
555 return NULL;
556 }
557
558 virtual bool IsValidPage(UINT /*nPage*/)
559 {
560 return true;
561 }
562
563 // Implementation - data
564 int m_nPJState;
565 };
566
567
568 class CPrintJob
569 {
570 public:
571 // Data members
572 CPrinterHandle m_printer;
573 IPrintJobInfo* m_pInfo;
574 DEVMODE* m_pDefDevMode;
575 DOCINFO m_docinfo;
576 int m_nJobID;
577 bool m_bCancel;
578 bool m_bComplete;
579 unsigned long m_nStartPage;
580 unsigned long m_nEndPage;
581
582 // Constructor/destructor
583 CPrintJob() : m_nJobID(0), m_bCancel(false), m_bComplete(true)
584 { }
585
586 ~CPrintJob()
587 {
588 ATLASSERT(IsJobComplete()); // premature destruction?
589 }
590
591 // Operations
592 bool IsJobComplete() const
593 {
594 return m_bComplete;
595 }
596
597 bool StartPrintJob(bool bBackground, HANDLE hPrinter, DEVMODE* pDefaultDevMode,
598 IPrintJobInfo* pInfo, LPCTSTR lpszDocName,
599 unsigned long nStartPage, unsigned long nEndPage,
600 bool bPrintToFile = false, LPCTSTR lpstrOutputFile = NULL)
601 {
602 ATLASSERT(m_bComplete); // previous job not done yet?
603 if (pInfo == NULL)
604 return false;
605
606 memset(&m_docinfo, 0, sizeof(m_docinfo));
607 m_docinfo.cbSize = sizeof(m_docinfo);
608 m_docinfo.lpszDocName = lpszDocName;
609 m_pInfo = pInfo;
610 m_nStartPage = nStartPage;
611 m_nEndPage = nEndPage;
612 m_printer.Attach(hPrinter);
613 m_pDefDevMode = pDefaultDevMode;
614 m_bComplete = false;
615
616 if(bPrintToFile)
617 m_docinfo.lpszOutput = (lpstrOutputFile != NULL) ? lpstrOutputFile : _T("FILE:");
618
619 if (!bBackground)
620 {
621 m_bComplete = true;
622 return StartHelper();
623 }
624
625 // Create a thread and return
626 DWORD dwThreadID = 0;
627 #if !defined(_ATL_MIN_CRT) && defined(_MT)
628 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))StartProc, this, 0, (UINT*)&dwThreadID);
629 #else
630 HANDLE hThread = ::CreateThread(NULL, 0, StartProc, (void*)this, 0, &dwThreadID);
631 #endif
632 if (hThread == NULL)
633 return false;
634
635 ::CloseHandle(hThread);
636
637 return true;
638 }
639
640 // Implementation
641 static DWORD WINAPI StartProc(void* p)
642 {
643 CPrintJob* pThis = (CPrintJob*)p;
644 pThis->StartHelper();
645 pThis->m_bComplete = true;
646 return 0;
647 }
648
649 bool StartHelper()
650 {
651 CDC dcPrinter;
652 dcPrinter.Attach(m_printer.CreatePrinterDC(m_pDefDevMode));
653 if (dcPrinter.IsNull())
654 return false;
655
656 m_nJobID = ::StartDoc(dcPrinter, &m_docinfo);
657 if (m_nJobID <= 0)
658 return false;
659
660 m_pInfo->BeginPrintJob(dcPrinter);
661
662 // print all the pages now
663 unsigned long nLastPage = 0;
664 for (unsigned long nPage = m_nStartPage; nPage <= m_nEndPage; nPage++)
665 {
666 if (!m_pInfo->IsValidPage(nPage))
667 break;
668 DEVMODE* pdm = m_pInfo->GetNewDevModeForPage(nLastPage, nPage);
669 if (pdm != NULL)
670 dcPrinter.ResetDC(pdm);
671 dcPrinter.StartPage();
672 m_pInfo->PrePrintPage(nPage, dcPrinter);
673 if (!m_pInfo->PrintPage(nPage, dcPrinter))
674 m_bCancel = true;
675 m_pInfo->PostPrintPage(nPage, dcPrinter);
676 dcPrinter.EndPage();
677 if (m_bCancel)
678 break;
679 nLastPage = nPage;
680 }
681
682 m_pInfo->EndPrintJob(dcPrinter, m_bCancel);
683 if (m_bCancel)
684 ::AbortDoc(dcPrinter);
685 else
686 ::EndDoc(dcPrinter);
687 m_nJobID = 0;
688 return true;
689 }
690
691 // Cancels a print job. Can be called asynchronously.
692 void CancelPrintJob()
693 {
694 m_bCancel = true;
695 }
696 };
697
698
699 ///////////////////////////////////////////////////////////////////////////////
700 // CPrintPreview - Adds print preview support to an existing window
701
702 class CPrintPreview
703 {
704 public:
705 // Data members
706 IPrintJobInfo* m_pInfo;
707 CPrinterHandle m_printer;
708 CEnhMetaFile m_meta;
709 DEVMODE* m_pDefDevMode;
710 DEVMODE* m_pCurDevMode;
711 SIZE m_sizeCurPhysOffset;
712
713 // Constructor
714 CPrintPreview() : m_pInfo(NULL), m_pDefDevMode(NULL), m_pCurDevMode(NULL)
715 {
716 m_sizeCurPhysOffset.cx = 0;
717 m_sizeCurPhysOffset.cy = 0;
718 }
719
720 // Operations
721 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode, IPrintJobInfo* pji)
722 {
723 m_printer.Attach(hPrinter);
724 m_pDefDevMode = pDefaultDevMode;
725 m_pInfo = pji;
726 m_nCurPage = 0;
727 m_pCurDevMode = NULL;
728 }
729
730 void SetEnhMetaFile(HENHMETAFILE hEMF)
731 {
732 m_meta = hEMF;
733 }
734
735 void SetPage(int nPage)
736 {
737 if (!m_pInfo->IsValidPage(nPage))
738 return;
739 m_nCurPage = nPage;
740 m_pCurDevMode = m_pInfo->GetNewDevModeForPage(0, nPage);
741 if (m_pCurDevMode == NULL)
742 m_pCurDevMode = m_pDefDevMode;
743 CDC dcPrinter = m_printer.CreatePrinterDC(m_pCurDevMode);
744
745 int iWidth = dcPrinter.GetDeviceCaps(PHYSICALWIDTH);
746 int iHeight = dcPrinter.GetDeviceCaps(PHYSICALHEIGHT);
747 int nLogx = dcPrinter.GetDeviceCaps(LOGPIXELSX);
748 int nLogy = dcPrinter.GetDeviceCaps(LOGPIXELSY);
749
750 RECT rcMM = { 0, 0, ::MulDiv(iWidth, 2540, nLogx), ::MulDiv(iHeight, 2540, nLogy) };
751
752 m_sizeCurPhysOffset.cx = dcPrinter.GetDeviceCaps(PHYSICALOFFSETX);
753 m_sizeCurPhysOffset.cy = dcPrinter.GetDeviceCaps(PHYSICALOFFSETY);
754
755 CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
756 m_pInfo->PrePrintPage(nPage, dcMeta);
757 m_pInfo->PrintPage(nPage, dcMeta);
758 m_pInfo->PostPrintPage(nPage, dcMeta);
759 m_meta.Attach(dcMeta.Close());
760 }
761
762 void GetPageRect(RECT& rc, LPRECT prc)
763 {
764 int x1 = rc.right-rc.left;
765 int y1 = rc.bottom - rc.top;
766 if ((x1 < 0) || (y1 < 0))
767 return;
768
769 CEnhMetaFileInfo emfinfo(m_meta);
770 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
771
772 // Compute whether we are OK vertically or horizontally
773 int x2 = pmh->szlDevice.cx;
774 int y2 = pmh->szlDevice.cy;
775 int y1p = MulDiv(x1, y2, x2);
776 int x1p = MulDiv(y1, x2, y2);
777 ATLASSERT((x1p <= x1) || (y1p <= y1));
778 if (x1p <= x1)
779 {
780 prc->left = rc.left + (x1 - x1p) / 2;
781 prc->right = prc->left + x1p;
782 prc->top = rc.top;
783 prc->bottom = rc.bottom;
784 }
785 else
786 {
787 prc->left = rc.left;
788 prc->right = rc.right;
789 prc->top = rc.top + (y1 - y1p) / 2;
790 prc->bottom = prc->top + y1p;
791 }
792 }
793
794 // Painting helpers
795 void DoPaint(CDCHandle dc)
796 {
797 // this one is not used
798 }
799
800 void DoPaint(CDCHandle dc, RECT& rc)
801 {
802 CEnhMetaFileInfo emfinfo(m_meta);
803 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
804 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
805 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
806
807 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
808 dc.PlayMetaFile(m_meta, &rc);
809 }
810
811 // Implementation - data
812 int m_nCurPage;
813 };
814
815
816 ///////////////////////////////////////////////////////////////////////////////
817 // CPrintPreviewWindow - Implements a print preview window
818
819 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
820 class ATL_NO_VTABLE CPrintPreviewWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CPrintPreview
821 {
822 public:
823 DECLARE_WND_CLASS_EX(NULL, CS_VREDRAW | CS_HREDRAW, -1)
824
825 enum { m_cxOffset = 10, m_cyOffset = 10 };
826
827 // Constructor
828 CPrintPreviewWindowImpl() : m_nMaxPage(0), m_nMinPage(0)
829 { }
830
831 // Operations
832 void SetPrintPreviewInfo(HANDLE hPrinter, DEVMODE* pDefaultDevMode,
833 IPrintJobInfo* pji, int nMinPage, int nMaxPage)
834 {
835 CPrintPreview::SetPrintPreviewInfo(hPrinter, pDefaultDevMode, pji);
836 m_nMinPage = nMinPage;
837 m_nMaxPage = nMaxPage;
838 }
839
840 bool NextPage()
841 {
842 if (m_nCurPage == m_nMaxPage)
843 return false;
844 SetPage(m_nCurPage + 1);
845 Invalidate();
846 return true;
847 }
848
849 bool PrevPage()
850 {
851 if (m_nCurPage == m_nMinPage)
852 return false;
853 if (m_nCurPage == 0)
854 return false;
855 SetPage(m_nCurPage - 1);
856 Invalidate();
857 return true;
858 }
859
860 // Message map and handlers
861 BEGIN_MSG_MAP(CPrintPreviewWindowImpl)
862 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
863 MESSAGE_HANDLER(WM_PAINT, OnPaint)
864 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
865 END_MSG_MAP()
866
867 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
868 {
869 return 1; // no need for the background
870 }
871
872 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
873 {
874 T* pT = static_cast<T*>(this);
875 RECT rc = { 0 };
876
877 if(wParam != NULL)
878 {
879 pT->DoPrePaint((HDC)wParam, rc);
880 pT->DoPaint((HDC)wParam, rc);
881 }
882 else
883 {
884 CPaintDC dc(m_hWnd);
885 pT->DoPrePaint(dc.m_hDC, rc);
886 pT->DoPaint(dc.m_hDC, rc);
887 }
888
889 return 0;
890 }
891
892 // Painting helper
893 void DoPrePaint(CDCHandle dc, RECT& rc)
894 {
895 RECT rcClient = { 0 };
896 GetClientRect(&rcClient);
897 RECT rcArea = rcClient;
898 T* pT = static_cast<T*>(this);
899 pT; // avoid level 4 warning
900 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
901 if (rcArea.left > rcArea.right)
902 rcArea.right = rcArea.left;
903 if (rcArea.top > rcArea.bottom)
904 rcArea.bottom = rcArea.top;
905 GetPageRect(rcArea, &rc);
906 CRgn rgn1, rgn2;
907 rgn1.CreateRectRgnIndirect(&rc);
908 rgn2.CreateRectRgnIndirect(&rcClient);
909 rgn2.CombineRgn(rgn1, RGN_DIFF);
910 dc.SelectClipRgn(rgn2);
911 dc.FillRect(&rcClient, COLOR_BTNSHADOW);
912 dc.SelectClipRgn(NULL);
913 dc.FillRect(&rc, (HBRUSH)::GetStockObject(WHITE_BRUSH));
914 }
915
916 // Implementation - data
917 int m_nMinPage;
918 int m_nMaxPage;
919 };
920
921
922 class CPrintPreviewWindow : public CPrintPreviewWindowImpl<CPrintPreviewWindow>
923 {
924 public:
925 DECLARE_WND_CLASS_EX(_T("WTL_PrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
926 };
927
928
929 ///////////////////////////////////////////////////////////////////////////////
930 // CZoomPrintPreviewWindowImpl - Implements print preview window with zooming
931
932 #ifdef __ATLSCRL_H__
933
934 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
935 class ATL_NO_VTABLE CZoomPrintPreviewWindowImpl : public CPrintPreviewWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
936 {
937 public:
938 bool m_bSized;
939
940 CZoomPrintPreviewWindowImpl()
941 {
942 SetScrollExtendedStyle(SCRL_DISABLENOSCROLL);
943 InitZoom();
944 }
945
946 // should be called to reset data members before recreating window
947 void InitZoom()
948 {
949 m_bSized = false;
950 m_nZoomMode = ZOOMMODE_OFF;
951 m_fZoomScaleMin = 1.0;
952 m_fZoomScale = 1.0;
953 }
954
955 BEGIN_MSG_MAP(CZoomPrintPreviewWindowImpl)
956 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
957 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
958 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
959 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
960 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
961 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
962 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
963 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
964 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
965 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
966 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
967 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
968 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
969 MESSAGE_HANDLER(WM_SIZE, OnSize)
970 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
971 MESSAGE_HANDLER(WM_PAINT, OnPaint)
972 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
973 ALT_MSG_MAP(1)
974 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
975 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
976 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
977 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
978 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
979 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
980 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
981 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
982 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
983 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
984 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
985 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
986 END_MSG_MAP()
987
988 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
989 {
990 SIZE sizeClient = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
991 POINT ptOffset = m_ptOffset;
992 SIZE sizeAll = m_sizeAll;
993 SetScrollSize(sizeClient);
994 if(sizeAll.cx > 0)
995 ptOffset.x = ::MulDiv(ptOffset.x, m_sizeAll.cx, sizeAll.cx);
996 if(sizeAll.cy > 0)
997 ptOffset.y = ::MulDiv(ptOffset.y, m_sizeAll.cy, sizeAll.cy);
998 SetScrollOffset(ptOffset);
999 CScrollImpl< T >::OnSize(uMsg, wParam, lParam, bHandled);
1000 if(!m_bSized)
1001 {
1002 m_bSized = true;
1003 T* pT = static_cast<T*>(this);
1004 pT->ShowScrollBar(SB_HORZ, TRUE);
1005 pT->ShowScrollBar(SB_VERT, TRUE);
1006 }
1007 return 0;
1008 }
1009
1010 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1011 {
1012 return 1;
1013 }
1014
1015 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1016 {
1017 T* pT = static_cast<T*>(this);
1018 RECT rc = { 0 };
1019
1020 if(wParam != NULL)
1021 {
1022 CDCHandle dc = (HDC)wParam;
1023 int nMapModeSav = dc.GetMapMode();
1024 dc.SetMapMode(MM_ANISOTROPIC);
1025 SIZE szWindowExt = { 0, 0 };
1026 dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
1027 SIZE szViewportExt = { 0, 0 };
1028 dc.SetViewportExt(m_sizeAll, &szViewportExt);
1029 POINT ptViewportOrg = { 0, 0 };
1030 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1031
1032 pT->DoPrePaint(dc, rc);
1033 pT->DoPaint(dc, rc);
1034
1035 dc.SetMapMode(nMapModeSav);
1036 dc.SetWindowExt(szWindowExt);
1037 dc.SetViewportExt(szViewportExt);
1038 dc.SetViewportOrg(ptViewportOrg);
1039 }
1040 else
1041 {
1042 CPaintDC dc(pT->m_hWnd);
1043 pT->PrepareDC(dc.m_hDC);
1044 pT->DoPrePaint(dc.m_hDC, rc);
1045 pT->DoPaint(dc.m_hDC, rc);
1046 }
1047
1048 return 0;
1049 }
1050
1051 // Painting helpers
1052 void DoPaint(CDCHandle dc)
1053 {
1054 // this one is not used
1055 }
1056
1057 void DoPrePaint(CDCHandle dc, RECT& rc)
1058 {
1059 RECT rcClient = { 0 };
1060 GetClientRect(&rcClient);
1061 RECT rcArea = rcClient;
1062 T* pT = static_cast<T*>(this);
1063 pT; // avoid level 4 warning
1064 ::InflateRect(&rcArea, -pT->m_cxOffset, -pT->m_cyOffset);
1065 if (rcArea.left > rcArea.right)
1066 rcArea.right = rcArea.left;
1067 if (rcArea.top > rcArea.bottom)
1068 rcArea.bottom = rcArea.top;
1069 GetPageRect(rcArea, &rc);
1070 HBRUSH hbrOld = dc.SelectBrush(::GetSysColorBrush(COLOR_BTNSHADOW));
1071 dc.PatBlt(rcClient.left, rcClient.top, rc.left - rcClient.left, rcClient.bottom - rcClient.top, PATCOPY);
1072 dc.PatBlt(rc.left, rcClient.top, rc.right - rc.left, rc.top - rcClient.top, PATCOPY);
1073 dc.PatBlt(rc.right, rcClient.top, rcClient.right - rc.right, rcClient.bottom - rcClient.top, PATCOPY);
1074 dc.PatBlt(rc.left, rc.bottom, rc.right - rc.left, rcClient.bottom - rc.bottom, PATCOPY);
1075 dc.SelectBrush((HBRUSH)::GetStockObject(WHITE_BRUSH));
1076 dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
1077 dc.SelectBrush(::GetSysColorBrush(COLOR_3DDKSHADOW));
1078 dc.PatBlt(rc.right, rc.top + 4, 4, rc.bottom - rc.top, PATCOPY);
1079 dc.PatBlt(rc.left + 4, rc.bottom, rc.right - rc.left, 4, PATCOPY);
1080 dc.SelectBrush(hbrOld);
1081 }
1082
1083 void DoPaint(CDCHandle dc, RECT& rc)
1084 {
1085 CEnhMetaFileInfo emfinfo(m_meta);
1086 ENHMETAHEADER* pmh = emfinfo.GetEnhMetaFileHeader();
1087 int nOffsetX = MulDiv(m_sizeCurPhysOffset.cx, rc.right-rc.left, pmh->szlDevice.cx);
1088 int nOffsetY = MulDiv(m_sizeCurPhysOffset.cy, rc.bottom-rc.top, pmh->szlDevice.cy);
1089
1090 dc.OffsetWindowOrg(-nOffsetX, -nOffsetY);
1091 dc.PlayMetaFile(m_meta, &rc);
1092 }
1093 };
1094
1095 class CZoomPrintPreviewWindow : public CZoomPrintPreviewWindowImpl<CZoomPrintPreviewWindow>
1096 {
1097 public:
1098 DECLARE_WND_CLASS_EX(_T("WTL_ZoomPrintPreview"), CS_VREDRAW | CS_HREDRAW, -1)
1099 };
1100
1101 #endif // __ATLSCRL_H__
1102
1103 }; // namespace WTL
1104
1105 #endif // __ATLPRINT_H__
+0
-265
src/third_party/wtl/Include/atlres.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLRES_H__
9 #define __ATLRES_H__
10
11 #pragma once
12
13 #if defined(_WIN32_WCE) && !defined(__ATLRESCE_H__)
14 #error Use atlresCE.h instead of atlres.h for Windows CE
15 #endif
16
17
18 #ifdef RC_INVOKED
19 #ifndef _INC_WINDOWS
20
21 #define _INC_WINDOWS
22
23 #ifndef _WIN32_WCE
24 #define VS_VERSION_INFO 1
25
26 #ifdef APSTUDIO_INVOKED
27 #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols
28 #endif // APSTUDIO_INVOKED
29
30 #ifndef WINVER
31 #define WINVER 0x0400 // default to Windows Version 4.0
32 #endif // !WINVER
33
34 #include <winresrc.h>
35
36 // operation messages sent to DLGINIT
37 #define LB_ADDSTRING (WM_USER+1)
38 #define CB_ADDSTRING (WM_USER+3)
39 #endif // !_WIN32_WCE
40
41 #ifdef APSTUDIO_INVOKED
42 #undef APSTUDIO_HIDDEN_SYMBOLS
43 #endif // APSTUDIO_INVOKED
44
45 #ifdef IDC_STATIC
46 #undef IDC_STATIC
47 #endif // IDC_STATIC
48 #define IDC_STATIC (-1)
49
50 #endif // !_INC_WINDOWS
51 #endif // RC_INVOKED
52
53 #ifdef APSTUDIO_INVOKED
54 #define APSTUDIO_HIDDEN_SYMBOLS
55 #endif // APSTUDIO_INVOKED
56
57 ///////////////////////////////////////////////////////////////////////////////
58 // ATL resource types
59
60 #ifndef RC_INVOKED
61 #define RT_DLGINIT MAKEINTRESOURCE(240)
62 #define RT_TOOLBAR MAKEINTRESOURCE(241)
63 #endif // RC_INVOKED
64
65 ///////////////////////////////////////////////////////////////////////////////
66
67 #ifdef APSTUDIO_INVOKED
68 #undef APSTUDIO_HIDDEN_SYMBOLS
69 #endif // APSTUDIO_INVOKED
70
71 ///////////////////////////////////////////////////////////////////////////////
72 // Standard window components
73
74 #define ID_SEPARATOR 0 // special separator value
75 #define ID_DEFAULT_PANE 0 // default status bar pane
76
77 #ifndef RC_INVOKED // code only
78 // standard control bars (IDW = window ID)
79 #define ATL_IDW_TOOLBAR 0xE800 // main Toolbar for window
80 #define ATL_IDW_STATUS_BAR 0xE801 // Status bar window
81 #define ATL_IDW_COMMAND_BAR 0xE802 // Command bar window
82
83 // parts of a frame window
84 #define ATL_IDW_CLIENT 0xE900
85 #define ATL_IDW_PANE_FIRST 0xE900 // first pane (256 max)
86 #define ATL_IDW_PANE_LAST 0xE9FF
87 #define ATL_IDW_HSCROLL_FIRST 0xEA00 // first Horz scrollbar (16 max)
88 #define ATL_IDW_VSCROLL_FIRST 0xEA10 // first Vert scrollbar (16 max)
89
90 #define ATL_IDW_SIZE_BOX 0xEA20 // size box for splitters
91 #define ATL_IDW_PANE_SAVE 0xEA21 // to shift ATL_IDW_PANE_FIRST
92
93 // bands for a rebar
94 #define ATL_IDW_BAND_FIRST 0xEB00
95 #define ATL_IDW_BAND_LAST 0xEBFF
96 #endif // !RC_INVOKED
97
98 ///////////////////////////////////////////////////////////////////////////////
99 // Standard Commands
100
101 // File commands
102 #define ID_FILE_NEW 0xE100
103 #define ID_FILE_OPEN 0xE101
104 #define ID_FILE_CLOSE 0xE102
105 #define ID_FILE_SAVE 0xE103
106 #define ID_FILE_SAVE_AS 0xE104
107 #define ID_FILE_PAGE_SETUP 0xE105
108 #define ID_FILE_PRINT_SETUP 0xE106
109 #define ID_FILE_PRINT 0xE107
110 #define ID_FILE_PRINT_DIRECT 0xE108
111 #define ID_FILE_PRINT_PREVIEW 0xE109
112 #define ID_FILE_UPDATE 0xE10A
113 #define ID_FILE_SAVE_COPY_AS 0xE10B
114 #define ID_FILE_SEND_MAIL 0xE10C
115
116 #define ID_FILE_MRU_FIRST 0xE110
117 #define ID_FILE_MRU_FILE1 0xE110 // range - 16 max
118 #define ID_FILE_MRU_FILE2 0xE111
119 #define ID_FILE_MRU_FILE3 0xE112
120 #define ID_FILE_MRU_FILE4 0xE113
121 #define ID_FILE_MRU_FILE5 0xE114
122 #define ID_FILE_MRU_FILE6 0xE115
123 #define ID_FILE_MRU_FILE7 0xE116
124 #define ID_FILE_MRU_FILE8 0xE117
125 #define ID_FILE_MRU_FILE9 0xE118
126 #define ID_FILE_MRU_FILE10 0xE119
127 #define ID_FILE_MRU_FILE11 0xE11A
128 #define ID_FILE_MRU_FILE12 0xE11B
129 #define ID_FILE_MRU_FILE13 0xE11C
130 #define ID_FILE_MRU_FILE14 0xE11D
131 #define ID_FILE_MRU_FILE15 0xE11E
132 #define ID_FILE_MRU_FILE16 0xE11F
133 #define ID_FILE_MRU_LAST 0xE11F
134
135 // Edit commands
136 #define ID_EDIT_CLEAR 0xE120
137 #define ID_EDIT_CLEAR_ALL 0xE121
138 #define ID_EDIT_COPY 0xE122
139 #define ID_EDIT_CUT 0xE123
140 #define ID_EDIT_FIND 0xE124
141 #define ID_EDIT_PASTE 0xE125
142 #define ID_EDIT_PASTE_LINK 0xE126
143 #define ID_EDIT_PASTE_SPECIAL 0xE127
144 #define ID_EDIT_REPEAT 0xE128
145 #define ID_EDIT_REPLACE 0xE129
146 #define ID_EDIT_SELECT_ALL 0xE12A
147 #define ID_EDIT_UNDO 0xE12B
148 #define ID_EDIT_REDO 0xE12C
149 #define ID_EDIT_DELETE ID_EDIT_CLEAR
150 #define ID_EDIT_FIND_NEXT ID_EDIT_REPEAT
151 #define ID_EDIT_FIND_PREVIOUS 0xE12D
152
153 // Window commands
154 #define ID_WINDOW_NEW 0xE130
155 #define ID_WINDOW_ARRANGE 0xE131
156 #define ID_WINDOW_CASCADE 0xE132
157 #define ID_WINDOW_TILE_HORZ 0xE133
158 #define ID_WINDOW_TILE_VERT 0xE134
159 #define ID_WINDOW_SPLIT 0xE135
160 #ifndef RC_INVOKED // code only
161 #define ATL_IDM_WINDOW_FIRST 0xE130
162 #define ATL_IDM_WINDOW_LAST 0xE13F
163 #define ATL_IDM_FIRST_MDICHILD 0xFF00 // window list starts here
164 #define ATL_IDM_LAST_MDICHILD 0xFFFD
165 #endif // !RC_INVOKED
166 // TabView
167 #define ID_WINDOW_TABFIRST 0xFF00 // = ATL_IDM_FIRST_MDICHILD
168 #define ID_WINDOW_TABLAST 0xFFFD
169 #define ID_WINDOW_SHOWTABLIST 0xFFFE
170
171 // Help and App commands
172 #define ID_APP_ABOUT 0xE140
173 #define ID_APP_EXIT 0xE141
174 #define ID_HELP_INDEX 0xE142
175 #define ID_HELP_FINDER 0xE143
176 #define ID_HELP_USING 0xE144
177 #define ID_CONTEXT_HELP 0xE145 // shift-F1
178 // special commands for processing help
179 #define ID_HELP 0xE146 // first attempt for F1
180 #define ID_DEFAULT_HELP 0xE147 // last attempt
181
182 // Misc
183 #define ID_NEXT_PANE 0xE150
184 #define ID_PREV_PANE 0xE151
185 #define ID_PANE_CLOSE 0xE152
186 #define ID_PANE_NEXT ID_NEXT_PANE
187 #define ID_PANE_PREVIOUS ID_PREV_PANE
188
189 // Format
190 #define ID_FORMAT_FONT 0xE160
191
192 // Scroll
193 #define ID_SCROLL_UP 0xE170
194 #define ID_SCROLL_DOWN 0xE171
195 #define ID_SCROLL_PAGE_UP 0xE172
196 #define ID_SCROLL_PAGE_DOWN 0xE173
197 #define ID_SCROLL_TOP 0xE174
198 #define ID_SCROLL_BOTTOM 0xE175
199 #define ID_SCROLL_LEFT 0xE176
200 #define ID_SCROLL_RIGHT 0xE177
201 #define ID_SCROLL_PAGE_LEFT 0xE178
202 #define ID_SCROLL_PAGE_RIGHT 0xE179
203 #define ID_SCROLL_ALL_LEFT 0xE17A
204 #define ID_SCROLL_ALL_RIGHT 0xE17B
205
206 // OLE commands
207 #define ID_OLE_INSERT_NEW 0xE200
208 #define ID_OLE_EDIT_LINKS 0xE201
209 #define ID_OLE_EDIT_CONVERT 0xE202
210 #define ID_OLE_EDIT_CHANGE_ICON 0xE203
211 #define ID_OLE_EDIT_PROPERTIES 0xE204
212 #define ID_OLE_VERB_FIRST 0xE210 // range - 16 max
213 #ifndef RC_INVOKED // code only
214 #define ID_OLE_VERB_LAST 0xE21F
215 #endif // !RC_INVOKED
216
217 // View commands (same number used as IDW used for toolbar and status bar)
218 #define ID_VIEW_TOOLBAR 0xE800
219 #define ID_VIEW_STATUS_BAR 0xE801
220 #define ID_VIEW_REFRESH 0xE803
221 #define ID_VIEW_RIBBON 0xE804
222
223 ///////////////////////////////////////////////////////////////////////////////
224 // Standard control IDs
225
226 #ifdef IDC_STATIC
227 #undef IDC_STATIC
228 #endif // IDC_STATIC
229 #define IDC_STATIC (-1) // all static controls
230
231 ///////////////////////////////////////////////////////////////////////////////
232 // Standard string error/warnings
233
234 // idle status bar message
235 #define ATL_IDS_IDLEMESSAGE 0xE001
236
237 #ifndef RC_INVOKED // code only
238 #define ATL_IDS_SCFIRST 0xEF00
239 #endif // !RC_INVOKED
240
241 #define ATL_IDS_SCSIZE 0xEF00
242 #define ATL_IDS_SCMOVE 0xEF01
243 #define ATL_IDS_SCMINIMIZE 0xEF02
244 #define ATL_IDS_SCMAXIMIZE 0xEF03
245 #define ATL_IDS_SCNEXTWINDOW 0xEF04
246 #define ATL_IDS_SCPREVWINDOW 0xEF05
247 #define ATL_IDS_SCCLOSE 0xEF06
248 #define ATL_IDS_SCRESTORE 0xEF12
249 #define ATL_IDS_SCTASKLIST 0xEF13
250
251 #define ATL_IDS_MDICHILD 0xEF1F
252 #define ATL_IDS_MRU_FILE 0xEFDA
253
254 ///////////////////////////////////////////////////////////////////////////////
255 // Misc. control IDs
256
257 // Property Sheet control id's (determined with Spy++)
258 #define ID_APPLY_NOW 0x3021
259 #define ID_WIZBACK 0x3023
260 #define ID_WIZNEXT 0x3024
261 #define ID_WIZFINISH 0x3025
262 #define ATL_IDC_TAB_CONTROL 0x3020
263
264 #endif // __ATLRES_H__
+0
-90
src/third_party/wtl/Include/atlresce.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLRESCE_H__
9 #define __ATLRESCE_H__
10
11 #pragma once
12
13 #ifndef _WIN32_WCE
14 #error atlresCE.h is only for Windows CE
15 #endif
16
17
18 #ifdef RC_INVOKED
19 #ifndef _INC_WINDOWS
20
21 #define VS_VERSION_INFO 1
22
23 #ifdef APSTUDIO_INVOKED
24 #define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols
25 #endif // APSTUDIO_INVOKED
26
27 #ifndef WINVER
28 #define WINVER 0x0400 // default to Windows Version 4.0
29 #endif // !WINVER
30
31 #if !defined(WCEOLE_ENABLE_DIALOGEX)
32 #define DIALOGEX DIALOG DISCARDABLE
33 #endif
34
35 #include <commctrl.h>
36 #define SHMENUBAR RCDATA
37
38 #if defined(SHELLSDK_MODULES_AYGSHELL)
39 #include <aygshell.h>
40 #else
41 #define NOMENU 0xFFFF
42 #define IDS_SHNEW 1
43 #define IDM_SHAREDNEW 10
44 #define IDM_SHAREDNEWDEFAULT 11
45 #endif
46 #ifndef I_IMAGENONE
47 #define I_IMAGENONE (-2)
48 #endif
49
50 #include <windows.h>
51
52 #endif // !_INC_WINDOWS
53 #endif // RC_INVOKED
54
55 #include "atlres.h"
56
57 #ifdef APSTUDIO_INVOKED
58 #undef APSTUDIO_HIDDEN_SYMBOLS
59 #endif // APSTUDIO_INVOKED
60
61 // Visual Studio dialog editor bug fix
62 #ifndef DS_FIXEDSYS
63 #define DS_FIXEDSYS 0
64 #endif
65
66 #define IDC_INFOSTATIC 0xFFFE // == IDC_STATIC -1
67
68 ///////////////////////////////////////////////////////////////////////////////
69 // Smartphone and PPC 2005 Resource IDs
70
71 // Command and associated string resource IDs
72 #define ID_MENU_OK 0xE790
73 #define ID_MENU_CANCEL 0xE791
74 #define ID_MENU 0xE792
75 #define ID_ACTION 0xE793
76 #define ID_VIEW_FULLSCREEN 0xE802
77
78 // MenuBar resource IDs
79 #define ATL_IDM_MENU_DONE 0xE701
80 #define ATL_IDM_MENU_CANCEL 0xE702
81 #define ATL_IDM_MENU_DONECANCEL 0xE703
82
83 // Default device MenuBar control ID and MenuBar resource ID
84 #define ATL_IDW_MENU_BAR 0xE802
85
86 // SmartPhone spinned controls ID offset for CSpinCtrl
87 #define ATL_IDW_SPIN_ID 9999
88
89 #endif // __ATLRESCE_H__
+0
-3456
src/third_party/wtl/Include/atlribbon.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLRIBBON_H__
9 #define __ATLRIBBON_H__
10
11 #pragma once
12
13 #if (_MSC_VER < 1500)
14 #error atlribbon.h requires Visual C++ 2008 compiler or higher
15 #endif
16
17 #ifndef _UNICODE
18 #error atlribbon.h requires the Unicode character set
19 #endif
20
21 #if !defined(NTDDI_WIN7) || (NTDDI_VERSION < NTDDI_WIN7)
22 #error atlribbon.h requires the Windows 7 SDK or higher
23 #endif
24
25 #ifdef _WIN32_WCE
26 #error atlribbon.h is not supported on Windows CE
27 #endif
28
29 #ifndef __ATLAPP_H__
30 #error atlribbon.h requires atlapp.h to be included first
31 #endif
32
33 #if (_ATL_VER < 0x0700)
34 #include <shlwapi.h>
35 #pragma comment(lib, "shlwapi.lib")
36 #endif
37
38 #include <atlmisc.h> // for RecentDocumentList classes
39 #include <atlframe.h> // for Frame and UpdateUI classes
40 #include <atlctrls.h> // required for atlctrlw.h
41 #include <atlctrlw.h> // for CCommandBarCtrl
42
43 #if !defined(_WTL_USE_CSTRING) && !defined(__ATLSTR_H__)
44 #pragma warning(push)
45 #pragma warning(disable: 4530) // unwind semantics not enabled
46 #include <string>
47 #pragma warning(pop)
48 #endif
49
50 #include <dwmapi.h>
51 #pragma comment(lib, "dwmapi.lib")
52
53 #include <UIRibbon.h>
54 #include <UIRibbonPropertyHelpers.h>
55 #pragma comment(lib, "propsys.lib")
56
57 #include <Richedit.h> // for CHARFORMAT2
58
59
60 ///////////////////////////////////////////////////////////////////////////////
61 // Classes in this file:
62 //
63 // CRibbonUpdateUI : Automatic mapping of ribbon UI elements
64 //
65 // RibbonUI::Text
66 // RibbonUI::CharFormat
67 // RibbonUI::ICtrl
68 // RibbonUI::CtrlImpl
69 // RibbonUI::CommandCtrlImpl
70 // RibbonUI::ItemProperty
71 // RibbonUI::CollectionImplBase
72 // RibbonUI::CollectionImpl
73 // RibbonUI::TextCollectionImpl
74 // RibbonUI::ItemCollectionImpl
75 // RibbonUI::ComboCollectionImpl
76 // RibbonUI::CommandCollectionImpl
77 // RibbonUI::ToolbarCollectionImpl
78 // RibbonUI::SimpleCollectionImpl
79 // RibbonUI::CollectionCtrlImpl
80 // RibbonUI::ToolbarGalleryCtrlImpl
81 // RibbonUI::SimpleCollectionCtrlImpl
82 // RibbonUI::RecentItemsCtrlImpl
83 // RibbonUI::FontCtrlImpl
84 // RibbonUI::ColorCtrlImpl
85 // RibbonUI::SpinnerCtrlImpl
86 //
87 // RibbonUI::CRibbonImpl
88 // CRibbonImpl::CRibbonComboCtrl
89 // CRibbonImpl::CRibbonItemGalleryCtrl
90 // CRibbonImpl::CRibbonCommandGalleryCtrl
91 // CRibbonImpl::CRibbonToolbarGalleryCtrl
92 // CRibbonImpl::CRibbonSimpleComboCtrl
93 // CRibbonImpl::CRibbonSimpleGalleryCtrl
94 // CRibbonImpl::CRibbonRecentItemsCtrl
95 // CRibbonImpl::CRibbonColorCtrl
96 // CRibbonImpl::CRibbonFontCtrl
97 // CRibbonImpl::CRibbonSpinnerCtrl
98 // CRibbonImpl::CRibbonFloatSpinnerCtrl
99 // CRibbonImpl::CRibbonCommandCtrl
100 //
101 // CRibbonFrameWindowImplBase
102 // CRibbonFrameWindowImpl
103 // CRibbonMDIFrameWindowImpl
104 // CRibbonPersist
105 //
106 // Global functions:
107 // RibbonUI::SetPropertyVal()
108 // RibbonUI::GetImage()
109
110
111 // Constants
112
113 #ifndef RIBBONUI_MAX_TEXT
114 #define RIBBONUI_MAX_TEXT 128
115 #endif
116
117 #define TWIPS_PER_POINT 20 // For font size
118
119
120 namespace WTL
121 {
122
123 ///////////////////////////////////////////////////////////////////////////////
124 // CRibbonUpdateUI : Automatic mapping of ribbon UI elements
125
126 template <class T>
127 class CRibbonUpdateUI : public CAutoUpdateUI<T>
128 {
129 public:
130 enum
131 {
132 UPDUI_RIBBON = 0x0080,
133 UPDUI_PERSIST = 0x0020
134 };
135
136 bool IsRibbonElement(const _AtlUpdateUIMap& UIMap)
137 {
138 return (UIMap.m_wType & UPDUI_RIBBON) != 0;
139 }
140
141 bool IsRibbonID(UINT nID)
142 {
143 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
144 {
145 if(m_arrUIMap[i].m_nID == nID)
146 return IsRibbonElement(m_arrUIMap[i]);
147 }
148
149 return false;
150 }
151
152 // Element
153 bool UIAddRibbonElement(UINT nID)
154 {
155 return UIAddElement<UPDUI_RIBBON>(nID);
156 }
157
158 bool UIRemoveRibbonElement(UINT nID)
159 {
160 return UIRemoveElement<UPDUI_RIBBON>(nID);
161 }
162
163 bool UIPersistElement(UINT nID, bool bPersist = true)
164 {
165 return bPersist ?
166 UIAddElement<UPDUI_PERSIST>(nID) :
167 UIRemoveElement<UPDUI_PERSIST>(nID);
168 }
169
170 // methods for Ribbon elements
171 BOOL UISetText(int nID, LPCWSTR sText, BOOL bForceUpdate = FALSE)
172 {
173 T* pT = static_cast<T*>(this);
174 BOOL bRes = CUpdateUIBase::UISetText(nID, sText, bForceUpdate);
175 if (pT->IsRibbonUI() && IsRibbonID(nID))
176 bRes = SUCCEEDED(pT->InvalidateProperty(nID, UI_PKEY_Label));
177 return bRes;
178 }
179
180 BOOL UISetText(int nID, UINT uIdResource, BOOL bForceUpdate = FALSE)
181 {
182 CTempBuffer<WCHAR> sText(RIBBONUI_MAX_TEXT);
183 int nRet = AtlLoadString(uIdResource, sText, RIBBONUI_MAX_TEXT);
184 if(nRet > 0)
185 UISetText(nID, sText, bForceUpdate);
186 return (nRet > 0) ? TRUE : FALSE;
187 }
188
189 LPCTSTR UIGetText(int nID)
190 {
191 T* pT = static_cast<T*>(this);
192 LPCTSTR sUI = CAutoUpdateUI::UIGetText(nID);
193
194 // replace 'tab' by 'space' for RibbonUI elements
195 if (sUI && pT->IsRibbonUI() && IsRibbonID(nID) && wcschr(sUI, L'\t'))
196 {
197 static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 };
198 wcscpy_s(sText, sUI);
199 WCHAR* pch = wcschr(sText, L'\t');
200 if (pch != NULL)
201 *pch = L' ';
202 return sText;
203 }
204 else
205 {
206 return sUI;
207 }
208 }
209
210 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
211 {
212 T* pT = static_cast<T*>(this);
213 BOOL bRes = CUpdateUIBase::UIEnable(nID, bEnable, bForceUpdate);
214 if (pT->IsRibbonUI() && IsRibbonID(nID))
215 bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_Enabled, bEnable));
216 return bRes;
217 }
218
219 BOOL UISetCheck(int nID, INT nCheck, BOOL bForceUpdate = FALSE)
220 {
221 if ((nCheck == 0) || (nCheck == 1))
222 return UISetCheck(nID, nCheck != 0, bForceUpdate);
223 else
224 return CUpdateUIBase::UISetCheck(nID, nCheck, bForceUpdate);
225 }
226
227 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
228 {
229 T* pT = static_cast<T*>(this);
230 BOOL bRes = CUpdateUIBase::UISetCheck(nID, bCheck, bForceUpdate);
231 if (bRes && pT->IsRibbonUI() && IsRibbonID(nID))
232 bRes = SUCCEEDED(pT->SetProperty((WORD)nID, UI_PKEY_BooleanValue, bCheck));
233 return bRes;
234 }
235 };
236
237
238 ///////////////////////////////////////////////////////////////////////////////
239 // RibbonUI namespace
240 //
241
242 namespace RibbonUI
243 {
244
245 // Minimal string allocation support for various PROPERTYKEY values
246 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
247 typedef _CSTRING_NS::CString Text;
248 #else
249 class Text : public std::wstring
250 {
251 public:
252 Text(std::wstring& s) : std::wstring(s)
253 { }
254 Text(LPCWSTR s) : std::wstring(s)
255 { }
256 Text()
257 { }
258 bool IsEmpty()
259 {
260 return empty();
261 }
262 operator LPCWSTR()
263 {
264 return c_str();
265 }
266 Text& operator =(LPCWSTR s)
267 {
268 return static_cast<Text&>(std::wstring::operator =(s));
269 }
270 };
271 #endif
272
273 // PROPERTYKEY enum and helpers
274 enum k_KEY
275 {
276 // state
277 k_Enabled = 1, k_BooleanValue = 200,
278 // text properties
279 k_LabelDescription = 2, k_Keytip = 3, k_Label = 4, k_TooltipDescription = 5, k_TooltipTitle = 6,
280 // image properties
281 k_LargeImage = 7, k_LargeHighContrastImage = 8, k_SmallImage = 9, k_SmallHighContrastImage = 10,
282 // collection properties
283 k_ItemsSource = 101, k_Categories = 102, k_SelectedItem = 104,
284 // collection item properties
285 k_CommandId = 100, k_CategoryId = 103, k_CommandType = 105, k_ItemImage = 106,
286 // combo control property
287 k_StringValue = 202,
288 // spinner control properties
289 k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces, k_FormatString, k_RepresentativeString = 208,
290 // font control properties
291 k_FontProperties = 300, k_FontProperties_Family, k_FontProperties_Size, k_FontProperties_Bold, k_FontProperties_Italic = 304,
292 k_FontProperties_Underline = 305, k_FontProperties_Strikethrough, k_FontProperties_VerticalPositioning, k_FontProperties_ForegroundColor = 308,
293 k_FontProperties_BackgroundColor = 309, k_FontProperties_ForegroundColorType, k_FontProperties_BackgroundColorType, k_FontProperties_ChangedProperties = 312,
294 k_FontProperties_DeltaSize = 313,
295 // recent items properties
296 k_RecentItems = 350, k_Pinned = 351,
297 // color control properties
298 k_Color = 400, k_ColorType = 401, k_ColorMode,
299 k_ThemeColorsCategoryLabel = 403, k_StandardColorsCategoryLabel, k_RecentColorsCategoryLabel = 405, k_AutomaticColorLabel = 406,
300 k_NoColorLabel = 407, k_MoreColorsLabel = 408,
301 k_ThemeColors = 409, k_StandardColors = 410, k_ThemeColorsTooltips = 411, k_StandardColorsTooltips = 412,
302 // Ribbon state
303 k_Viewable = 1000, k_Minimized = 1001, k_QuickAccessToolbarDock = 1002, k_ContextAvailable = 1100,
304 // Ribbon UI colors
305 k_GlobalBackgroundColor = 2000, k_GlobalHighlightColor, k_GlobalTextColor = 2002
306 };
307
308 inline k_KEY k_(REFPROPERTYKEY key)
309 {
310 return (k_KEY)key.fmtid.Data1;
311 }
312
313 // PROPERTYKEY value assignment and specializations
314 //
315 template <typename V>
316 HRESULT SetPropertyVal(REFPROPERTYKEY key, V val, PROPVARIANT* ppv)
317 {
318 switch (k_(key))
319 {
320 case k_Enabled:
321 case k_BooleanValue:
322 return InitPropVariantFromBoolean(val, ppv);
323 default:
324 return UIInitPropertyFromUInt32(key, val, ppv);
325 }
326 }
327
328 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DOUBLE val, PROPVARIANT* ppv)
329 {
330 return SetPropertyVal(key, (LONG)val, ppv);
331 }
332
333 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUIImage* val, PROPVARIANT* ppv)
334 {
335 HRESULT hr = UIInitPropertyFromImage(key, val, ppv);
336 ATLVERIFY(val->Release() == 1);
337 return hr;
338 }
339
340 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IUnknown* val, PROPVARIANT* ppv)
341 {
342 return UIInitPropertyFromInterface(key, val, ppv);
343 }
344
345 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, IPropertyStore* val, PROPVARIANT* ppv)
346 {
347 return UIInitPropertyFromInterface(key, val, ppv);
348 }
349
350 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, SAFEARRAY* val, PROPVARIANT* ppv)
351 {
352 return UIInitPropertyFromIUnknownArray(key, val, ppv);
353 }
354
355 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, DECIMAL* val, PROPVARIANT* ppv)
356 {
357 return UIInitPropertyFromDecimal(key, *val, ppv);
358 }
359
360 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, bool val, PROPVARIANT* ppv)
361 {
362 return UIInitPropertyFromBoolean(key, val, ppv);
363 }
364
365 inline HRESULT SetPropertyVal(REFPROPERTYKEY key, LPCWSTR val, PROPVARIANT* ppv)
366 {
367 return UIInitPropertyFromString(key, val, ppv);
368 }
369
370 // CharFormat helper struct for RibbonUI font control
371 //
372 struct CharFormat : CHARFORMAT2
373 {
374 // Default constructor
375 CharFormat()
376 {
377 cbSize = sizeof(CHARFORMAT2);
378 Reset();
379 }
380
381 // Copy constructor
382 CharFormat(const CharFormat& cf)
383 {
384 ::CopyMemory(this, &cf, sizeof(CHARFORMAT2));
385 }
386
387 // Assign operator
388 CharFormat& operator =(const CharFormat& cf)
389 {
390 ::CopyMemory(this, &cf, sizeof(CHARFORMAT2));
391 return (*this);
392 }
393
394 void Reset()
395 {
396 uValue = dwMask = dwEffects = 0;
397 PropVariantInit(&propvar);
398 }
399
400 void operator <<(IPropertyStore* pStore)
401 {
402 if (pStore == NULL)
403 {
404 ATLASSERT(FALSE);
405 return;
406 }
407
408 static void (CharFormat::*Getk_[])(IPropertyStore*) =
409 {
410 &CharFormat::Getk_Family,
411 &CharFormat::Getk_FontProperties_Size,
412 &CharFormat::Getk_MaskEffect<CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold>,
413 &CharFormat::Getk_MaskEffect<CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic>,
414 &CharFormat::Getk_MaskEffect<CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline>,
415 &CharFormat::Getk_MaskEffect<CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough>,
416 &CharFormat::Getk_VerticalPositioning,
417 &CharFormat::Getk_Color<CFM_COLOR, UI_PKEY_FontProperties_ForegroundColor>,
418 &CharFormat::Getk_Color<CFM_BACKCOLOR, UI_PKEY_FontProperties_BackgroundColor>,
419 &CharFormat::Getk_ColorType<CFM_COLOR, CFE_AUTOCOLOR, UI_SWATCHCOLORTYPE_AUTOMATIC, UI_PKEY_FontProperties_ForegroundColorType>,
420 &CharFormat::Getk_ColorType<CFM_BACKCOLOR, CFE_AUTOBACKCOLOR, UI_SWATCHCOLORTYPE_NOCOLOR, UI_PKEY_FontProperties_BackgroundColorType>,
421 };
422
423 DWORD nProps = 0;
424 Reset();
425
426 ATLVERIFY(SUCCEEDED(pStore->GetCount(&nProps)));
427 for (DWORD iProp = 0; iProp < nProps; iProp++)
428 {
429 PROPERTYKEY key;
430 ATLVERIFY(SUCCEEDED(pStore->GetAt(iProp, &key)));
431 ATLASSERT(k_(key) >= k_FontProperties_Family);
432
433 if (k_(key) <= k_FontProperties_BackgroundColorType)
434 (this->*Getk_[k_(key) - k_FontProperties_Family])(pStore);
435 }
436 }
437
438 void operator >>(IPropertyStore* pStore)
439 {
440 if (pStore == NULL)
441 {
442 ATLASSERT(FALSE);
443 return;
444 }
445
446 PutFace(pStore);
447 PutSize(pStore);
448 PutMaskEffect(CFM_BOLD, CFE_BOLD, UI_PKEY_FontProperties_Bold, pStore);
449 PutMaskEffect(CFM_ITALIC, CFE_ITALIC, UI_PKEY_FontProperties_Italic, pStore);
450 PutMaskEffect(CFM_UNDERLINE, CFE_UNDERLINE, UI_PKEY_FontProperties_Underline, pStore);
451 PutMaskEffect(CFM_STRIKEOUT, CFE_STRIKEOUT, UI_PKEY_FontProperties_Strikethrough, pStore);
452 PutVerticalPos(pStore);
453 PutColor(pStore);
454 PutBackColor(pStore);
455 }
456
457 private:
458 PROPVARIANT propvar;
459 UINT uValue;
460
461 // Getk_ functions
462 void Getk_Family(IPropertyStore* pStore)
463 {
464 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Family, &propvar)))
465 {
466 PropVariantToString(propvar, szFaceName, LF_FACESIZE);
467 if (*szFaceName)
468 dwMask |= CFM_FACE;
469 }
470 }
471
472 void Getk_FontProperties_Size(IPropertyStore* pStore)
473 {
474 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_Size, &propvar)))
475 {
476 DECIMAL decSize = { 0 };
477 UIPropertyToDecimal(UI_PKEY_FontProperties_Size, propvar, &decSize);
478 DOUBLE dSize = 0;
479 VarR8FromDec(&decSize, &dSize);
480 if (dSize > 0)
481 {
482 dwMask |= CFM_SIZE;
483 yHeight = (LONG)(dSize * TWIPS_PER_POINT);
484 }
485 }
486 }
487
488 template <DWORD t_dwMask, DWORD t_dwEffects, REFPROPERTYKEY key>
489 void Getk_MaskEffect(IPropertyStore* pStore)
490 {
491 if (SUCCEEDED(pStore->GetValue(key, &propvar)))
492 {
493 UIPropertyToUInt32(key, propvar, &uValue);
494 if ((UI_FONTPROPERTIES)uValue != UI_FONTPROPERTIES_NOTAVAILABLE)
495 {
496 dwMask |= t_dwMask;
497 dwEffects |= ((UI_FONTPROPERTIES) uValue == UI_FONTPROPERTIES_SET) ? t_dwEffects : 0;
498 }
499 }
500 }
501
502 void Getk_VerticalPositioning(IPropertyStore* pStore)
503 {
504 if (SUCCEEDED(pStore->GetValue(UI_PKEY_FontProperties_VerticalPositioning, &propvar)))
505 {
506 UIPropertyToUInt32(UI_PKEY_FontProperties_VerticalPositioning, propvar, &uValue);
507 UI_FONTVERTICALPOSITION uVerticalPosition = (UI_FONTVERTICALPOSITION) uValue;
508 if ((uVerticalPosition != UI_FONTVERTICALPOSITION_NOTAVAILABLE))
509 {
510 dwMask |= (CFM_SUPERSCRIPT | CFM_SUBSCRIPT);
511 if (uVerticalPosition != UI_FONTVERTICALPOSITION_NOTSET)
512 {
513 dwEffects |= (uVerticalPosition == UI_FONTVERTICALPOSITION_SUPERSCRIPT) ? CFE_SUPERSCRIPT : CFE_SUBSCRIPT;
514 }
515 }
516 }
517 }
518
519 template <DWORD t_dwMask, REFPROPERTYKEY key>
520 void Getk_Color(IPropertyStore* pStore)
521 {
522 UINT32 color = 0;
523 if (SUCCEEDED(pStore->GetValue(key, &propvar)))
524 {
525 UIPropertyToUInt32(key, propvar, &color);
526 dwMask |= t_dwMask;
527
528 if (t_dwMask == CFM_COLOR)
529 crTextColor = color;
530 else
531 crBackColor = color;
532 }
533 }
534
535 template <DWORD t_dwMask, DWORD t_dwEffects, UI_SWATCHCOLORTYPE t_type, REFPROPERTYKEY key>
536 void Getk_ColorType(IPropertyStore* pStore)
537 {
538 if (SUCCEEDED(pStore->GetValue(key, &propvar)))
539 {
540 UIPropertyToUInt32(key, propvar, &uValue);
541 if (t_type == (UI_SWATCHCOLORTYPE)uValue)
542 {
543 dwMask |= t_dwMask;
544 dwEffects |= t_dwEffects;
545 }
546 }
547 }
548
549 // Put functions
550 void PutMaskEffect(WORD dwMaskVal, WORD dwEffectVal, REFPROPERTYKEY key, IPropertyStore* pStore)
551 {
552 PROPVARIANT var;
553 UI_FONTPROPERTIES uProp = UI_FONTPROPERTIES_NOTAVAILABLE;
554 if ((dwMask & dwMaskVal) != 0)
555 uProp = dwEffects & dwEffectVal ? UI_FONTPROPERTIES_SET : UI_FONTPROPERTIES_NOTSET;
556 SetPropertyVal(key, uProp, &var);
557 pStore->SetValue(key, var);
558 }
559
560 void PutVerticalPos(IPropertyStore* pStore)
561 {
562 PROPVARIANT var;
563 UI_FONTVERTICALPOSITION uProp = UI_FONTVERTICALPOSITION_NOTAVAILABLE;
564
565 if ((dwMask & CFE_SUBSCRIPT) != 0)
566 {
567 if ((dwMask & CFM_SUBSCRIPT) && (dwEffects & CFE_SUBSCRIPT))
568 uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT;
569 else
570 uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT;
571 }
572 else if ((dwMask & CFM_OFFSET) != 0)
573 {
574 if (yOffset > 0)
575 uProp = UI_FONTVERTICALPOSITION_SUPERSCRIPT;
576 else if (yOffset < 0)
577 uProp = UI_FONTVERTICALPOSITION_SUBSCRIPT;
578 }
579
580 SetPropertyVal(UI_PKEY_FontProperties_VerticalPositioning, uProp, &var);
581 pStore->SetValue(UI_PKEY_FontProperties_VerticalPositioning, var);
582 }
583
584 void PutFace(IPropertyStore* pStore)
585 {
586 PROPVARIANT var;
587 SetPropertyVal(UI_PKEY_FontProperties_Family,
588 dwMask & CFM_FACE ? szFaceName : L"", &var);
589 pStore->SetValue(UI_PKEY_FontProperties_Family, var);
590 }
591
592 void PutSize(IPropertyStore* pStore)
593 {
594 PROPVARIANT var;
595 DECIMAL decVal;
596
597 if ((dwMask & CFM_SIZE) != 0)
598 VarDecFromR8((DOUBLE)yHeight / TWIPS_PER_POINT, &decVal);
599 else
600 VarDecFromI4(0, &decVal);
601
602 SetPropertyVal(UI_PKEY_FontProperties_Size, &decVal, &var);
603 pStore->SetValue(UI_PKEY_FontProperties_Size, var);
604 }
605
606 void PutColor(IPropertyStore* pStore)
607 {
608 if ((dwMask & CFM_COLOR) != 0)
609 {
610 if ((dwEffects & CFE_AUTOCOLOR) == 0)
611 {
612 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar);
613 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar);
614
615 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColor, crTextColor, &propvar);
616 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColor, propvar);
617 }
618 else
619 {
620 SetPropertyVal(UI_PKEY_FontProperties_ForegroundColorType, UI_SWATCHCOLORTYPE_AUTOMATIC, &propvar);
621 pStore->SetValue(UI_PKEY_FontProperties_ForegroundColorType, propvar);
622 }
623 }
624 }
625
626 void PutBackColor(IPropertyStore* pStore)
627 {
628 if (((dwMask & CFM_BACKCOLOR) != 0) && ((dwEffects & CFE_AUTOBACKCOLOR) == 0))
629 {
630 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_RGB, &propvar);
631 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar);
632
633 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColor, crBackColor, &propvar);
634 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColor, propvar);
635 }
636 else
637 {
638 SetPropertyVal(UI_PKEY_FontProperties_BackgroundColorType, UI_SWATCHCOLORTYPE_NOCOLOR, &propvar);
639 pStore->SetValue(UI_PKEY_FontProperties_BackgroundColorType, propvar);
640 }
641 }
642 };
643
644 // IUIImage helper
645 //
646 inline IUIImage* GetImage(HBITMAP hbm, UI_OWNERSHIP owner)
647 {
648 ATLASSERT(hbm);
649 IUIImage* pIUII = NULL;
650 ATL::CComPtr<IUIImageFromBitmap> pIFB;
651
652 if SUCCEEDED(pIFB.CoCreateInstance(CLSID_UIRibbonImageFromBitmapFactory))
653 ATLVERIFY(SUCCEEDED(pIFB->CreateImage(hbm, owner, &pIUII)));
654
655 return pIUII;
656 }
657
658
659 ///////////////////////////////////////////////////////////////////////////////
660 // Ribbon control classes
661
662 // RibbonUI::ICtrl abstract interface of RibbonUI::CRibbonImpl and all RibbonUI control classes
663 //
664 struct ICtrl
665 {
666 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
667 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
668 IUISimplePropertySet* pCommandExecutionProperties) = 0;
669
670 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
671 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue) = 0;
672 };
673
674 // RibbonUI::CtrlImpl base class for all ribbon controls
675 //
676 template <class T, UINT t_ID>
677 class ATL_NO_VTABLE CtrlImpl : public ICtrl
678 {
679 protected:
680 T* m_pWndRibbon;
681
682 public:
683 typedef T WndRibbon;
684
685 CtrlImpl() : m_pWndRibbon(T::pWndRibbon)
686 { }
687
688 WndRibbon& GetWndRibbon()
689 {
690 return *m_pWndRibbon;
691 }
692
693 static WORD GetID()
694 {
695 return t_ID;
696 }
697
698 Text m_sTxt[5];
699
700 // Operations
701 HRESULT Invalidate()
702 {
703 return GetWndRibbon().InvalidateCtrl(GetID());
704 }
705
706 HRESULT Invalidate(REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY)
707 {
708 return GetWndRibbon().InvalidateProperty(GetID(), key, flags);
709 }
710
711 HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sTxt, bool bUpdate = false)
712 {
713 ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription));
714
715 m_sTxt[k_(key) - k_LabelDescription] = sTxt;
716
717 return bUpdate ?
718 GetWndRibbon().InvalidateProperty(GetID(), key) :
719 S_OK;
720 }
721
722 // Implementation
723 template <typename V>
724 HRESULT SetProperty(REFPROPERTYKEY key, V val)
725 {
726 return GetWndRibbon().SetProperty(GetID(), key, val);
727 }
728
729 HRESULT OnGetText(REFPROPERTYKEY key, PROPVARIANT* ppv)
730 {
731 ATLASSERT((k_(key) <= k_TooltipTitle) && (k_(key) >= k_LabelDescription));
732
733 const INT iText = k_(key) - k_LabelDescription;
734 if (m_sTxt[iText].IsEmpty())
735 if (LPCWSTR sText = GetWndRibbon().OnRibbonQueryText(GetID(), key))
736 m_sTxt[iText] = sText;
737
738 return !m_sTxt[iText].IsEmpty() ?
739 SetPropertyVal(key, (LPCWSTR)m_sTxt[iText], ppv) :
740 S_OK;
741 }
742
743 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
744 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
745 IUISimplePropertySet* pCommandExecutionProperties)
746 {
747 ATLASSERT(nCmdID == t_ID);
748 return GetWndRibbon().DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties);
749 }
750
751 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
752 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
753 {
754 ATLASSERT(nCmdID == t_ID);
755
756 const INT iMax = k_TooltipTitle - k_LabelDescription;
757 const INT iVal = k_(key) - k_LabelDescription;
758
759 return (iVal <= iMax) && (iVal >= 0) ?
760 OnGetText(key, ppropvarNewValue) :
761 GetWndRibbon().DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
762 }
763 };
764
765 // CommandCtrlImpl base class for most ribbon controls
766 //
767 template <class T, UINT t_ID>
768 class CommandCtrlImpl : public CtrlImpl<T, t_ID>
769 {
770 public:
771 CBitmap m_hbm[4];
772
773 HRESULT SetImage(REFPROPERTYKEY key, HBITMAP hbm, bool bUpdate = false)
774 {
775 ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage));
776
777 m_hbm[k_(key) - k_LargeImage].Attach(hbm);
778
779 return bUpdate ?
780 GetWndRibbon().InvalidateProperty(GetID(), key) :
781 S_OK;
782 }
783
784 HRESULT OnGetImage(REFPROPERTYKEY key, PROPVARIANT* ppv)
785 {
786 ATLASSERT((k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage));
787
788 const INT iImage = k_(key) - k_LargeImage;
789
790 if (m_hbm[iImage].IsNull())
791 m_hbm[iImage] = GetWndRibbon().OnRibbonQueryImage(GetID(), key);
792
793 return m_hbm[iImage].IsNull() ?
794 E_NOTIMPL :
795 SetPropertyVal(key, GetImage(m_hbm[iImage], UI_OWNERSHIP_COPY), ppv);
796 }
797
798 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
799 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
800 {
801 ATLASSERT (nCmdID == GetID());
802
803 return (k_(key) <= k_SmallHighContrastImage) && (k_(key) >= k_LargeImage) ?
804 OnGetImage(key, ppropvarNewValue) :
805 CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
806 }
807 };
808
809
810 ///////////////////////////////////////////////////////////////////////////////
811 // Ribbon collection base classes
812
813 // ItemProperty class: ribbon callback for each item in a collection
814 //
815
816 #pragma warning(push)
817 #pragma warning(disable: 4512) // assignment operator could not be generated
818
819 template <class TCollection>
820 class ItemProperty : public IUISimplePropertySet
821 {
822 public:
823 ItemProperty(UINT i, TCollection* pCollection) : m_Index(i), m_pCollection(pCollection)
824 { }
825
826 const UINT m_Index;
827 TCollection* m_pCollection;
828
829 // IUISimplePropertySet method.
830 STDMETHODIMP GetValue(REFPROPERTYKEY key, PROPVARIANT *value)
831 {
832 return m_pCollection->OnGetItem(m_Index, key, value);
833 }
834
835 // IUnknown methods.
836 STDMETHODIMP_(ULONG) AddRef()
837 {
838 return 1;
839 }
840
841 STDMETHODIMP_(ULONG) Release()
842 {
843 return 1;
844 }
845
846 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
847 {
848 if ((iid == __uuidof(IUnknown)) || (iid == __uuidof(IUISimplePropertySet)))
849 {
850 *ppv = this;
851 return S_OK;
852 }
853 else
854 {
855 return E_NOINTERFACE;
856 }
857 }
858 };
859
860 #pragma warning(pop)
861
862
863 // CollectionImplBase: base class for all RibbonUI collections
864 //
865 template <class TCollection, size_t t_size>
866 class CollectionImplBase
867 {
868 typedef CollectionImplBase<TCollection, t_size> thisClass;
869
870 public:
871 CollectionImplBase()
872 {
873 for (int i = 0; i < t_size; i++)
874 m_apItems[i] = new ItemProperty<TCollection>(i, static_cast<TCollection*>(this));
875 }
876
877 ~CollectionImplBase()
878 {
879 for (int i = 0; i < t_size; i++)
880 delete m_apItems[i];
881 }
882
883 // Data members
884 ItemProperty<TCollection>* m_apItems[t_size];
885 };
886
887 // CollectionImpl: handles categories and collecton resizing
888 //
889 template <class TCtrl, size_t t_items, size_t t_categories>
890 class CollectionImpl : public CollectionImplBase<CollectionImpl<TCtrl, t_items, t_categories>, t_items + t_categories>
891 {
892 typedef CollectionImpl<TCtrl, t_items, t_categories> thisClass;
893 public:
894 typedef thisClass Collection;
895
896 CollectionImpl() : m_size(t_items)
897 {
898 ::FillMemory(m_auItemCat, sizeof(m_auItemCat), 0xff); // UI_COLLECTION_INVALIDINDEX
899 }
900
901 UINT32 m_auItemCat[t_items];
902 Text m_asCatName[__max(t_categories, 1)];
903 size_t m_size;
904
905 // Operations
906 HRESULT SetItemCategory(UINT uItem, UINT uCat, bool bUpdate = false)
907 {
908 ATLASSERT((uItem < t_items) && (uCat < t_categories));
909
910 m_auItemCat[uItem] = uCat;
911
912 return bUpdate ? InvalidateItems() : S_OK;
913 }
914
915 HRESULT SetCategoryText(UINT uCat, LPCWSTR sText, bool bUpdate = false)
916 {
917 ATLASSERT(uCat < t_categories);
918
919 m_asCatName[uCat] = sText;
920
921 return bUpdate ? InvalidateCategories() : S_OK;
922 }
923
924 HRESULT Resize(size_t size, bool bUpdate = false)
925 {
926 ATLASSERT(size <= t_items);
927
928 m_size = size;
929
930 return bUpdate ? InvalidateItems() : S_OK;
931 }
932
933 // Implementation
934 HRESULT OnGetItem(UINT uIndex, REFPROPERTYKEY key, PROPVARIANT *value)
935 {
936 ATLASSERT(uIndex < t_items + t_categories);
937 TCtrl* pCtrl = static_cast<TCtrl*>(this);
938
939 return uIndex < t_items ?
940 pCtrl->DoGetItem(uIndex, key, value) :
941 pCtrl->DoGetCategory(uIndex - t_items, key, value);
942 }
943
944 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
945 {
946 ATLASSERT(k_(key) == k_CategoryId);
947 UINT32 uCat = UI_COLLECTION_INVALIDINDEX;
948
949 if (t_categories != 0)
950 {
951 if (m_auItemCat[uItem] == UI_COLLECTION_INVALIDINDEX)
952 {
953 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
954 m_auItemCat[uItem] = ribbon.OnRibbonQueryItemCategory(TCtrl::GetID(), uItem);
955 }
956 uCat = m_auItemCat[uItem];
957 }
958
959 return SetPropertyVal(key, uCat, value);
960 }
961
962 HRESULT DoGetCategory(UINT uCat, REFPROPERTYKEY key, PROPVARIANT *value)
963 {
964 HRESULT hr = S_OK;
965
966 switch (k_(key))
967 {
968 case k_Label:
969 if (m_asCatName[uCat].IsEmpty())
970 {
971 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
972 m_asCatName[uCat] = ribbon.OnRibbonQueryCategoryText(TCtrl::GetID(), uCat);
973 }
974 hr = SetPropertyVal(key, (LPCWSTR)m_asCatName[uCat], value);
975 break;
976 case k_CategoryId:
977 hr = SetPropertyVal(key, uCat, value);
978 break;
979 default:
980 ATLASSERT(FALSE);
981 break;
982 }
983
984 return hr;
985 }
986
987 HRESULT InvalidateItems()
988 {
989 return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_ItemsSource);
990 }
991
992 HRESULT InvalidateCategories()
993 {
994 return static_cast<TCtrl*>(this)->Invalidate(UI_PKEY_Categories);
995 }
996
997 HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
998 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* /*ppropvarNewValue*/)
999 {
1000 ATLASSERT(nCmdID == TCtrl::GetID());
1001 nCmdID; // avoid level 4 warning
1002
1003 HRESULT hr = E_NOTIMPL;
1004 switch (k_(key))
1005 {
1006 case k_ItemsSource:
1007 {
1008 ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal);
1009 ATLASSERT(pIUICollection);
1010 hr = pIUICollection->Clear();
1011 for (UINT i = 0; i < m_size; i++)
1012 {
1013 if FAILED(hr = pIUICollection->Add(m_apItems[i]))
1014 break;
1015 }
1016 ATLASSERT(SUCCEEDED(hr));
1017 }
1018 break;
1019 case k_Categories:
1020 if (t_categories != 0)
1021 {
1022 ATL::CComQIPtr<IUICollection> pIUICategory(ppropvarCurrentValue->punkVal);
1023 ATLASSERT(pIUICategory.p);
1024 hr = pIUICategory->Clear();
1025 for (UINT i = t_items; i < (t_items + t_categories); i++)
1026 {
1027 if FAILED(hr = pIUICategory->Add(m_apItems[i]))
1028 break;
1029 }
1030 ATLASSERT(SUCCEEDED(hr));
1031 }
1032 break;
1033 }
1034
1035 return hr;
1036 }
1037 };
1038
1039 // TextCollectionImpl: handles item labels and selection
1040 //
1041 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1042 class TextCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories>
1043 {
1044 typedef TextCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1045 public:
1046 typedef thisClass TextCollection;
1047
1048 TextCollectionImpl() : m_uSelected(UI_COLLECTION_INVALIDINDEX)
1049 { }
1050
1051 Text m_asText[t_items];
1052 UINT m_uSelected;
1053
1054 // Operations
1055 HRESULT SetItemText(UINT uItem, LPCWSTR sText, bool bUpdate = false)
1056 {
1057 ATLASSERT(uItem < t_items);
1058
1059 m_asText[uItem] = sText;
1060
1061 return bUpdate ? InvalidateItems() : S_OK;
1062 }
1063
1064 UINT GetSelected()
1065 {
1066 return m_uSelected;
1067 }
1068
1069 HRESULT Select(UINT uItem, bool bUpdate = false)
1070 {
1071 ATLASSERT((uItem < t_items) || (uItem == UI_COLLECTION_INVALIDINDEX));
1072
1073 m_uSelected = uItem;
1074
1075 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1076 return bUpdate ?
1077 ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_SelectedItem, uItem) :
1078 S_OK;
1079 }
1080
1081 // Implementation
1082 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1083 {
1084 ATLASSERT(uItem < t_items);
1085
1086 if (k_(key) == k_Label)
1087 {
1088 if (m_asText[uItem].IsEmpty())
1089 {
1090 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1091 m_asText[uItem] = ribbon.OnRibbonQueryItemText(TCtrl::GetID(), uItem);
1092 }
1093 return SetPropertyVal(key, (LPCWSTR)m_asText[uItem], value);
1094 }
1095 else
1096 {
1097 return Collection::DoGetItem(uItem, key, value);
1098 }
1099 }
1100
1101 HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1102 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1103 {
1104 ATLASSERT(nCmdID == TCtrl::GetID());
1105
1106 if (k_(key) == k_SelectedItem)
1107 {
1108 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1109 UINT uSel = UI_COLLECTION_INVALIDINDEX;
1110 if ((m_uSelected == UI_COLLECTION_INVALIDINDEX) &&
1111 ribbon.OnRibbonQuerySelectedItem(TCtrl::GetID(), uSel))
1112 m_uSelected = uSel;
1113
1114 return SetPropertyVal(key, m_uSelected, ppropvarNewValue);
1115 }
1116 else
1117 {
1118 return Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1119 }
1120 }
1121 };
1122
1123 // ItemCollectionImpl: handles item image
1124 //
1125 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1126 class ItemCollectionImpl : public TextCollectionImpl<TCtrl, t_items, t_categories>
1127 {
1128 typedef ItemCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1129 public:
1130 typedef thisClass ItemCollection;
1131
1132 ItemCollectionImpl()
1133 {
1134 ::ZeroMemory(m_aBitmap, sizeof(m_aBitmap));
1135 }
1136
1137 CBitmap m_aBitmap[t_items];
1138
1139 // Operations
1140 HRESULT SetItemImage(UINT uIndex, HBITMAP hbm, bool bUpdate = false)
1141 {
1142 ATLASSERT(uIndex < t_items);
1143
1144 m_aBitmap[uIndex] = hbm;
1145
1146 return bUpdate ? InvalidateItems() : S_OK;
1147 }
1148
1149 // Implementation
1150 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1151 {
1152 ATLASSERT(uItem < t_items);
1153
1154 if (k_(key) == k_ItemImage)
1155 {
1156 if (m_aBitmap[uItem].IsNull())
1157 {
1158 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1159 m_aBitmap[uItem] = ribbon.OnRibbonQueryItemImage(TCtrl::GetID(), uItem);
1160 }
1161 return m_aBitmap[uItem].IsNull() ?
1162 E_NOTIMPL :
1163 SetPropertyVal(key, GetImage(m_aBitmap[uItem], UI_OWNERSHIP_COPY), value);
1164 }
1165 else
1166 {
1167 return TextCollection::DoGetItem(uItem, key, value);
1168 }
1169 }
1170 };
1171
1172 // ComboCollectionImpl: handles combo text
1173 //
1174 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1175 class ComboCollectionImpl : public ItemCollectionImpl<TCtrl, t_items, t_categories>
1176 {
1177 typedef ComboCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1178 public:
1179 typedef thisClass ComboCollection;
1180
1181 // Operations
1182 HRESULT SetComboText(LPCWSTR sText)
1183 {
1184 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1185 return ribbon.IsRibbonUI() ?
1186 ribbon.SetProperty(TCtrl::GetID(), UI_PKEY_StringValue, sText) :
1187 S_OK;
1188 }
1189
1190 LPCWSTR GetComboText()
1191 {
1192 static WCHAR sCombo[RIBBONUI_MAX_TEXT] = { 0 };
1193 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1194 PROPVARIANT var;
1195 if (ribbon.IsRibbonUI())
1196 {
1197 HRESULT hr = ribbon.GetIUIFrameworkPtr()->GetUICommandProperty(TCtrl::GetID(), UI_PKEY_StringValue, &var);
1198 hr = PropVariantToString(var, sCombo, RIBBONUI_MAX_TEXT);
1199 return sCombo;
1200 }
1201 return NULL;
1202 }
1203 };
1204
1205 // CommandCollectionImpl: handles RibbonUI command collection controls
1206 //
1207 template <class TCtrl, size_t t_items, size_t t_categories = 0>
1208 class CommandCollectionImpl : public CollectionImpl<TCtrl, t_items, t_categories>
1209 {
1210 typedef CommandCollectionImpl<TCtrl, t_items, t_categories> thisClass;
1211 public:
1212 typedef thisClass CommandCollection;
1213
1214 CommandCollectionImpl()
1215 {
1216 ::ZeroMemory(m_auCmd, sizeof(m_auCmd));
1217 ::ZeroMemory(m_aCmdType, sizeof(m_aCmdType));
1218 }
1219
1220 UINT32 m_auCmd[t_items];
1221 BYTE m_aCmdType[t_items];
1222
1223 // Operations
1224 HRESULT SetItemCommand(UINT uItem, UINT32 uCommandID, bool bUpdate = false)
1225 {
1226 ATLASSERT(uItem < t_items);
1227
1228 if (uCommandID == m_auCmd[uItem])
1229 return S_OK;
1230
1231 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1232
1233 m_auCmd[uItem] = uCommandID;
1234 if (uCommandID != 0)
1235 ribbon.UIAddRibbonElement(uCommandID);
1236
1237 return bUpdate ? InvalidateItems() : S_OK;
1238 }
1239
1240 HRESULT SetItemCommandType(UINT uItem, UI_COMMANDTYPE type, bool bUpdate = false)
1241 {
1242 ATLASSERT(uItem < t_items);
1243
1244 m_aCmdType[uItem] = (BYTE)type;
1245
1246 return bUpdate ? InvalidateItems() : S_OK;
1247 }
1248
1249 // Implementation
1250 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1251 {
1252 ATLASSERT(uItem < t_items);
1253 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1254
1255 HRESULT hr = E_FAIL;
1256 switch (k_(key))
1257 {
1258 case k_CommandId:
1259 if (m_auCmd[uItem] == 0)
1260 SetItemCommand(uItem, ribbon.OnRibbonQueryItemCommand(TCtrl::GetID(), uItem));
1261 hr = SetPropertyVal(key, m_auCmd[uItem], value);
1262 break;
1263 case k_CommandType:
1264 if (m_aCmdType[uItem] == UI_COMMANDTYPE_UNKNOWN)
1265 SetItemCommandType(uItem, ribbon.OnRibbonQueryItemCommandType(TCtrl::GetID(), uItem));
1266 hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value);
1267 break;
1268 case k_CategoryId:
1269 default:
1270 hr = Collection::DoGetItem(uItem, key, value);
1271 break;
1272 }
1273
1274 return hr;
1275 }
1276
1277 HRESULT Select(UINT /*uItem*/, bool /*bUpdate*/ = false)
1278 {
1279 ATLASSERT(FALSE);
1280 return S_OK;
1281 }
1282 };
1283
1284 // SimpleCollectionImpl: collection class for ribbon simple collection controls
1285 //
1286 template <class TCtrl, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
1287 class SimpleCollectionImpl : public CollectionImplBase<SimpleCollectionImpl<TCtrl, t_size>, t_size>
1288 {
1289 typedef SimpleCollectionImpl<TCtrl, t_size, t_CommandType> thisClass;
1290 public:
1291 typedef CollectionImplBase<thisClass, t_size> CollectionBase;
1292 typedef thisClass SimpleCollection;
1293
1294 // Implementation
1295 HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1296 {
1297 ATLASSERT(uItem < t_size);
1298 TCtrl::WndRibbon& ribbon = static_cast<TCtrl*>(this)->GetWndRibbon();
1299
1300 HRESULT hr = E_NOTIMPL;
1301 switch (k_(key))
1302 {
1303 case k_ItemImage:
1304 if (HBITMAP hbm = ribbon.DefRibbonQueryItemImage(TCtrl::GetID(), uItem))
1305 hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), value);
1306 break;
1307 case k_Label:
1308 if (LPCWSTR sText = ribbon.DefRibbonQueryItemText(TCtrl::GetID(), uItem))
1309 hr = SetPropertyVal(key, (LPCWSTR)sText, value);
1310 break;
1311 case k_CommandType:
1312 hr = SetPropertyVal(key, t_CommandType, value);
1313 break;
1314 case k_CommandId:
1315 hr = SetPropertyVal(key, ribbon.DefRibbonQueryItemCommand(TCtrl::GetID(), uItem), value);
1316 break;
1317 case k_CategoryId:
1318 hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value);
1319 break;
1320 default:
1321 ATLASSERT(FALSE);
1322 break;
1323 }
1324
1325 return hr;
1326 }
1327 };
1328
1329
1330 ///////////////////////////////////////////////////////////////////////////////
1331 // Ribbon collection control classes
1332
1333 // CollectionCtrlImpl: specializable class for ribbon collection controls
1334 //
1335 template <class T, UINT t_ID, class TCollection>
1336 class CollectionCtrlImpl : public CommandCtrlImpl<T, t_ID>, public TCollection
1337 {
1338 typedef CollectionCtrlImpl<T, t_ID, TCollection> thisClass;
1339 public:
1340 typedef CommandCtrlImpl<T, t_ID> CommandCtrl;
1341 typedef TCollection Collection;
1342
1343 // Implementation
1344 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1345 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1346 {
1347 ATLASSERT(nCmdID == GetID());
1348 ATLASSERT(ppropvarNewValue);
1349
1350 HRESULT hr = Collection::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1351 if FAILED(hr)
1352 hr = CommandCtrl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1353
1354 return hr;
1355 }
1356
1357 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1358 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1359 IUISimplePropertySet* /*pCommandExecutionProperties*/)
1360 {
1361 ATLASSERT (nCmdID == GetID());
1362 nCmdID; // avoid level4 warning
1363
1364 if (key == NULL) // gallery button pressed
1365 {
1366 GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX);
1367 return S_OK;
1368 }
1369
1370 ATLASSERT(k_(*key) == k_SelectedItem);
1371 ATLASSERT(ppropvarValue);
1372
1373 HRESULT hr = S_OK;
1374 UINT32 uSel = 0xffff;
1375 hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel);
1376
1377 if (SUCCEEDED(hr))
1378 {
1379 if (GetWndRibbon().OnRibbonItemSelected(GetID(), verb, uSel))
1380 TCollection::Select(uSel);
1381 }
1382
1383 return hr;
1384 }
1385 };
1386
1387 // ToolbarGalleryCtrlImpl: base class for ribbon toolbar gallery controls
1388 //
1389 template <class T, UINT t_ID, UINT t_idTB, size_t t_size>
1390 class ToolbarGalleryCtrlImpl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>, t_size>>
1391 {
1392 public:
1393 ToolbarGalleryCtrlImpl()
1394 {
1395 CResource tbres;
1396 ATLVERIFY(tbres.Load(RT_TOOLBAR, t_idTB));
1397 _AtlToolBarData* pData = (_AtlToolBarData*)tbres.Lock();
1398 ATLASSERT(pData);
1399 ATLASSERT(pData->wVersion == 1);
1400
1401 WORD* pItems = pData->items();
1402 INT j = 0;
1403 for (int i = 0; (i < pData->wItemCount) && (j < t_size); i++)
1404 {
1405 if (pItems[i] != 0)
1406 {
1407 m_aCmdType[j] = UI_COMMANDTYPE_ACTION;
1408 m_auCmd[j++] = pItems[i];
1409 }
1410 }
1411
1412 if (j < t_size)
1413 Resize(j);
1414 }
1415
1416 HRESULT DoGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1417 {
1418 ATLASSERT(uItem < m_size);
1419 ATLASSERT(m_auCmd[uItem]);
1420
1421 HRESULT hr = E_FAIL;
1422 switch (k_(key))
1423 {
1424 case k_CommandId:
1425 hr = SetPropertyVal(key, m_auCmd[uItem], value);
1426 break;
1427 case k_CommandType:
1428 hr = SetPropertyVal(key, UINT32(m_aCmdType[uItem]), value);
1429 break;
1430 case k_CategoryId:
1431 hr = SetPropertyVal(key, UI_COLLECTION_INVALIDINDEX, value);
1432 break;
1433 default:
1434 ATLASSERT(FALSE);
1435 break;
1436 }
1437
1438 return hr;
1439 }
1440 };
1441
1442
1443 // SimpleCollectionCtrlImpl: base class for simple gallery and listbox controls
1444 //
1445 template <class T, UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
1446 class SimpleCollectionCtrlImpl :
1447 public CommandCtrlImpl<T, t_ID>,
1448 public SimpleCollectionImpl<SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>, t_size, t_CommandType>
1449 {
1450 typedef SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType> thisClass;
1451 public:
1452 typedef thisClass SimpleCollection;
1453
1454 SimpleCollectionCtrlImpl() : m_uSelected(0)
1455 { }
1456
1457 UINT m_uSelected;
1458
1459 HRESULT Select(UINT uItem, bool bUpdate = false)
1460 {
1461 ATLASSERT((uItem < t_size) || (uItem == UI_COLLECTION_INVALIDINDEX));
1462
1463 m_uSelected = uItem;
1464
1465 return bUpdate ?
1466 GetWndRibbon().SetProperty(GetID(), UI_PKEY_SelectedItem, uItem) :
1467 S_OK;
1468 }
1469
1470 // Implementation
1471 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1472 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1473 {
1474 ATLASSERT(nCmdID == GetID());
1475 ATLASSERT(ppropvarNewValue != NULL);
1476
1477 HRESULT hr = S_OK;
1478 switch (k_(key))
1479 {
1480 case k_ItemsSource:
1481 {
1482 ATL::CComQIPtr<IUICollection> pIUICollection(ppropvarCurrentValue->punkVal);
1483 ATLASSERT(pIUICollection.p);
1484 hr = pIUICollection->Clear();
1485 for (UINT i = 0; i < t_size; i++)
1486 {
1487 if FAILED(hr = pIUICollection->Add(m_apItems[i]))
1488 break;
1489 }
1490 ATLASSERT(SUCCEEDED(hr));
1491 }
1492 break;
1493 case k_SelectedItem:
1494 hr = SetPropertyVal(UI_PKEY_SelectedItem, m_uSelected, ppropvarNewValue);
1495 break;
1496 default:
1497 hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1498 break;
1499 }
1500
1501 return hr;
1502 }
1503
1504 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1505 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1506 IUISimplePropertySet* /*pCommandExecutionProperties*/)
1507 {
1508 ATLASSERT (nCmdID == GetID());
1509 nCmdID; // avoid level 4 warning
1510
1511 HRESULT hr = S_OK;
1512 if (key == NULL) // gallery button pressed
1513 {
1514 GetWndRibbon().OnRibbonItemSelected(GetID(), UI_EXECUTIONVERB_EXECUTE, UI_COLLECTION_INVALIDINDEX);
1515 return hr;
1516 }
1517 ATLASSERT(k_(*key) == k_SelectedItem);
1518 ATLASSERT(ppropvarValue);
1519
1520 if SUCCEEDED(hr = UIPropertyToUInt32(*key, *ppropvarValue, &m_uSelected))
1521 GetWndRibbon().OnRibbonItemSelected(GetID(), verb, m_uSelected);
1522
1523 return hr;
1524 }
1525 };
1526
1527 // RecentItemsCtrlImpl
1528 //
1529 template <class T, UINT t_ID, class TDocList = CRecentDocumentList>
1530 class RecentItemsCtrlImpl :
1531 public CtrlImpl<T, t_ID>,
1532 public CollectionImplBase<RecentItemsCtrlImpl<T, t_ID, TDocList>, TDocList::m_nMaxEntries_Max>,
1533 public TDocList
1534 {
1535 typedef RecentItemsCtrlImpl<T, t_ID, TDocList> thisClass;
1536 public:
1537 typedef thisClass RecentItems;
1538
1539 // Implementation
1540 HRESULT OnGetItem(UINT uItem, REFPROPERTYKEY key, PROPVARIANT *value)
1541 {
1542 ATLASSERT((INT)uItem < GetMaxEntries());
1543
1544 LPCWSTR sPath = m_arrDocs[uItem].szDocName;
1545 HRESULT hr = E_NOTIMPL;
1546 switch (k_(key))
1547 {
1548 case k_Label:
1549 hr = SetPropertyVal(key, GetWndRibbon().OnRibbonQueryRecentItemName(sPath), value);
1550 break;
1551 case k_LabelDescription:
1552 hr = SetPropertyVal(key, sPath, value);
1553 break;
1554 default:
1555 ATLASSERT(FALSE);
1556 break;
1557 }
1558
1559 return hr;
1560 }
1561
1562 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1563 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1564 {
1565 ATLASSERT(nCmdID == GetID());
1566 ATLASSERT(ppropvarNewValue);
1567
1568 HRESULT hr = S_OK;
1569 switch (k_(key))
1570 {
1571 case k_RecentItems:
1572 if (SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, m_arrDocs.GetSize()))
1573 {
1574 const int iLastIndex = m_arrDocs.GetSize() - 1;
1575 for (LONG i = 0; i <= iLastIndex; i++)
1576 SafeArrayPutElement(psa, &i, m_apItems[iLastIndex - i]); // reverse order
1577
1578 hr = SetPropertyVal(key, psa, ppropvarNewValue);
1579 SafeArrayDestroy(psa);
1580 }
1581 break;
1582 default:
1583 hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1584 break;
1585 }
1586
1587 return hr;
1588 }
1589
1590 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1591 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1592 IUISimplePropertySet* /*pCommandExecutionProperties*/)
1593 {
1594 ATLASSERT(nCmdID == GetID());
1595 nCmdID; // avoid level 4 warning
1596 ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE);
1597 verb; // avoid level 4 warning
1598 ATLASSERT((key) && (k_(*key) == k_SelectedItem));
1599 ATLASSERT(ppropvarValue);
1600
1601 UINT32 uSel = 0xffff;
1602 HRESULT hr = UIPropertyToUInt32(*key, *ppropvarValue, &uSel);
1603 if SUCCEEDED(hr)
1604 {
1605 ATLASSERT(uSel < (UINT)GetMaxEntries());
1606 GetWndRibbon().DefCommandExecute(ID_FILE_MRU_FIRST + uSel);
1607 }
1608
1609 return hr;
1610 }
1611 };
1612
1613
1614 ///////////////////////////////////////////////////////////////////////////////
1615 // Ribbon stand-alone control classes
1616
1617 // FontCtrlImpl
1618 //
1619 template <class T, UINT t_ID>
1620 class FontCtrlImpl : public CtrlImpl<T, t_ID>
1621 {
1622 public:
1623
1624 CharFormat m_cf;
1625
1626 // Implementation
1627 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1628 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1629 IUISimplePropertySet* pCommandExecutionProperties)
1630 {
1631 ATLASSERT (nCmdID == GetID());
1632 nCmdID; // avoid level 4 warning
1633 ATLASSERT ((key) && (k_(*key) == k_FontProperties));
1634 key; // avoid level 4 warning
1635
1636 HRESULT hr = E_INVALIDARG;
1637 switch (verb)
1638 {
1639 case UI_EXECUTIONVERB_PREVIEW:
1640 case UI_EXECUTIONVERB_EXECUTE:
1641 ATLASSERT(pCommandExecutionProperties);
1642 PROPVARIANT propvar;
1643
1644 if (SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_FontProperties_ChangedProperties, &propvar)))
1645 m_cf << ATL::CComQIPtr<IPropertyStore>(propvar.punkVal);
1646 break;
1647
1648 case UI_EXECUTIONVERB_CANCELPREVIEW:
1649 ATLASSERT(ppropvarValue);
1650 ATL::CComPtr<IPropertyStore> pStore;
1651
1652 if (SUCCEEDED(hr = UIPropertyToInterface(UI_PKEY_FontProperties, *ppropvarValue, &pStore)))
1653 m_cf << pStore;
1654 break;
1655 }
1656
1657 if (SUCCEEDED(hr))
1658 GetWndRibbon().OnRibbonFontCtrlExecute(GetID(), verb, &m_cf);
1659 else
1660 ATLASSERT(FALSE);
1661
1662 return hr;
1663 }
1664
1665 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1666 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1667 {
1668 if ((k_(key) == k_FontProperties) && (GetWndRibbon().OnRibbonQueryFont(t_ID, m_cf)))
1669 {
1670 ATL::CComQIPtr<IPropertyStore> pStore(ppropvarCurrentValue->punkVal);
1671 m_cf >> pStore;
1672 return SetPropertyVal(key, pStore.p, ppropvarNewValue);
1673 }
1674 else
1675 {
1676 return CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1677 }
1678 }
1679 };
1680
1681 // ColorCtrlImpl
1682 //
1683 template <class T, UINT t_ID>
1684 class ColorCtrlImpl : public CommandCtrlImpl<T, t_ID>
1685 {
1686 public:
1687 ColorCtrlImpl() : m_colorType(UI_SWATCHCOLORTYPE_NOCOLOR), m_color(0x800080) /*MAGENTA*/
1688 { }
1689
1690 COLORREF m_color;
1691 UINT32 m_colorType; // value in UI_SWATCHCOLORTYPE
1692 Text m_sLabels[6]; // k_MoreColorsLabel to k_ThemeColorsCategoryLabel
1693 ATL::CSimpleArray<COLORREF> m_aColors[2];
1694 ATL::CSimpleArray<LPCWSTR> m_aTooltips[2];
1695
1696 // Operations
1697 HRESULT SetColor(COLORREF color, bool bUpdate = false)
1698 {
1699 if (m_colorType != UI_SWATCHCOLORTYPE_RGB)
1700 SetColorType(UI_SWATCHCOLORTYPE_RGB, bUpdate);
1701 m_color = color;
1702 return bUpdate ? SetProperty(UI_PKEY_Color, color) : S_OK;
1703 }
1704
1705 HRESULT SetColorType(UI_SWATCHCOLORTYPE type, bool bUpdate = false)
1706 {
1707 m_colorType = type;
1708 return bUpdate ? SetProperty(UI_PKEY_ColorType, type) : S_OK;
1709 }
1710
1711 HRESULT SetColorLabel(REFPROPERTYKEY key, LPCWSTR sLabel, bool bUpdate = false)
1712 {
1713 ATLASSERT((k_(key) >= k_ThemeColorsCategoryLabel) && (k_(key) <= k_MoreColorsLabel));
1714 m_sLabels[k_(key) - k_ThemeColorsCategoryLabel] = sLabel;
1715 return bUpdate ? SetProperty(key, sLabel) : S_OK;
1716 }
1717
1718 HRESULT SetColorArray(REFPROPERTYKEY key, COLORREF* pColor, bool bUpdate = false)
1719 {
1720 ATLASSERT((k_(key) == k_ThemeColors) || (k_(key) == k_StandardColors));
1721
1722 const INT ic = k_(key) - k_ThemeColors;
1723 m_aColors[ic].RemoveAll();
1724 while (*pColor != 0x800080) /*MAGENTA*/
1725 m_aColors[ic].Add(*pColor++);
1726
1727 if (bUpdate)
1728 {
1729 PROPVARIANT var;
1730 if SUCCEEDED(InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), m_aColors[ic].GetSize(), &var))
1731 return SetProperty(key, var);
1732 else
1733 return E_INVALIDARG;
1734 }
1735 else
1736 {
1737 return S_OK;
1738 }
1739 }
1740
1741 HRESULT SetColorTooltips(REFPROPERTYKEY key, LPCWSTR* ppsTT, bool bUpdate = false)
1742 {
1743 ATLASSERT((k_(key) == k_ThemeColorsTooltips) || (k_(key) == k_StandardColorsTooltips));
1744
1745 const INT ic = k_(key) - k_ThemeColorsTooltips;
1746 m_aTooltips[ic].RemoveAll();
1747 while (*ppsTT)
1748 m_aTooltips[ic].Add(*ppsTT++);
1749
1750 if (bUpdate)
1751 {
1752 PROPVARIANT var;
1753 if SUCCEEDED(InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), m_aTooltips[ic].GetSize(), &var))
1754 return SetProperty(key, var);
1755 else
1756 return E_INVALIDARG;
1757 }
1758 else
1759 {
1760 return S_OK;
1761 }
1762 }
1763
1764 // Implementation
1765 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1766 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1767 IUISimplePropertySet* pCommandExecutionProperties)
1768 {
1769 ATLASSERT (nCmdID == GetID());
1770 nCmdID; // avoid level 4 warning
1771 ATLASSERT (key && (k_(*key) == k_ColorType));
1772 key; // avoid level 4 warning
1773 ATLASSERT (ppropvarValue);
1774
1775 HRESULT hr = PropVariantToUInt32(*ppropvarValue, &m_colorType);
1776 ATLASSERT(SUCCEEDED(hr));
1777
1778 if (SUCCEEDED(hr) && (m_colorType == UI_SWATCHCOLORTYPE_RGB))
1779 {
1780 ATLASSERT(pCommandExecutionProperties);
1781 PROPVARIANT var;
1782 if SUCCEEDED(hr = pCommandExecutionProperties->GetValue(UI_PKEY_Color, &var))
1783 hr = PropVariantToUInt32(var, &m_color);
1784 }
1785
1786 if SUCCEEDED(hr)
1787 GetWndRibbon().OnRibbonColorCtrlExecute(GetID(), verb, (UI_SWATCHCOLORTYPE)m_colorType/*uType*/, m_color);
1788 else
1789 ATLASSERT(FALSE); // something was wrong
1790
1791 return hr;
1792 }
1793
1794 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
1795 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
1796 {
1797 ATLASSERT (nCmdID == GetID());
1798
1799 HRESULT hr = E_NOTIMPL;
1800
1801 switch (k_(key))
1802 {
1803 case k_ColorType:
1804 hr = SetPropertyVal(key, m_colorType, ppropvarNewValue);
1805 break;
1806 case k_Color:
1807 if (m_color == 0x800080) /*MAGENTA*/
1808 m_color = GetWndRibbon().OnRibbonQueryColor(GetID());
1809 hr = SetPropertyVal(key, m_color, ppropvarNewValue);
1810 break;
1811 case k_ColorMode:
1812 break;
1813 case k_ThemeColorsCategoryLabel:
1814 case k_StandardColorsCategoryLabel:
1815 case k_RecentColorsCategoryLabel:
1816 case k_AutomaticColorLabel:
1817 case k_NoColorLabel:
1818 case k_MoreColorsLabel:
1819 {
1820 const UINT iLabel = k_(key) - k_ThemeColorsCategoryLabel;
1821 if (m_sLabels[iLabel].IsEmpty())
1822 if (LPCWSTR psLabel = GetWndRibbon().OnRibbonQueryColorLabel(GetID(), key))
1823 m_sLabels[iLabel] = psLabel;
1824 if (!m_sLabels[iLabel].IsEmpty())
1825 hr = SetPropertyVal(key, (LPCWSTR)m_sLabels[iLabel], ppropvarNewValue);
1826 }
1827 break;
1828 case k_ThemeColors:
1829 case k_StandardColors:
1830 {
1831 const INT ic = k_(key) - k_ThemeColors;
1832 if (!m_aColors[ic].GetSize())
1833 if (COLORREF* pColor = GetWndRibbon().OnRibbonQueryColorArray(GetID(), key))
1834 SetColorArray(key, pColor);
1835 if (INT iMax = m_aColors[ic].GetSize())
1836 hr = InitPropVariantFromUInt32Vector(m_aColors[ic].GetData(), iMax, ppropvarNewValue);
1837 }
1838 break;
1839 case k_ThemeColorsTooltips:
1840 case k_StandardColorsTooltips:
1841 {
1842 const INT ic = k_(key) - k_ThemeColorsTooltips;
1843 if (m_aTooltips[ic].GetSize() == 0)
1844 if (LPCWSTR* ppsTT = GetWndRibbon().OnRibbonQueryColorTooltips(GetID(), key))
1845 SetColorTooltips(key, ppsTT);
1846 if (INT iMax = m_aTooltips[ic].GetSize())
1847 hr = InitPropVariantFromStringVector(m_aTooltips[ic].GetData(), iMax, ppropvarNewValue);
1848 }
1849 break;
1850 default:
1851 hr = CommandCtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
1852 break;
1853 }
1854
1855 return hr;
1856 }
1857 };
1858
1859 // SpinnerCtrlImpl
1860 //
1861 template <class T, UINT t_ID, typename V = LONG>
1862 class SpinnerCtrlImpl : public CtrlImpl<T, t_ID>
1863 {
1864 public:
1865 SpinnerCtrlImpl()
1866 {
1867 m_Values[0] = m_Values[2] = m_Values[4] = 0;
1868 m_Values[1] = 100;
1869 m_Values[3] = 1;
1870 }
1871
1872 V m_Values[5];
1873 // k_DecimalValue = 201, k_MaxValue = 203, k_MinValue, k_Increment, k_DecimalPlaces
1874
1875 Text m_FormatString;
1876 Text m_RepresentativeString;
1877
1878 // Operations
1879 HRESULT SetDecimalPlaces(V vPlaces, bool bUpdate = false)
1880 {
1881 return SetValue(UI_PKEY_DecimalPlaces, vPlaces, bUpdate);
1882 }
1883
1884 HRESULT SetMin(V vMin, bool bUpdate = false)
1885 {
1886 return SetValue(UI_PKEY_MinValue, vMin, bUpdate);
1887 }
1888
1889 HRESULT SetMax(V vMax, bool bUpdate = false)
1890 {
1891 return SetValue(UI_PKEY_MaxValue, vMax, bUpdate);
1892 }
1893
1894 HRESULT SetVal(V vVal, bool bUpdate = false)
1895 {
1896 return SetValue(UI_PKEY_DecimalValue, vVal, bUpdate);
1897 }
1898
1899 HRESULT SetIncrement(V vIncrement, bool bUpdate = false)
1900 {
1901 return SetValue(UI_PKEY_Increment, vIncrement, bUpdate);
1902 }
1903
1904 HRESULT SetFormatString(LPCWSTR sFormat, bool bUpdate = false)
1905 {
1906 return SetText(UI_PKEY_FormatString, sFormat, bUpdate);
1907 }
1908
1909 HRESULT SetRepresentativeString(LPCWSTR sRepresentative, bool bUpdate = false)
1910 {
1911 return SetText(UI_PKEY_RepresentativeString, sRepresentative, bUpdate);
1912 }
1913
1914 // Implementation
1915 HRESULT SetText(REFPROPERTYKEY key, LPCWSTR sText, bool bUpdate = false)
1916 {
1917 switch (k_(key))
1918 {
1919 case k_FormatString:
1920 m_FormatString = sText;
1921 break;
1922 case k_RepresentativeString:
1923 m_RepresentativeString = sText;
1924 break;
1925 default:
1926 return CtrlImpl::SetText(key, sText, bUpdate);
1927 }
1928
1929 return bUpdate ?
1930 GetWndRibbon().InvalidateProperty(GetID(), key) :
1931 S_OK;
1932 }
1933
1934 HRESULT SetValue(REFPROPERTYKEY key, V val, bool bUpdate = false)
1935 {
1936 ATLASSERT((k_(key) <= k_DecimalPlaces) && (k_(key) >= k_DecimalValue));
1937
1938 const INT iVal = k_(key) == k_DecimalValue ? 0 : k_(key) - k_StringValue;
1939 m_Values[iVal] = val;
1940
1941 if (bUpdate)
1942 {
1943 if(k_(key) == k_DecimalValue)
1944 {
1945 DECIMAL decVal;
1946 InitDecimal(val, &decVal);
1947 return SetProperty(key, &decVal);
1948 }
1949 else
1950 {
1951 return GetWndRibbon().InvalidateProperty(GetID(), key);
1952 }
1953 }
1954 else
1955 {
1956 return S_OK;
1957 }
1958 }
1959
1960 HRESULT QueryValue(REFPROPERTYKEY key, LONG* plVal)
1961 {
1962 return GetWndRibbon().OnRibbonQuerySpinnerValue(GetID(), key, plVal) ? S_OK : S_FALSE;
1963 }
1964
1965 HRESULT QueryValue(REFPROPERTYKEY key, DOUBLE* pdVal)
1966 {
1967 return GetWndRibbon().OnRibbonQueryFloatSpinnerValue(GetID(), key, pdVal) ? S_OK : S_FALSE;
1968 }
1969
1970 HRESULT OnGetValue(REFPROPERTYKEY key, PROPVARIANT* ppv)
1971 {
1972 ATLASSERT((k_(key) <= k_DecimalPlaces) && (k_(key) >= k_DecimalValue));
1973
1974 const INT iVal = k_(key) == k_DecimalValue ? 0 : k_(key) - k_StringValue;
1975
1976 QueryValue(key, m_Values + iVal);
1977
1978 if (k_(key) == k_DecimalPlaces)
1979 {
1980 return SetPropertyVal(key, m_Values[iVal], ppv);
1981 }
1982 else
1983 {
1984 DECIMAL decVal;
1985 InitDecimal(m_Values[iVal], &decVal);
1986 return SetPropertyVal(key, &decVal, ppv);
1987 }
1988 }
1989
1990 HRESULT OnGetText(REFPROPERTYKEY key, Text& sVal, PROPVARIANT* ppv)
1991 {
1992 if (LPCWSTR sNew = GetWndRibbon().OnRibbonQueryText(GetID(), key))
1993 sVal = sNew;
1994 return SetPropertyVal(key, (LPCWSTR)sVal, ppv);
1995 }
1996
1997 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
1998 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
1999 IUISimplePropertySet* /*pCommandExecutionProperties*/)
2000 {
2001 ATLASSERT (nCmdID == GetID());
2002 nCmdID; // avoid level 4 warning
2003 ATLASSERT (key && (k_(*key) == k_DecimalValue));
2004 key; // avoid level 4 warning
2005 ATLASSERT (verb == UI_EXECUTIONVERB_EXECUTE);
2006 verb; // avoid level 4 warning
2007
2008 DECIMAL decVal;
2009
2010 HRESULT hr = UIPropertyToDecimal(UI_PKEY_DecimalValue, *ppropvarValue, &decVal);
2011 hr = InitVal(m_Values[0], &decVal);
2012
2013 GetWndRibbon().OnRibbonSpinnerCtrlExecute(GetID(), &m_Values[0]);
2014
2015 return hr;
2016 }
2017
2018 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
2019 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
2020 {
2021 ATLASSERT (nCmdID == GetID());
2022
2023 HRESULT hr = E_NOTIMPL;
2024 switch (k_(key))
2025 {
2026 case k_DecimalPlaces:
2027 case k_DecimalValue:
2028 case k_Increment:
2029 case k_MaxValue:
2030 case k_MinValue:
2031 hr = OnGetValue(key, ppropvarNewValue);
2032 break;
2033 case k_FormatString:
2034 if (m_FormatString.IsEmpty())
2035 return OnGetText(key, m_FormatString, ppropvarNewValue);
2036 break;
2037 case k_RepresentativeString:
2038 if (m_RepresentativeString.IsEmpty())
2039 return OnGetText(key, m_RepresentativeString, ppropvarNewValue);
2040 break;
2041 default:
2042 hr = CtrlImpl::DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
2043 break;
2044 }
2045
2046 return hr;
2047 }
2048
2049 // decimal conversion helpers
2050 static HRESULT InitDecimal(LONG& val, DECIMAL* pDecimal)
2051 {
2052 return ::VarDecFromI4(val, pDecimal);
2053 }
2054
2055 static HRESULT InitDecimal(DOUBLE& val, DECIMAL* pDecimal)
2056 {
2057 return ::VarDecFromR8(val, pDecimal);
2058 }
2059
2060 static HRESULT InitVal(LONG& val, const DECIMAL* pDecimal)
2061 {
2062 return ::VarI4FromDec(pDecimal, &val);
2063 }
2064
2065 static HRESULT InitVal(DOUBLE& val, const DECIMAL* pDecimal)
2066 {
2067 return ::VarR8FromDec(pDecimal, &val);
2068 }
2069 };
2070
2071 // CRibbonImpl Ribbon implementation class
2072 //
2073 template <class T>
2074 class CRibbonImpl :
2075 public CRibbonUpdateUI<T>,
2076 public ICtrl,
2077 public IUIApplication,
2078 public IUICommandHandler
2079 {
2080 typedef CRibbonImpl<T> thisClass;
2081 public:
2082 typedef thisClass Ribbon;
2083 typedef T WndRibbon;
2084
2085 CRibbonImpl() : m_bRibbonUI(false), m_hgRibbonSettings(NULL)
2086 {
2087 #ifdef _DEBUG
2088 m_cRef = 1;
2089 #endif
2090 pWndRibbon = static_cast<T*>(this);
2091 HRESULT hr = ::CoInitialize(NULL);
2092 if(SUCCEEDED(hr))
2093 if (RunTimeHelper::IsRibbonUIAvailable())
2094 hr = m_pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework);
2095 else
2096 ATLTRACE2(atlTraceUI, 0, _T("Ribbon UI not available\n"));
2097
2098 if FAILED(hr)
2099 ATLTRACE2(atlTraceUI, 0, _T("Ribbon construction failed\n"));
2100
2101 ATLASSERT(SUCCEEDED(hr));
2102 }
2103
2104 ~CRibbonImpl()
2105 {
2106 ::GlobalFree(m_hgRibbonSettings);
2107 m_pIUIFramework.Release();
2108 ::CoUninitialize();
2109 }
2110
2111 ICtrl& GetRibbonCtrl(UINT)
2112 {
2113 return static_cast<ICtrl&>(*this);
2114 }
2115
2116 ATL::CComPtr<IUIFramework> m_pIUIFramework;
2117 HGLOBAL m_hgRibbonSettings;
2118 bool m_bRibbonUI;
2119
2120 bool IsRibbonUI()
2121 {
2122 return m_bRibbonUI;
2123 }
2124
2125 IUIFramework* GetIUIFrameworkPtr()
2126 {
2127 return m_pIUIFramework;
2128 }
2129
2130 template <typename I>
2131 I* GetRibbonViewPtr(UINT32 uID)
2132 {
2133 ATLASSERT(m_pIUIFramework);
2134 ATL::CComPtr<I> pI;
2135 return m_pIUIFramework->GetView(uID, __uuidof(I), (void**) &pI) == S_OK ?
2136 pI :
2137 NULL;
2138 }
2139
2140 IUIRibbon* GetRibbonPtr()
2141 {
2142 return GetRibbonViewPtr<IUIRibbon>(0);
2143 }
2144
2145 IUIContextualUI* GetMenuPtr(UINT32 uID)
2146 {
2147 ATLASSERT(uID);
2148 return GetRibbonViewPtr<IUIContextualUI>(uID);
2149 }
2150
2151 UINT GetRibbonHeight()
2152 {
2153 ATLASSERT(IsRibbonUI());
2154
2155 UINT32 cy = 0;
2156 if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
2157 pIUIRibbon->GetHeight(&cy);
2158 return cy;
2159 }
2160
2161 HRESULT CreateRibbon(LPCWSTR sResName = L"APPLICATION_RIBBON")
2162 {
2163 T* pT = static_cast<T*>(this);
2164 ATLASSERT(GetIUIFrameworkPtr() && !IsRibbonUI());
2165 ATLASSERT(pT->IsWindow());
2166
2167 HRESULT hr = m_pIUIFramework->Initialize(pT->m_hWnd, this);
2168
2169 if (hr == S_OK)
2170 hr = m_pIUIFramework->LoadUI(ModuleHelper::GetResourceInstance(), sResName);
2171
2172 return hr;
2173 }
2174
2175 HRESULT DestroyRibbon()
2176 {
2177 T* pT = static_cast<T*>(this);
2178 ATLASSERT(GetIUIFrameworkPtr() && IsRibbonUI());
2179 ATLASSERT(pT->IsWindow());
2180
2181 HRESULT hRes = m_pIUIFramework->Destroy();
2182 if (!RunTimeHelper::IsWin7())
2183 pT->SetWindowRgn(NULL, TRUE); // Vista Basic bug workaround
2184 return hRes;
2185 }
2186
2187 // Ribbon persistency
2188 HRESULT operator >>(IStream* pIStream)
2189 {
2190 ATLASSERT(GetIUIFrameworkPtr());
2191 ATLASSERT(pIStream);
2192
2193 HRESULT hr = E_FAIL;
2194 if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
2195 {
2196 const LARGE_INTEGER li0 = { 0 };
2197 pIStream->Seek(li0, STREAM_SEEK_SET, NULL);
2198 hr = pIUIRibbon->SaveSettingsToStream(pIStream);
2199 pIStream->Commit(STGC_DEFAULT);
2200 }
2201
2202 return hr;
2203 }
2204
2205 HRESULT operator <<(IStream* pIStream)
2206 {
2207 ATLASSERT(GetIUIFrameworkPtr());
2208 ATLASSERT(pIStream);
2209
2210 HRESULT hr = E_FAIL;
2211 if (ATL::CComPtr<IUIRibbon> pIUIRibbon = GetRibbonPtr())
2212 {
2213 const LARGE_INTEGER li0 = { 0 };
2214 pIStream->Seek(li0, STREAM_SEEK_SET, NULL);
2215 hr = pIUIRibbon->LoadSettingsFromStream(pIStream);
2216 }
2217
2218 return hr;
2219 }
2220
2221 void ResetRibbonSettings()
2222 {
2223 if (m_hgRibbonSettings != NULL)
2224 {
2225 ::GlobalFree(m_hgRibbonSettings);
2226 m_hgRibbonSettings = NULL;
2227 }
2228 }
2229
2230 HRESULT SaveRibbonSettings()
2231 {
2232 ATLASSERT(GetIUIFrameworkPtr());
2233 ATLASSERT(static_cast<T*>(this)->IsWindow());
2234
2235 HRESULT hr = E_FAIL;
2236 ATL::CComPtr<IStream> pIStream;
2237
2238 if SUCCEEDED(hr = ::CreateStreamOnHGlobal(m_hgRibbonSettings, FALSE, &pIStream))
2239 hr = *this >> pIStream;
2240
2241 if (SUCCEEDED(hr) && (m_hgRibbonSettings == NULL))
2242 hr = ::GetHGlobalFromStream(pIStream, &m_hgRibbonSettings);
2243
2244 if FAILED(hr)
2245 ResetRibbonSettings();
2246
2247 return hr;
2248 }
2249
2250 HRESULT RestoreRibbonSettings()
2251 {
2252 ATLASSERT(GetIUIFrameworkPtr());
2253 ATLASSERT(m_hgRibbonSettings);
2254 ATLASSERT(static_cast<T*>(this)->IsWindow());
2255
2256 HRESULT hr = E_FAIL;
2257 ATL::CComPtr<IStream> pIStream;
2258
2259 if SUCCEEDED(hr = ::CreateStreamOnHGlobal(m_hgRibbonSettings, FALSE, &pIStream))
2260 hr = *this << pIStream;
2261
2262 if FAILED(hr)
2263 ResetRibbonSettings();
2264
2265 return hr;
2266 }
2267
2268 // QAT dock states
2269 UI_CONTROLDOCK GetQATDock()
2270 {
2271 ATLASSERT(GetIUIFrameworkPtr());
2272 ATLASSERT(IsRibbonUI());
2273
2274 UINT32 uDock = 0;
2275 PROPVARIANT propvar;
2276 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2277
2278 if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(UI_PKEY_QuickAccessToolbarDock, &propvar)) &&
2279 SUCCEEDED(UIPropertyToUInt32(UI_PKEY_QuickAccessToolbarDock, propvar, &uDock)))
2280 return (UI_CONTROLDOCK)uDock;
2281
2282 ATLASSERT(FALSE); // something was wrong
2283 return (UI_CONTROLDOCK)0;
2284 }
2285
2286 bool SetQATDock(UI_CONTROLDOCK dockState)
2287 {
2288 ATLASSERT(GetIUIFrameworkPtr());
2289 ATLASSERT(IsRibbonUI());
2290
2291 PROPVARIANT propvar;
2292 ATLVERIFY(SUCCEEDED(SetPropertyVal(UI_PKEY_QuickAccessToolbarDock, dockState, &propvar)));
2293
2294 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2295 if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(UI_PKEY_QuickAccessToolbarDock, propvar)))
2296 {
2297 pIPS->Commit();
2298 return true;
2299 }
2300
2301 ATLASSERT(FALSE); // something was wrong
2302 return false;
2303 }
2304
2305 // Ribbon display states
2306 bool GetRibbonDisplayState(REFPROPERTYKEY key)
2307 {
2308 ATLASSERT(GetIUIFrameworkPtr());
2309 ATLASSERT(IsRibbonUI());
2310 ATLASSERT((k_(key) == k_Viewable) || (k_(key) == k_Minimized));
2311
2312 PROPVARIANT propvar;
2313 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2314
2315 if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(key, &propvar)))
2316 {
2317 BOOL bState = FALSE;
2318 if SUCCEEDED(UIPropertyToBoolean(key, propvar, &bState))
2319 return (bState != FALSE);
2320 }
2321
2322 ATLASSERT(FALSE); // something was wrong
2323 return false;
2324 }
2325
2326 bool SetRibbonDisplayState(REFPROPERTYKEY key, bool bState = true)
2327 {
2328 ATLASSERT(GetIUIFrameworkPtr());
2329 ATLASSERT(IsRibbonUI());
2330 ATLASSERT((k_(key) == k_Viewable) || (k_(key) == k_Minimized));
2331
2332 PROPVARIANT propvar;
2333 ATLVERIFY(SUCCEEDED(SetPropertyVal(key, bState, &propvar)));
2334
2335 ATL::CComQIPtr<IPropertyStore>pIPS(GetRibbonPtr());
2336
2337 if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(key, propvar)))
2338 {
2339 pIPS->Commit();
2340 return true;
2341 }
2342
2343 ATLASSERT(FALSE); // something was wrong
2344 return false;
2345 }
2346
2347 bool IsRibbonMinimized()
2348 {
2349 return GetRibbonDisplayState(UI_PKEY_Minimized);
2350 }
2351
2352 bool MinimizeRibbon(bool bMinimize = true)
2353 {
2354 return SetRibbonDisplayState(UI_PKEY_Minimized, bMinimize);
2355 }
2356
2357 bool IsRibbonHidden()
2358 {
2359 return !GetRibbonDisplayState(UI_PKEY_Viewable);
2360 }
2361
2362 bool HideRibbon(bool bHide = true)
2363 {
2364 return SetRibbonDisplayState(UI_PKEY_Viewable, !bHide);
2365 }
2366
2367 // Ribbon colors
2368 UI_HSBCOLOR GetRibbonColor(REFPROPERTYKEY key)
2369 {
2370 ATLASSERT(GetIUIFrameworkPtr());
2371 ATLASSERT(IsRibbonUI());
2372 ATLASSERT((k_(key) >= k_GlobalBackgroundColor) && (k_(key) <= k_GlobalTextColor));
2373
2374 PROPVARIANT propvar;
2375 ATL::CComQIPtr<IPropertyStore>pIPS(GetIUIFrameworkPtr());
2376
2377 if ((pIPS != NULL) && SUCCEEDED(pIPS->GetValue(key, &propvar)))
2378 {
2379 UINT32 color = 0;
2380 if SUCCEEDED(UIPropertyToUInt32(key, propvar, &color))
2381 return color;
2382 }
2383
2384 ATLASSERT(FALSE); // something was wrong
2385 return 0;
2386 }
2387
2388 bool SetRibbonColor(REFPROPERTYKEY key, UI_HSBCOLOR color)
2389 {
2390 ATLASSERT(GetIUIFrameworkPtr());
2391 ATLASSERT(IsRibbonUI());
2392 ATLASSERT((k_(key) >= k_GlobalBackgroundColor) && (k_(key) <= k_GlobalTextColor));
2393
2394 PROPVARIANT propvar;
2395 ATLVERIFY(SUCCEEDED(SetPropertyVal(key, color, &propvar)));
2396
2397 ATL::CComQIPtr<IPropertyStore>pIPS(GetIUIFrameworkPtr());
2398
2399 if ((pIPS != NULL) && SUCCEEDED(pIPS->SetValue(key, propvar)))
2400 {
2401 pIPS->Commit();
2402 return true;
2403 }
2404
2405 ATLASSERT(FALSE); // something was wrong
2406 return false;
2407 }
2408
2409 // Ribbon modes
2410 HRESULT SetRibbonModes(INT32 iModes)
2411 {
2412 ATLASSERT(IsRibbonUI());
2413 return GetIUIFrameworkPtr()->SetModes(iModes);
2414 }
2415
2416 // Ribbon contextual tab
2417 UI_CONTEXTAVAILABILITY GetRibbonContextAvail(UINT32 uID)
2418 {
2419 ATLASSERT(GetIUIFrameworkPtr());
2420
2421 PROPVARIANT propvar;
2422 if (IsRibbonUI() &&
2423 SUCCEEDED(GetIUIFrameworkPtr()->GetUICommandProperty(uID, UI_PKEY_ContextAvailable, &propvar)))
2424 {
2425 UINT uav;
2426 if (SUCCEEDED(PropVariantToUInt32(propvar, &uav)))
2427 {
2428 CUpdateUIBase::UIEnable(uID, uav != UI_CONTEXTAVAILABILITY_NOTAVAILABLE);
2429 CUpdateUIBase::UISetCheck(uID, uav == UI_CONTEXTAVAILABILITY_ACTIVE);
2430 return (UI_CONTEXTAVAILABILITY)uav;
2431 }
2432 }
2433
2434 return UI_CONTEXTAVAILABILITY_NOTAVAILABLE;
2435 }
2436
2437 HRESULT SetRibbonContextAvail(UINT32 uID, UI_CONTEXTAVAILABILITY cav)
2438 {
2439 CUpdateUIBase::UIEnable(uID, cav != UI_CONTEXTAVAILABILITY_NOTAVAILABLE);
2440 CUpdateUIBase::UISetCheck(uID, cav == UI_CONTEXTAVAILABILITY_ACTIVE);
2441
2442 return SetProperty((WORD)uID, UI_PKEY_ContextAvailable, UINT32(cav));
2443 }
2444
2445 // Ribbon context menu
2446 bool HasRibbonMenu(UINT32 uID)
2447 {
2448 ATL::CComPtr<IUIContextualUI> pI = GetMenuPtr(uID);
2449 return pI != NULL;
2450 }
2451
2452 HRESULT TrackRibbonMenu(UINT32 uID, INT32 x, INT32 y)
2453 {
2454 ATLASSERT(HasRibbonMenu(uID));
2455
2456 return IsRibbonUI() ?
2457 ATL::CComPtr<IUIContextualUI>(GetMenuPtr(uID))->ShowAtLocation(x, y) :
2458 E_FAIL;
2459 }
2460
2461 HRESULT TrackRibbonMenu(UINT32 uID, LPARAM lParam)
2462 {
2463 return TrackRibbonMenu(uID, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
2464 }
2465
2466 // Overrideables
2467 HBITMAP OnRibbonQueryImage(UINT nCmdID, REFPROPERTYKEY /*key*/)
2468 {
2469 return DefRibbonQueryImage(nCmdID);
2470 }
2471
2472 LPCWSTR OnRibbonQueryText(UINT nCmdID, REFPROPERTYKEY key)
2473 {
2474 return DefRibbonQueryText(nCmdID, key);
2475 }
2476
2477 bool OnRibbonQueryState(UINT nCmdID, REFPROPERTYKEY key)
2478 {
2479 return DefRibbonQueryState(nCmdID, key);
2480 }
2481
2482 UI_CONTEXTAVAILABILITY OnRibbonQueryTabAvail(UINT nCmdID)
2483 {
2484 DWORD dwState = UIGetState(nCmdID);
2485 return ((dwState & UPDUI_DISABLED) == UPDUI_DISABLED) ?
2486 UI_CONTEXTAVAILABILITY_NOTAVAILABLE :
2487 (((dwState & UPDUI_CHECKED) == UPDUI_CHECKED) ?
2488 UI_CONTEXTAVAILABILITY_ACTIVE :
2489 UI_CONTEXTAVAILABILITY_AVAILABLE);
2490 }
2491
2492 LPCWSTR OnRibbonQueryComboText(UINT32 /*uCtrlID*/)
2493 {
2494 return NULL;
2495 }
2496
2497 LPCWSTR OnRibbonQueryCategoryText(UINT32 /*uCtrlID*/, UINT32 /*uCat*/)
2498 {
2499 return L"Category";
2500 }
2501
2502 UINT32 OnRibbonQueryItemCategory(UINT32 /*uCtrlID*/, UINT32 /*uItem*/)
2503 {
2504 return 0;
2505 }
2506
2507 LPCWSTR OnRibbonQueryItemText(UINT32 uCtrlID, UINT32 uItem)
2508 {
2509 return DefRibbonQueryItemText(uCtrlID, uItem);
2510 }
2511
2512 bool OnRibbonQuerySelectedItem(UINT32 /*uCtrlID*/, UINT32& /*uSel*/)
2513 {
2514 return false;
2515 }
2516
2517 HBITMAP OnRibbonQueryItemImage(UINT32 uCtrlID, UINT32 uItem)
2518 {
2519 return DefRibbonQueryItemImage(uCtrlID, uItem);
2520 }
2521
2522 UINT32 OnRibbonQueryItemCommand(UINT32 uCtrlID, UINT32 uItem)
2523 {
2524 return DefRibbonQueryItemCommand(uCtrlID, uItem);
2525 }
2526
2527 UI_COMMANDTYPE OnRibbonQueryItemCommandType(UINT32 /*uCtrlID*/, UINT32 /*uItem*/)
2528 {
2529 return UI_COMMANDTYPE_ACTION;
2530 }
2531
2532 LPCWSTR OnRibbonQueryRecentItemName(LPCWSTR sPath)
2533 {
2534 return ::PathFindFileName(sPath);
2535 }
2536
2537 bool OnRibbonQueryFont(UINT /*nId*/, CHARFORMAT2& /*cf*/)
2538 {
2539 return false;
2540 }
2541
2542 bool OnRibbonQuerySpinnerValue(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/, LONG* /*pVal*/)
2543 {
2544 return false;
2545 }
2546
2547 bool OnRibbonQueryFloatSpinnerValue(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/, DOUBLE* /*pVal*/)
2548 {
2549 return false;
2550 }
2551
2552 COLORREF OnRibbonQueryColor(UINT /*nCmdID*/)
2553 {
2554 return 0x800080; /*MAGENTA*/
2555 }
2556
2557 LPCWSTR OnRibbonQueryColorLabel(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
2558 {
2559 return NULL;
2560 }
2561
2562 COLORREF* OnRibbonQueryColorArray(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
2563 {
2564 return NULL;
2565 }
2566
2567 LPCWSTR* OnRibbonQueryColorTooltips(UINT /*nCmdID*/, REFPROPERTYKEY /*key*/)
2568 {
2569 return NULL;
2570 }
2571
2572 bool OnRibbonItemSelected(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UINT32 uItem)
2573 {
2574 DefCommandExecute(MAKELONG(uCtrlID, verb), uItem);
2575 return true;
2576 }
2577
2578 void OnRibbonColorCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UI_SWATCHCOLORTYPE uType, COLORREF color)
2579 {
2580 DefRibbonColorCtrlExecute(uCtrlID, verb, uType, color);
2581 }
2582
2583 void OnRibbonFontCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, CHARFORMAT2* pcf)
2584 {
2585 DefCommandExecute(MAKELONG(uCtrlID, verb), (LPARAM)pcf);
2586 }
2587
2588 void OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID, LONG* pVal)
2589 {
2590 DefCommandExecute(uCtrlID, *pVal);
2591 }
2592
2593 void OnRibbonSpinnerCtrlExecute(UINT32 uCtrlID, DOUBLE* pVal)
2594 {
2595 DefCommandExecute(uCtrlID, (LPARAM)pVal);
2596 }
2597
2598 void OnRibbonCommandExecute(UINT32 uCmdID)
2599 {
2600 DefCommandExecute(uCmdID);
2601 }
2602
2603 // Default implementations
2604 HBITMAP DefRibbonQueryImage(UINT nCmdID)
2605 {
2606 return AtlLoadBitmapImage(nCmdID, LR_CREATEDIBSECTION);
2607 }
2608
2609 bool DefRibbonQueryState(UINT nCmdID, REFPROPERTYKEY key)
2610 {
2611 DWORD dwState = UIGetState(nCmdID);
2612 bool bRet = false;
2613 switch (k_(key))
2614 {
2615 case k_BooleanValue:
2616 bRet = (dwState & UPDUI_CHECKED) == UPDUI_CHECKED;
2617 break;
2618 case k_Enabled:
2619 bRet = (dwState & UPDUI_DISABLED) != UPDUI_DISABLED;
2620 break;
2621 default:
2622 ATLASSERT(FALSE);
2623 break;
2624 }
2625
2626 return bRet;
2627 }
2628
2629 LPCTSTR DefRibbonQueryText(UINT nCmdID, REFPROPERTYKEY key)
2630 {
2631 static WCHAR sText[RIBBONUI_MAX_TEXT] = { 0 };
2632
2633 if (k_(key) == k_Label)
2634 return UIGetText(nCmdID);
2635
2636 if (AtlLoadString(nCmdID, sText, RIBBONUI_MAX_TEXT))
2637 {
2638 PWCHAR pTitle = wcschr(sText, L'\n');
2639 switch (k_(key))
2640 {
2641 case k_Keytip:
2642 if (PWCHAR pAmp = wcschr(sText, L'&'))
2643 pTitle = pAmp;
2644 if (pTitle != NULL)
2645 *(pTitle + 2) = NULL; // fall through
2646 case k_TooltipTitle:
2647 return pTitle ? ++pTitle : NULL;
2648 case k_TooltipDescription:
2649 case k_LabelDescription:
2650 if (pTitle != NULL)
2651 *pTitle = NULL;
2652 return sText;
2653 }
2654 }
2655
2656 return NULL;
2657 }
2658
2659 LPCWSTR DefRibbonQueryItemText(UINT32 uCtrlID, UINT32 uItem)
2660 {
2661 return DefRibbonQueryText(uCtrlID + 1 + uItem, UI_PKEY_LabelDescription);
2662 }
2663
2664 HBITMAP DefRibbonQueryItemImage(UINT32 uCtrlID, UINT32 uItem)
2665 {
2666 return DefRibbonQueryImage(uCtrlID + 1 + uItem);
2667 }
2668
2669 UINT32 DefRibbonQueryItemCommand(UINT32 uCtrlID, UINT32 uItem)
2670 {
2671 return uCtrlID + 1 + uItem;
2672 }
2673
2674 void DefRibbonColorCtrlExecute(UINT32 uCtrlID, UI_EXECUTIONVERB verb, UI_SWATCHCOLORTYPE uType, COLORREF color)
2675 {
2676 switch(uType)
2677 {
2678 case UI_SWATCHCOLORTYPE_RGB:
2679 break;
2680 case UI_SWATCHCOLORTYPE_AUTOMATIC:
2681 color = ::GetSysColor(COLOR_WINDOWTEXT);
2682 break;
2683 case UI_SWATCHCOLORTYPE_NOCOLOR:
2684 color = ::GetSysColor(COLOR_WINDOW);
2685 break;
2686 default:
2687 ATLASSERT(FALSE);
2688 break;
2689 }
2690
2691 DefCommandExecute(MAKELONG(uCtrlID, verb), color);
2692 }
2693
2694 void DefCommandExecute(UINT32 uCmd, LPARAM lParam = 0)
2695 {
2696 static_cast<T*>(this)->PostMessage(WM_COMMAND, uCmd, lParam);
2697 }
2698
2699 // Elements setting helpers
2700 HRESULT InvalidateCtrl(UINT32 nID)
2701 {
2702 return IsRibbonUI() ?
2703 GetIUIFrameworkPtr()->InvalidateUICommand(nID, UI_INVALIDATIONS_ALLPROPERTIES, NULL) :
2704 E_FAIL;
2705 }
2706
2707 HRESULT InvalidateProperty(UINT32 nID, REFPROPERTYKEY key, UI_INVALIDATIONS flags = UI_INVALIDATIONS_PROPERTY)
2708 {
2709 return IsRibbonUI() ?
2710 GetIUIFrameworkPtr()->InvalidateUICommand(nID, flags, &key) :
2711 E_FAIL;
2712 }
2713
2714 template <typename V>
2715 HRESULT SetProperty(WORD wID, REFPROPERTYKEY key, V val)
2716 {
2717 if (IsRibbonUI())
2718 {
2719 PROPVARIANT var;
2720 if (SUCCEEDED(RibbonUI::SetPropertyVal(key, val, &var)))
2721 {
2722 return SetProperty(wID, key, var);
2723 }
2724 return E_INVALIDARG;
2725 }
2726 else
2727 {
2728 return E_FAIL;
2729 }
2730 }
2731
2732 template <>
2733 HRESULT SetProperty(WORD nID, REFPROPERTYKEY key, PROPVARIANT var)
2734 {
2735 return IsRibbonUI() ?
2736 GetIUIFrameworkPtr()->SetUICommandProperty(nID, key, var) :
2737 E_FAIL;
2738 }
2739
2740 // Interfaces
2741 // IUIApplication
2742 STDMETHODIMP OnViewChanged(UINT32, UI_VIEWTYPE, IUnknown*, UI_VIEWVERB verb, INT32)
2743 {
2744 switch (verb)
2745 {
2746 case UI_VIEWVERB_CREATE:
2747 m_bRibbonUI = true;
2748 if (m_hgRibbonSettings != NULL)
2749 RestoreRibbonSettings();
2750 break;
2751 case UI_VIEWVERB_SIZE:
2752 static_cast<T*>(this)->UpdateLayout(FALSE);
2753 break;
2754 case UI_VIEWVERB_DESTROY:
2755 SaveRibbonSettings();
2756 m_bRibbonUI = false;
2757 break;
2758 }
2759
2760 return S_OK;
2761 }
2762
2763 STDMETHODIMP OnCreateUICommand(UINT32 nCmdID, UI_COMMANDTYPE typeID, IUICommandHandler** ppCommandHandler)
2764 {
2765 UIAddRibbonElement(nCmdID);
2766 if (typeID == UI_COMMANDTYPE_CONTEXT)
2767 CUpdateUIBase::UIEnable(nCmdID, false);
2768 *ppCommandHandler = this;
2769 return S_OK;
2770 }
2771
2772 STDMETHODIMP OnDestroyUICommand(UINT32 nCmdID, UI_COMMANDTYPE, IUICommandHandler*)
2773 {
2774 UIRemoveRibbonElement(nCmdID);
2775 return S_OK;
2776 }
2777
2778 // IUICommandHandler
2779 STDMETHODIMP Execute(UINT nCmdID,
2780 UI_EXECUTIONVERB verb,
2781 const PROPERTYKEY* key,
2782 const PROPVARIANT* ppropvarValue,
2783 IUISimplePropertySet* pCommandExecutionProperties)
2784 {
2785 T* pT =static_cast<T*>(this);
2786 return pT->GetRibbonCtrl(nCmdID).DoExecute(nCmdID, verb, key, ppropvarValue, pCommandExecutionProperties);
2787 }
2788
2789 STDMETHODIMP UpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
2790 const PROPVARIANT* ppropvarCurrentValue, PROPVARIANT* ppropvarNewValue)
2791 {
2792 T* pT =static_cast<T*>(this);
2793 return pT->GetRibbonCtrl(nCmdID).DoUpdateProperty(nCmdID, key, ppropvarCurrentValue, ppropvarNewValue);
2794 }
2795
2796 #ifdef _DEBUG
2797 // IUnknown methods (heavyweight)
2798 STDMETHODIMP_(ULONG) AddRef()
2799 {
2800 return InterlockedIncrement(&m_cRef);
2801 }
2802
2803 STDMETHODIMP_(ULONG) Release()
2804 {
2805 LONG cRef = InterlockedDecrement(&m_cRef);
2806 if (cRef == 0) // NoOp for breakpoint
2807 {
2808 cRef = 0;
2809 }
2810
2811 return cRef;
2812 }
2813
2814 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
2815 {
2816 if (ppv == NULL)
2817 {
2818 return E_POINTER;
2819 }
2820 else if ((iid == __uuidof(IUnknown)) ||
2821 (iid == __uuidof(IUICommandHandler)) ||
2822 (iid == __uuidof(IUIApplication)))
2823 {
2824 *ppv = this;
2825 AddRef();
2826 return S_OK;
2827 }
2828 else
2829 {
2830 return E_NOINTERFACE;
2831 }
2832 }
2833
2834 LONG m_cRef;
2835 #else
2836 // IUnknown methods (lightweight)
2837 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
2838 {
2839 if ((iid == __uuidof(IUnknown)) ||
2840 (iid == __uuidof(IUICommandHandler)) ||
2841 (iid == __uuidof(IUIApplication)))
2842 {
2843 *ppv = this;
2844 return S_OK;
2845 }
2846 return E_NOINTERFACE;
2847 }
2848 ULONG STDMETHODCALLTYPE AddRef()
2849 {
2850 return 1;
2851 }
2852 ULONG STDMETHODCALLTYPE Release()
2853 {
2854 return 1;
2855 }
2856 #endif
2857
2858 // CRibbonImpl ICtrl implementation
2859 virtual HRESULT DoExecute(UINT nCmdID, UI_EXECUTIONVERB verb,
2860 const PROPERTYKEY* key, const PROPVARIANT* ppropvarValue,
2861 IUISimplePropertySet* /*pCommandExecutionProperties*/)
2862 {
2863 if (key != NULL)
2864 {
2865 if(k_(*key) != k_BooleanValue)
2866 {
2867 ATLTRACE2(atlTraceUI, 0, _T("Control ID %d is not handled\n"), nCmdID);
2868 return E_NOTIMPL;
2869 }
2870 BOOL bChecked = FALSE;
2871 ATLVERIFY(SUCCEEDED(PropVariantToBoolean(*ppropvarValue, &bChecked)));
2872 CUpdateUIBase::UISetCheck(nCmdID, bChecked);
2873 }
2874
2875 ATLASSERT(verb == UI_EXECUTIONVERB_EXECUTE);
2876 verb; // avoid level 4 warning
2877
2878 static_cast<T*>(this)->OnRibbonCommandExecute(nCmdID);
2879
2880 return S_OK;
2881 }
2882
2883 virtual HRESULT DoUpdateProperty(UINT nCmdID, REFPROPERTYKEY key,
2884 const PROPVARIANT* /*ppropvarCurrentValue*/, PROPVARIANT* ppropvarNewValue)
2885 {
2886 T* pT = static_cast<T*>(this);
2887 HRESULT hr = E_NOTIMPL;
2888 switch (k_(key))
2889 {
2890 case k_LargeImage:
2891 case k_LargeHighContrastImage:
2892 case k_SmallImage:
2893 case k_SmallHighContrastImage:
2894 if (HBITMAP hbm = pT->OnRibbonQueryImage(nCmdID, key))
2895 hr = SetPropertyVal(key, GetImage(hbm, UI_OWNERSHIP_TRANSFER), ppropvarNewValue);
2896 break;
2897 case k_Label:
2898 case k_Keytip:
2899 case k_TooltipTitle:
2900 case k_TooltipDescription:
2901 case k_LabelDescription:
2902 if (LPCWSTR sText = pT->OnRibbonQueryText(nCmdID, key))
2903 hr = SetPropertyVal(key, sText, ppropvarNewValue);
2904 break;
2905 case k_BooleanValue:
2906 case k_Enabled:
2907 hr = SetPropertyVal(key, pT->OnRibbonQueryState(nCmdID, key), ppropvarNewValue);
2908 break;
2909 case k_ContextAvailable:
2910 hr = SetPropertyVal(key, pT->OnRibbonQueryTabAvail(nCmdID), ppropvarNewValue);
2911 break;
2912 }
2913
2914 return hr;
2915 }
2916
2917 // CRibbonImpl::CRibbonXXXCtrl specialized classes
2918 //CRibbonComboCtrl
2919 template <UINT t_ID, size_t t_items, size_t t_categories = 0>
2920 class CRibbonComboCtrl : public CollectionCtrlImpl<T, t_ID, ComboCollectionImpl<CRibbonComboCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
2921 {
2922 public:
2923 CRibbonComboCtrl()
2924 { }
2925 };
2926
2927 // CRibbonItemGalleryCtrl
2928 template <UINT t_ID, size_t t_items, size_t t_categories = 0>
2929 class CRibbonItemGalleryCtrl : public CollectionCtrlImpl<T, t_ID, ItemCollectionImpl<CRibbonItemGalleryCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
2930 {
2931 public:
2932 CRibbonItemGalleryCtrl()
2933 { }
2934 };
2935
2936 // CRibbonCommandGalleryCtrl
2937 template <UINT t_ID, size_t t_items, size_t t_categories = 0>
2938 class CRibbonCommandGalleryCtrl : public CollectionCtrlImpl<T, t_ID, CommandCollectionImpl<CRibbonCommandGalleryCtrl<t_ID, t_items, t_categories>, t_items, t_categories>>
2939 {
2940 public:
2941 CRibbonCommandGalleryCtrl()
2942 { }
2943 };
2944
2945 // CRibbonToolbarGalleryCtrl
2946 template <UINT t_ID, UINT t_idTB, size_t t_size>
2947 class CRibbonToolbarGalleryCtrl : public ToolbarGalleryCtrlImpl<T, t_ID, t_idTB, t_size>
2948 { };
2949
2950 // CRibbonSimpleComboCtrl
2951 template <UINT t_ID, size_t t_size>
2952 class CRibbonSimpleComboCtrl : public SimpleCollectionCtrlImpl<T, t_ID, t_size>
2953 { };
2954
2955 // CRibbonSimpleGalleryCtrl
2956 template <UINT t_ID, size_t t_size, UI_COMMANDTYPE t_CommandType = UI_COMMANDTYPE_ACTION>
2957 class CRibbonSimpleGalleryCtrl : public SimpleCollectionCtrlImpl<T, t_ID, t_size, t_CommandType>
2958 { };
2959
2960 //CRibbonRecentItemsCtrl
2961 template <UINT t_ID, class TDocList = CRecentDocumentList>
2962 class CRibbonRecentItemsCtrl : public RecentItemsCtrlImpl<T, t_ID, TDocList>
2963 {
2964 public:
2965 CRibbonRecentItemsCtrl()
2966 { }
2967 };
2968
2969 // CRibbonColorCtrl
2970 template <UINT t_ID>
2971 class CRibbonColorCtrl : public ColorCtrlImpl<T, t_ID>
2972 {
2973 public:
2974 CRibbonColorCtrl()
2975 { }
2976 };
2977
2978 //CRibbonFontCtrl
2979 template <UINT t_ID>
2980 class CRibbonFontCtrl : public FontCtrlImpl<T, t_ID>
2981 {
2982 public:
2983 CRibbonFontCtrl()
2984 { }
2985 };
2986
2987 // CRibbonSpinnerCtrl
2988 template <UINT t_ID>
2989 class CRibbonSpinnerCtrl : public SpinnerCtrlImpl<T, t_ID, LONG>
2990 {
2991 public:
2992 CRibbonSpinnerCtrl()
2993 { }
2994 };
2995
2996 // CRibbonFloatSpinnerCtrl
2997 template <UINT t_ID>
2998 class CRibbonFloatSpinnerCtrl : public SpinnerCtrlImpl<T, t_ID, DOUBLE>
2999 {
3000 public:
3001 CRibbonFloatSpinnerCtrl()
3002 {
3003 m_Values[4] = 1; // 1 decimal
3004 }
3005 };
3006
3007 // CRibbonCommandCtrl
3008 template <UINT t_ID>
3009 class CRibbonCommandCtrl : public CommandCtrlImpl<T, t_ID>
3010 {
3011 public:
3012 CRibbonCommandCtrl()
3013 { }
3014 };
3015
3016 // Control classes access to T instance (re-initialized in constructor)
3017 static T* pWndRibbon;
3018 };
3019
3020 template <class T>
3021 __declspec(selectany) T* CRibbonImpl<T>::pWndRibbon;
3022
3023 // Control map element
3024 #pragma warning(push)
3025 #pragma warning(disable: 4510 610 4512) // missing default constructor, can't be instatiated, assignment operator could not be generated
3026 typedef struct
3027 {
3028 UINT uID;
3029 ICtrl& ctrl;
3030 } _ribbonCtrl;
3031 #pragma warning(pop)
3032
3033 }; // namespace RibbonUI
3034
3035
3036 ///////////////////////////////////////////////////////////////////////////////
3037 // RibbonUI Control map
3038
3039 // Control map macros
3040 #define BEGIN_RIBBON_CONTROL_MAP(theClass) \
3041 WTL::RibbonUI::ICtrl& GetRibbonCtrl(UINT id) \
3042 { \
3043 WTL::RibbonUI::_ribbonCtrl _ctrls[] = \
3044 {
3045
3046 #define RIBBON_CONTROL(member) {member.GetID(), static_cast<WTL::RibbonUI::ICtrl&>(member)},
3047
3048 #define END_RIBBON_CONTROL_MAP() \
3049 {0, *this} \
3050 }; \
3051 int i = 0; \
3052 for(; i < _countof(_ctrls) - 1; i++) \
3053 if (_ctrls[i].uID == id) \
3054 break; \
3055 return _ctrls[i].ctrl; \
3056 }
3057
3058 // Control message map macros
3059 #define RIBBON_GALLERY_CONTROL_HANDLER(id, func) \
3060 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
3061 { \
3062 bHandled = TRUE; \
3063 lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (UINT)lParam, bHandled); \
3064 if(bHandled) \
3065 return TRUE; \
3066 }
3067
3068 #define RIBBON_COMBO_CONTROL_HANDLER(id, func) \
3069 RIBBON_GALLERY_CONTROL_HANDLER(id, func)
3070
3071 #define RIBBON_FONT_CONTROL_HANDLER(id, func) \
3072 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
3073 { \
3074 bHandled = TRUE; \
3075 lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (CHARFORMAT2*)lParam, bHandled); \
3076 if(bHandled) \
3077 return TRUE; \
3078 }
3079
3080 #define RIBBON_COLOR_CONTROL_HANDLER(id, func) \
3081 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
3082 { \
3083 bHandled = TRUE; \
3084 lResult = func((UI_EXECUTIONVERB)HIWORD(wParam), LOWORD(wParam), (COLORREF)lParam, bHandled); \
3085 if(bHandled) \
3086 return TRUE; \
3087 }
3088
3089 #define RIBBON_SPINNER_CONTROL_HANDLER(id, func) \
3090 if(uMsg == WM_COMMAND && id == wParam) \
3091 { \
3092 bHandled = TRUE; \
3093 lResult = func((WORD)wParam, (LONG)lParam, bHandled); \
3094 if(bHandled) \
3095 return TRUE; \
3096 }
3097
3098 #define RIBBON_FLOATSPINNER_CONTROL_HANDLER(id, func) \
3099 if(uMsg == WM_COMMAND && id == wParam) \
3100 { \
3101 bHandled = TRUE; \
3102 lResult = func((WORD)wParam, (DOUBLE*)lParam, bHandled); \
3103 if(bHandled) \
3104 return TRUE; \
3105 }
3106
3107 // Handler prototypes
3108 /*
3109 LRESULT OnRibbonGalleryCtrl(UI_EXECUTIONVERB verb, WORD wID, UINT uSel, BOOL& bHandled);
3110 LRESULT OnRibbonComboCtrl(UI_EXECUTIONVERB verb, WORD wID, UINT uSel, BOOL& bHandled);
3111 LRESULT OnRibbonFontCtrl(UI_EXECUTIONVERB verb, WORD wID, CHARFORMAT2* pcf, BOOL& bHandled);
3112 LRESULT OnRibbonColorCtrl(UI_EXECUTIONVERB verb, WORD wID, COLORREF color, BOOL& bHandled);
3113 LRESULT OnRibbonSpinnerCtrl(WORD wID, LONG lVal, BOOL& bHandled);
3114 LRESULT OnRibbonFloatSpinnerCtrl(WORD wID, DOUBLE* pdVal, BOOL& bHandled);
3115 */
3116
3117
3118 ///////////////////////////////////////////////////////////////////////////////
3119 // Ribbon frame classes
3120
3121 // CRibbonFrameWindowImplBase
3122 //
3123 template <class T, class TFrameImpl>
3124 class ATL_NO_VTABLE CRibbonFrameWindowImplBase : public TFrameImpl, public RibbonUI::CRibbonImpl<T>
3125 {
3126 typedef TFrameImpl baseFrame;
3127 bool m_bUseCommandBarBitmaps;
3128 bool m_bWin7Fix;
3129
3130 public:
3131 // Construction
3132 CRibbonFrameWindowImplBase(bool bUseCommandBarBitmaps = true) :
3133 m_bUseCommandBarBitmaps(bUseCommandBarBitmaps), m_bWin7Fix(false)
3134 {
3135 __if_not_exists(T::m_CmdBar)
3136 {
3137 m_bUseCommandBarBitmaps = false;
3138 }
3139 }
3140
3141 // Win7 Aero fix helpers
3142 void ResetFrame()
3143 {
3144 const MARGINS margins = { 0 };
3145 ::DwmExtendFrameIntoClientArea(m_hWnd, &margins);
3146 }
3147
3148 INT CalcWin7Fix()
3149 {
3150 ResetFrame();
3151 RECT rc = { 0 };
3152 ::AdjustWindowRectEx(&rc, T::GetWndStyle(0), GetMenu() != NULL, T::GetWndExStyle(0));
3153 return -rc.top;
3154 }
3155
3156 bool NeedWin7Fix()
3157 {
3158 BOOL bComp = FALSE;
3159 return m_bWin7Fix && RunTimeHelper::IsWin7() && SUCCEEDED(DwmIsCompositionEnabled(&bComp)) && bComp;
3160 }
3161
3162 // Operations
3163 bool UseCommandBarBitmaps(bool bUse)
3164 {
3165 __if_exists(T::m_CmdBar)
3166 {
3167 return m_bUseCommandBarBitmaps = bUse;
3168 }
3169 __if_not_exists(T::m_CmdBar)
3170 {
3171 bUse; // avoid level 4 warning
3172 return false;
3173 }
3174 }
3175
3176 bool ShowRibbonUI(bool bShow, INT32 imodes = UI_MAKEAPPMODE(0), LPCWSTR sResName = L"APPLICATION_RIBBON")
3177 {
3178 if (!RunTimeHelper::IsRibbonUIAvailable())
3179 return false;
3180
3181 ATLASSERT(GetIUIFrameworkPtr());
3182
3183 if (IsRibbonUI() == bShow)
3184 return bShow;
3185
3186 bool bVisible = (IsWindowVisible() != FALSE);
3187 if(bVisible && !bShow)
3188 SetRedraw(FALSE);
3189
3190 if (bShow && ::IsWindow(m_hWndToolBar))
3191 {
3192 ::ShowWindow(m_hWndToolBar, SW_HIDE);
3193 UpdateLayout();
3194 }
3195
3196 m_bWin7Fix = !bShow;
3197
3198 HRESULT hr = bShow ? CreateRibbon(sResName) : DestroyRibbon();
3199
3200 m_bWin7Fix = SUCCEEDED(hr) && !bShow;
3201
3202 if (SUCCEEDED(hr))
3203 {
3204 if(::IsWindow(m_hWndToolBar) && !bShow)
3205 {
3206 ::ShowWindow(m_hWndToolBar, SW_SHOWNA);
3207 UpdateLayout();
3208 }
3209 else if (bShow)
3210 {
3211 PostMessage(WM_SIZE);
3212 SetRibbonModes(imodes);
3213 }
3214 }
3215
3216 if(bVisible && !bShow)
3217 {
3218 SetRedraw(TRUE);
3219 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
3220 }
3221
3222 return SUCCEEDED(hr) ? bShow : !bShow;
3223 }
3224
3225 // Overrideables
3226 HBITMAP OnRibbonQueryImage(UINT nCmdID, REFPROPERTYKEY key)
3227 {
3228 if ((key == UI_PKEY_SmallImage) && m_bUseCommandBarBitmaps)
3229 {
3230 if (HBITMAP hbm = GetCommandBarBitmap(nCmdID))
3231 return (HBITMAP)::CopyImage(hbm, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
3232 }
3233
3234 return DefRibbonQueryImage(nCmdID);
3235 }
3236
3237 BEGIN_MSG_MAP(CRibbonFrameWindowImplBase)
3238 if (!IsRibbonUI() && NeedWin7Fix())
3239 {
3240 MESSAGE_HANDLER(WM_SIZING, OnSizing)
3241 MESSAGE_HANDLER(WM_SIZE, OnSize)
3242 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
3243 MESSAGE_HANDLER(WM_NCCALCSIZE, OnNCCalcSize)
3244 }
3245 CHAIN_MSG_MAP(CRibbonUpdateUI<T>)
3246 CHAIN_MSG_MAP(baseFrame)
3247 END_MSG_MAP()
3248
3249 // Message handlers for Win7 Aero
3250 LRESULT OnSizing(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3251 {
3252 switch (wParam)
3253 {
3254 case WMSZ_TOP:
3255 case WMSZ_TOPLEFT:
3256 case WMSZ_TOPRIGHT:
3257 SetWindowPos(NULL, (LPRECT)lParam, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
3258 break;
3259 default:
3260 DefWindowProc();
3261 break;
3262 }
3263
3264 return 1; // handled
3265 }
3266
3267 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
3268 {
3269 if (wParam != SIZE_MINIMIZED)
3270 SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
3271
3272 bHandled = FALSE;
3273 return 1;
3274 }
3275
3276 LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
3277 {
3278 if(wParam != WA_INACTIVE)
3279 SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
3280
3281 bHandled = FALSE;
3282 return 1;
3283 }
3284
3285 LRESULT OnNCCalcSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
3286 {
3287 ATLASSERT(!IsRibbonUI() && NeedWin7Fix());
3288
3289 LRESULT lRet = DefWindowProc();
3290
3291 if(wParam)
3292 {
3293 LPNCCALCSIZE_PARAMS pParams = (LPNCCALCSIZE_PARAMS)lParam;
3294 pParams->rgrc[0].top = pParams->rgrc[1].top + CalcWin7Fix();
3295 }
3296
3297 return lRet;
3298 }
3299
3300 // Overrides
3301 void UpdateLayout(BOOL bResizeBars = TRUE)
3302 {
3303 RECT rect = { 0 };
3304 GetClientRect(&rect);
3305
3306 if (IsRibbonUI() && !IsRibbonHidden())
3307 {
3308 rect.top += GetRibbonHeight();
3309 }
3310 else if (!IsRibbonUI() && NeedWin7Fix())
3311 {
3312 ResetFrame();
3313 }
3314
3315 // position bars and offset their dimensions
3316 UpdateBarsPosition(rect, bResizeBars);
3317
3318 // resize client window
3319 if(m_hWndClient != NULL)
3320 ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
3321 rect.right - rect.left, rect.bottom - rect.top,
3322 SWP_NOZORDER | SWP_NOACTIVATE);
3323 }
3324
3325 // Implementation
3326 HBITMAP GetCommandBarBitmap(UINT nCmdID)
3327 {
3328 __if_exists (T::m_CmdBar)
3329 {
3330 ATLASSERT(RunTimeHelper::IsVista());
3331 T* pT =static_cast<T*>(this);
3332 int nIndex = pT->m_CmdBar.m_arrCommand.Find((WORD&)nCmdID);
3333 return (nIndex == -1) ? NULL : pT->m_CmdBar.m_arrVistaBitmap[nIndex];
3334 }
3335 __if_not_exists (T::m_CmdBar)
3336 {
3337 nCmdID; // avoid level 4 warning
3338 return NULL;
3339 }
3340 }
3341 };
3342
3343 // CRibbonFrameWindowImpl
3344 //
3345 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
3346 class ATL_NO_VTABLE CRibbonFrameWindowImpl : public CRibbonFrameWindowImplBase<T, CFrameWindowImpl<T, TBase, TWinTraits>>
3347 { };
3348
3349 // CRibbonMDIFrameWindowImpl
3350 //
3351 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
3352 class ATL_NO_VTABLE CRibbonMDIFrameWindowImpl : public CRibbonFrameWindowImplBase<T, CMDIFrameWindowImpl<T, TBase, TWinTraits>>
3353 { };
3354
3355
3356 ///////////////////////////////////////////////////////////////////////////////
3357 // CRibbonPersist helper for RibbonUI persistency
3358
3359 class CRibbonPersist
3360 {
3361 public:
3362 CRibbonPersist(LPCWSTR sAppKey)
3363 {
3364 ATLASSERT(sAppKey && *sAppKey);
3365 m_Key.Create(HKEY_CURRENT_USER, sAppKey);
3366 ATLASSERT(m_Key.m_hKey);
3367 }
3368
3369 CRegKeyEx m_Key;
3370
3371 LONG Save(bool bRibbonUI, HGLOBAL hgSettings = NULL)
3372 {
3373 CRegKeyEx key;
3374 const DWORD dwUI = bRibbonUI;
3375
3376 LONG lRet = key.Create(m_Key, L"Ribbon");
3377 if(lRet != ERROR_SUCCESS)
3378 return lRet;
3379
3380 lRet = key.SetDWORDValue(L"UI", dwUI);
3381 if(lRet != ERROR_SUCCESS)
3382 return lRet;
3383
3384 if (hgSettings != NULL)
3385 {
3386 LPBYTE pVal = (LPBYTE)::GlobalLock(hgSettings);
3387 if (pVal != NULL)
3388 {
3389 lRet = key.SetBinaryValue(L"Settings", pVal, (ULONG)::GlobalSize(hgSettings));
3390 ::GlobalUnlock(hgSettings);
3391 }
3392 else
3393 {
3394 lRet = GetLastError();
3395 }
3396 }
3397
3398 return lRet;
3399 }
3400
3401 LONG Restore(bool& bRibbonUI, HGLOBAL& hgSettings)
3402 {
3403 ATLASSERT(hgSettings == NULL);
3404
3405 CRegKeyEx key;
3406
3407 LONG lRet = key.Open(m_Key, L"Ribbon");
3408 if(lRet != ERROR_SUCCESS)
3409 return lRet;
3410
3411 DWORD dwUI = 0xffff;
3412 lRet = key.QueryDWORDValue(L"UI", dwUI);
3413 if(lRet == ERROR_SUCCESS)
3414 bRibbonUI = dwUI == 1;
3415 else
3416 return lRet;
3417
3418 ULONG ulSize = 0;
3419 lRet = key.QueryBinaryValue(L"Settings", NULL, &ulSize);
3420 if (lRet == ERROR_SUCCESS)
3421 {
3422 ATLASSERT(ulSize != 0);
3423
3424 hgSettings = ::GlobalAlloc(GHND, ulSize);
3425 if (hgSettings != NULL)
3426 {
3427 LPBYTE pData = (LPBYTE)::GlobalLock(hgSettings);
3428 if (pData != NULL)
3429 {
3430 lRet = key.QueryBinaryValue(L"Settings", pData, &ulSize);
3431 }
3432 else
3433 {
3434 lRet = GetLastError();
3435 ::GlobalFree(hgSettings);
3436 hgSettings = NULL;
3437 }
3438 }
3439 else
3440 {
3441 lRet = GetLastError();
3442 }
3443 }
3444 return lRet;
3445 }
3446
3447 LONG Delete()
3448 {
3449 return m_Key.DeleteSubKey(L"Ribbon");
3450 }
3451 };
3452
3453 } // namespace WTL
3454
3455 #endif // __ATLRIBBON_H__
+0
-2166
src/third_party/wtl/Include/atlscrl.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLSCRL_H__
9 #define __ATLSCRL_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlscrl.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLWIN_H__
18 #error atlscrl.h requires atlwin.h to be included first
19 #endif
20
21 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
22 #include <zmouse.h>
23 #endif
24
25 #ifndef GET_WHEEL_DELTA_WPARAM
26 #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
27 #endif
28
29
30 ///////////////////////////////////////////////////////////////////////////////
31 // Classes in this file:
32 //
33 // CScrollImpl<T>
34 // CScrollWindowImpl<T, TBase, TWinTraits>
35 // CMapScrollImpl<T>
36 // CMapScrollWindowImpl<T, TBase, TWinTraits>
37 // CFSBWindowT<TBase>
38 // CZoomScrollImpl<T>
39 // CZoomScrollWindowImpl<T, TBase, TWinTraits>
40 // CScrollContainerImpl<T, TBase, TWinTraits>
41 // CScrollContainer
42
43 namespace WTL
44 {
45
46 ///////////////////////////////////////////////////////////////////////////////
47 // CScrollImpl - Provides scrolling support to any window
48
49 // Scroll extended styles
50 #define SCRL_SCROLLCHILDREN 0x00000001
51 #define SCRL_ERASEBACKGROUND 0x00000002
52 #define SCRL_NOTHUMBTRACKING 0x00000004
53 #if (WINVER >= 0x0500)
54 #define SCRL_SMOOTHSCROLL 0x00000008
55 #endif // (WINVER >= 0x0500)
56 #define SCRL_DISABLENOSCROLLV 0x00000010
57 #define SCRL_DISABLENOSCROLLH 0x00000020
58 #define SCRL_DISABLENOSCROLL (SCRL_DISABLENOSCROLLV | SCRL_DISABLENOSCROLLH)
59
60
61 template <class T>
62 class CScrollImpl
63 {
64 public:
65 enum { uSCROLL_FLAGS = SW_INVALIDATE };
66
67 POINT m_ptOffset;
68 SIZE m_sizeAll;
69 SIZE m_sizeLine;
70 SIZE m_sizePage;
71 SIZE m_sizeClient;
72 int m_zDelta; // current wheel value
73 int m_nWheelLines; // number of lines to scroll on wheel
74 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
75 // Note that this message must be forwarded from a top level window
76 UINT m_uMsgMouseWheel; // MSH_MOUSEWHEEL
77 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
78 int m_zHDelta; // current horizontal wheel value
79 int m_nHWheelChars; // number of chars to scroll on horizontal wheel
80 UINT m_uScrollFlags;
81 DWORD m_dwExtendedStyle; // scroll specific extended styles
82
83 // Constructor
84 CScrollImpl() : m_zDelta(0), m_nWheelLines(3),
85 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
86 m_uMsgMouseWheel(0U),
87 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
88 m_zHDelta(0), m_nHWheelChars(3),
89 m_uScrollFlags(0U), m_dwExtendedStyle(0)
90 {
91 m_ptOffset.x = 0;
92 m_ptOffset.y = 0;
93 m_sizeAll.cx = 0;
94 m_sizeAll.cy = 0;
95 m_sizePage.cx = 0;
96 m_sizePage.cy = 0;
97 m_sizeLine.cx = 0;
98 m_sizeLine.cy = 0;
99 m_sizeClient.cx = 0;
100 m_sizeClient.cy = 0;
101
102 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN | SCRL_ERASEBACKGROUND);
103 }
104
105 // Attributes & Operations
106 DWORD GetScrollExtendedStyle() const
107 {
108 return m_dwExtendedStyle;
109 }
110
111 DWORD SetScrollExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
112 {
113 DWORD dwPrevStyle = m_dwExtendedStyle;
114 if(dwMask == 0)
115 m_dwExtendedStyle = dwExtendedStyle;
116 else
117 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
118 // cache scroll flags
119 T* pT = static_cast<T*>(this);
120 pT; // avoid level 4 warning
121 m_uScrollFlags = pT->uSCROLL_FLAGS | (IsScrollingChildren() ? SW_SCROLLCHILDREN : 0) | (IsErasingBackground() ? SW_ERASE : 0);
122 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
123 m_uScrollFlags |= (IsSmoothScroll() ? SW_SMOOTHSCROLL : 0);
124 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
125 return dwPrevStyle;
126 }
127
128 // offset operations
129 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
130 {
131 T* pT = static_cast<T*>(this);
132 ATLASSERT(::IsWindow(pT->m_hWnd));
133
134 pT->AdjustScrollOffset(x, y);
135
136 int dx = m_ptOffset.x - x;
137 int dy = m_ptOffset.y - y;
138 m_ptOffset.x = x;
139 m_ptOffset.y = y;
140
141 // block: set horizontal scroll bar
142 {
143 SCROLLINFO si = { sizeof(SCROLLINFO) };
144 si.fMask = SIF_POS;
145 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
146 si.fMask |= SIF_DISABLENOSCROLL;
147 si.nPos = m_ptOffset.x;
148 pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
149 }
150
151 // block: set vertical scroll bar
152 {
153 SCROLLINFO si = { sizeof(SCROLLINFO) };
154 si.fMask = SIF_POS;
155 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
156 si.fMask |= SIF_DISABLENOSCROLL;
157 si.nPos = m_ptOffset.y;
158 pT->SetScrollInfo(SB_VERT, &si, bRedraw);
159 }
160
161 // Move all children if needed
162 if(IsScrollingChildren() && (dx != 0 || dy != 0))
163 {
164 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
165 {
166 RECT rect = { 0 };
167 ::GetWindowRect(hWndChild, &rect);
168 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
169 ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
170 }
171 }
172
173 if(bRedraw)
174 pT->Invalidate();
175 }
176
177 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
178 {
179 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
180 }
181
182 void GetScrollOffset(POINT& ptOffset) const
183 {
184 ptOffset = m_ptOffset;
185 }
186
187 // size operations
188 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
189 {
190 T* pT = static_cast<T*>(this);
191 ATLASSERT(::IsWindow(pT->m_hWnd));
192
193 m_sizeAll.cx = cx;
194 m_sizeAll.cy = cy;
195
196 int x = 0;
197 int y = 0;
198 if(!bResetOffset)
199 {
200 x = m_ptOffset.x;
201 y = m_ptOffset.y;
202 pT->AdjustScrollOffset(x, y);
203 }
204
205 int dx = m_ptOffset.x - x;
206 int dy = m_ptOffset.y - y;
207 m_ptOffset.x = x;
208 m_ptOffset.y = y;
209
210 // block: set horizontal scroll bar
211 {
212 SCROLLINFO si = { sizeof(SCROLLINFO) };
213 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
214 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
215 si.fMask |= SIF_DISABLENOSCROLL;
216 si.nMin = 0;
217 si.nMax = m_sizeAll.cx - 1;
218 si.nPage = m_sizeClient.cx;
219 si.nPos = m_ptOffset.x;
220 pT->SetScrollInfo(SB_HORZ, &si, bRedraw);
221 }
222
223 // block: set vertical scroll bar
224 {
225 SCROLLINFO si = { sizeof(SCROLLINFO) };
226 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
227 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
228 si.fMask |= SIF_DISABLENOSCROLL;
229 si.nMin = 0;
230 si.nMax = m_sizeAll.cy - 1;
231 si.nPage = m_sizeClient.cy;
232 si.nPos = m_ptOffset.y;
233 pT->SetScrollInfo(SB_VERT, &si, bRedraw);
234 }
235
236 // Move all children if needed
237 if(IsScrollingChildren() && (dx != 0 || dy != 0))
238 {
239 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
240 {
241 RECT rect = { 0 };
242 ::GetWindowRect(hWndChild, &rect);
243 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 1);
244 ::SetWindowPos(hWndChild, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
245 }
246 }
247
248 SetScrollLine(0, 0);
249 SetScrollPage(0, 0);
250
251 if(bRedraw)
252 pT->Invalidate();
253 }
254
255 void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
256 {
257 SetScrollSize(size.cx, size.cy, bRedraw, bResetOffset);
258 }
259
260 void GetScrollSize(SIZE& sizeWnd) const
261 {
262 sizeWnd = m_sizeAll;
263 }
264
265 // line operations
266 void SetScrollLine(int cxLine, int cyLine)
267 {
268 ATLASSERT(cxLine >= 0 && cyLine >= 0);
269 ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
270
271 m_sizeLine.cx = T::CalcLineOrPage(cxLine, m_sizeAll.cx, 100);
272 m_sizeLine.cy = T::CalcLineOrPage(cyLine, m_sizeAll.cy, 100);
273 }
274
275 void SetScrollLine(SIZE sizeLine)
276 {
277 SetScrollLine(sizeLine.cx, sizeLine.cy);
278 }
279
280 void GetScrollLine(SIZE& sizeLine) const
281 {
282 sizeLine = m_sizeLine;
283 }
284
285 // page operations
286 void SetScrollPage(int cxPage, int cyPage)
287 {
288 ATLASSERT(cxPage >= 0 && cyPage >= 0);
289 ATLASSERT(m_sizeAll.cx != 0 && m_sizeAll.cy != 0);
290
291 m_sizePage.cx = T::CalcLineOrPage(cxPage, m_sizeAll.cx, 10);
292 m_sizePage.cy = T::CalcLineOrPage(cyPage, m_sizeAll.cy, 10);
293 }
294
295 void SetScrollPage(SIZE sizePage)
296 {
297 SetScrollPage(sizePage.cx, sizePage.cy);
298 }
299
300 void GetScrollPage(SIZE& sizePage) const
301 {
302 sizePage = m_sizePage;
303 }
304
305 // commands
306 void ScrollLineDown()
307 {
308 T* pT = static_cast<T*>(this);
309 ATLASSERT(::IsWindow(pT->m_hWnd));
310 pT->DoScroll(SB_VERT, SB_LINEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
311 }
312
313 void ScrollLineUp()
314 {
315 T* pT = static_cast<T*>(this);
316 ATLASSERT(::IsWindow(pT->m_hWnd));
317 pT->DoScroll(SB_VERT, SB_LINEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
318 }
319
320 void ScrollPageDown()
321 {
322 T* pT = static_cast<T*>(this);
323 ATLASSERT(::IsWindow(pT->m_hWnd));
324 pT->DoScroll(SB_VERT, SB_PAGEDOWN, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
325 }
326
327 void ScrollPageUp()
328 {
329 T* pT = static_cast<T*>(this);
330 ATLASSERT(::IsWindow(pT->m_hWnd));
331 pT->DoScroll(SB_VERT, SB_PAGEUP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
332 }
333
334 void ScrollTop()
335 {
336 T* pT = static_cast<T*>(this);
337 ATLASSERT(::IsWindow(pT->m_hWnd));
338 pT->DoScroll(SB_VERT, SB_TOP, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
339 }
340
341 void ScrollBottom()
342 {
343 T* pT = static_cast<T*>(this);
344 ATLASSERT(::IsWindow(pT->m_hWnd));
345 pT->DoScroll(SB_VERT, SB_BOTTOM, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
346 }
347
348 void ScrollLineRight()
349 {
350 T* pT = static_cast<T*>(this);
351 ATLASSERT(::IsWindow(pT->m_hWnd));
352 pT->DoScroll(SB_HORZ, SB_LINEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
353 }
354
355 void ScrollLineLeft()
356 {
357 T* pT = static_cast<T*>(this);
358 ATLASSERT(::IsWindow(pT->m_hWnd));
359 pT->DoScroll(SB_HORZ, SB_LINEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
360 }
361
362 void ScrollPageRight()
363 {
364 T* pT = static_cast<T*>(this);
365 ATLASSERT(::IsWindow(pT->m_hWnd));
366 pT->DoScroll(SB_HORZ, SB_PAGEDOWN, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
367 }
368
369 void ScrollPageLeft()
370 {
371 T* pT = static_cast<T*>(this);
372 ATLASSERT(::IsWindow(pT->m_hWnd));
373 pT->DoScroll(SB_HORZ, SB_PAGEUP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
374 }
375
376 void ScrollAllLeft()
377 {
378 T* pT = static_cast<T*>(this);
379 ATLASSERT(::IsWindow(pT->m_hWnd));
380 pT->DoScroll(SB_HORZ, SB_TOP, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
381 }
382
383 void ScrollAllRight()
384 {
385 T* pT = static_cast<T*>(this);
386 ATLASSERT(::IsWindow(pT->m_hWnd));
387 pT->DoScroll(SB_HORZ, SB_BOTTOM, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
388 }
389
390 // scroll to make point/view/window visible
391 void ScrollToView(POINT pt)
392 {
393 T* pT = static_cast<T*>(this);
394 ATLASSERT(::IsWindow(pT->m_hWnd));
395 RECT rect = { pt.x, pt.y, pt.x, pt.y };
396 pT->ScrollToView(rect);
397 }
398
399 void ScrollToView(RECT& rect)
400 {
401 T* pT = static_cast<T*>(this);
402 ATLASSERT(::IsWindow(pT->m_hWnd));
403
404 RECT rcClient = { 0 };
405 pT->GetClientRect(&rcClient);
406
407 int x = m_ptOffset.x;
408 if(rect.left < m_ptOffset.x)
409 x = rect.left;
410 else if(rect.right > (m_ptOffset.x + rcClient.right))
411 x = rect.right - rcClient.right;
412
413 int y = m_ptOffset.y;
414 if(rect.top < m_ptOffset.y)
415 y = rect.top;
416 else if(rect.bottom > (m_ptOffset.y + rcClient.bottom))
417 y = rect.bottom - rcClient.bottom;
418
419 SetScrollOffset(x, y);
420 }
421
422 void ScrollToView(HWND hWnd)
423 {
424 T* pT = static_cast<T*>(this);
425 ATLASSERT(::IsWindow(pT->m_hWnd));
426
427 RECT rect = { 0 };
428 ::GetWindowRect(hWnd, &rect);
429 ::OffsetRect(&rect, m_ptOffset.x, m_ptOffset.y);
430 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
431 ScrollToView(rect);
432 }
433
434 BEGIN_MSG_MAP(CScrollImpl)
435 MESSAGE_HANDLER(WM_CREATE, OnCreate)
436 MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
437 MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
438 MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
439 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
440 MESSAGE_HANDLER(m_uMsgMouseWheel, OnMouseWheel)
441 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
442 MESSAGE_HANDLER(WM_MOUSEHWHEEL, OnMouseHWheel)
443 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
444 MESSAGE_HANDLER(WM_SIZE, OnSize)
445 MESSAGE_HANDLER(WM_PAINT, OnPaint)
446 #ifndef _WIN32_WCE
447 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
448 #endif // !_WIN32_WCE
449 // standard scroll commands
450 ALT_MSG_MAP(1)
451 COMMAND_ID_HANDLER(ID_SCROLL_UP, OnScrollUp)
452 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, OnScrollDown)
453 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, OnScrollPageUp)
454 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, OnScrollPageDown)
455 COMMAND_ID_HANDLER(ID_SCROLL_TOP, OnScrollTop)
456 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, OnScrollBottom)
457 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, OnScrollLeft)
458 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, OnScrollRight)
459 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, OnScrollPageLeft)
460 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, OnScrollPageRight)
461 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, OnScrollAllLeft)
462 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, OnScrollAllRight)
463 END_MSG_MAP()
464
465 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
466 {
467 T* pT = static_cast<T*>(this);
468 pT->GetSystemSettings();
469
470 bHandled = FALSE;
471 return 1;
472 }
473
474 LRESULT OnVScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
475 {
476 T* pT = static_cast<T*>(this);
477 ATLASSERT(::IsWindow(pT->m_hWnd));
478 pT->DoScroll(SB_VERT, (int)(short)LOWORD(wParam), (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
479 return 0;
480 }
481
482 LRESULT OnHScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
483 {
484 T* pT = static_cast<T*>(this);
485 ATLASSERT(::IsWindow(pT->m_hWnd));
486 pT->DoScroll(SB_HORZ, (int)(short)LOWORD(wParam), (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
487 return 0;
488 }
489
490 LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
491 {
492 T* pT = static_cast<T*>(this);
493 ATLASSERT(::IsWindow(pT->m_hWnd));
494
495 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE)
496 uMsg;
497 int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
498 #else
499 int zDelta = (uMsg == WM_MOUSEWHEEL) ? (int)GET_WHEEL_DELTA_WPARAM(wParam) : (int)wParam;
500 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) || defined(_WIN32_WCE))
501 int nScrollCode = (m_nWheelLines == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGEUP : SB_PAGEDOWN) : ((zDelta > 0) ? SB_LINEUP : SB_LINEDOWN);
502 m_zDelta += zDelta; // cumulative
503 int zTotal = (m_nWheelLines == WHEEL_PAGESCROLL) ? abs(m_zDelta) : abs(m_zDelta) * m_nWheelLines;
504 if(m_sizeAll.cy > m_sizeClient.cy)
505 {
506 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
507 {
508 pT->DoScroll(SB_VERT, nScrollCode, (int&)m_ptOffset.y, m_sizeAll.cy, m_sizePage.cy, m_sizeLine.cy);
509 pT->UpdateWindow();
510 }
511 }
512 else if(m_sizeAll.cx > m_sizeClient.cx) // can't scroll vertically, scroll horizontally
513 {
514 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
515 {
516 pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
517 pT->UpdateWindow();
518 }
519 }
520 m_zDelta %= WHEEL_DELTA;
521
522 return 0;
523 }
524
525 LRESULT OnMouseHWheel(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
526 {
527 T* pT = static_cast<T*>(this);
528 ATLASSERT(::IsWindow(pT->m_hWnd));
529
530 int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
531 int nScrollCode = (m_nHWheelChars == WHEEL_PAGESCROLL) ? ((zDelta > 0) ? SB_PAGERIGHT : SB_PAGELEFT) : ((zDelta > 0) ? SB_LINERIGHT : SB_LINELEFT);
532 m_zHDelta += zDelta; // cumulative
533 int zTotal = (m_nHWheelChars == WHEEL_PAGESCROLL) ? abs(m_zHDelta) : abs(m_zHDelta) * m_nHWheelChars;
534 if(m_sizeAll.cx > m_sizeClient.cx)
535 {
536 for(int i = 0; i < zTotal; i += WHEEL_DELTA)
537 {
538 pT->DoScroll(SB_HORZ, nScrollCode, (int&)m_ptOffset.x, m_sizeAll.cx, m_sizePage.cx, m_sizeLine.cx);
539 pT->UpdateWindow();
540 }
541 }
542 m_zHDelta %= WHEEL_DELTA;
543
544 return 0;
545 }
546
547 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
548 {
549 GetSystemSettings();
550 return 0;
551 }
552
553 LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
554 {
555 T* pT = static_cast<T*>(this);
556 ATLASSERT(::IsWindow(pT->m_hWnd));
557
558 pT->DoSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
559
560 bHandled = FALSE;
561 return 1;
562 }
563
564 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
565 {
566 T* pT = static_cast<T*>(this);
567 ATLASSERT(::IsWindow(pT->m_hWnd));
568 if(wParam != NULL)
569 {
570 CDCHandle dc = (HDC)wParam;
571 POINT ptViewportOrg = { 0, 0 };
572 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
573 pT->DoPaint(dc);
574 dc.SetViewportOrg(ptViewportOrg);
575 }
576 else
577 {
578 CPaintDC dc(pT->m_hWnd);
579 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
580 pT->DoPaint(dc.m_hDC);
581 }
582 return 0;
583 }
584
585 // scrolling handlers
586 LRESULT OnScrollUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
587 {
588 ScrollLineUp();
589 return 0;
590 }
591
592 LRESULT OnScrollDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
593 {
594 ScrollLineDown();
595 return 0;
596 }
597
598 LRESULT OnScrollPageUp(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
599 {
600 ScrollPageUp();
601 return 0;
602 }
603
604 LRESULT OnScrollPageDown(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
605 {
606 ScrollPageDown();
607 return 0;
608 }
609
610 LRESULT OnScrollTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
611 {
612 ScrollTop();
613 return 0;
614 }
615
616 LRESULT OnScrollBottom(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
617 {
618 ScrollBottom();
619 return 0;
620 }
621
622 LRESULT OnScrollLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
623 {
624 ScrollLineLeft();
625 return 0;
626 }
627
628 LRESULT OnScrollRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
629 {
630 ScrollLineRight();
631 return 0;
632 }
633
634 LRESULT OnScrollPageLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
635 {
636 ScrollPageLeft();
637 return 0;
638 }
639
640 LRESULT OnScrollPageRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
641 {
642 ScrollPageRight();
643 return 0;
644 }
645
646 LRESULT OnScrollAllLeft(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
647 {
648 ScrollAllLeft();
649 return 0;
650 }
651
652 LRESULT OnScrollAllRight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
653 {
654 ScrollAllRight();
655 return 0;
656 }
657
658 // Overrideables
659 void DoPaint(CDCHandle /*dc*/)
660 {
661 // must be implemented in a derived class
662 ATLASSERT(FALSE);
663 }
664
665 // Implementation
666 void DoSize(int cx, int cy)
667 {
668 m_sizeClient.cx = cx;
669 m_sizeClient.cy = cy;
670
671 T* pT = static_cast<T*>(this);
672
673 // block: set horizontal scroll bar
674 {
675 SCROLLINFO si = { sizeof(SCROLLINFO) };
676 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
677 si.nMin = 0;
678 si.nMax = m_sizeAll.cx - 1;
679 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLH) != 0)
680 si.fMask |= SIF_DISABLENOSCROLL;
681 si.nPage = m_sizeClient.cx;
682 si.nPos = m_ptOffset.x;
683 pT->SetScrollInfo(SB_HORZ, &si, TRUE);
684 }
685
686 // block: set vertical scroll bar
687 {
688 SCROLLINFO si = { sizeof(SCROLLINFO) };
689 si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
690 si.nMin = 0;
691 si.nMax = m_sizeAll.cy - 1;
692 if((m_dwExtendedStyle & SCRL_DISABLENOSCROLLV) != 0)
693 si.fMask |= SIF_DISABLENOSCROLL;
694 si.nPage = m_sizeClient.cy;
695 si.nPos = m_ptOffset.y;
696 pT->SetScrollInfo(SB_VERT, &si, TRUE);
697 }
698
699 int x = m_ptOffset.x;
700 int y = m_ptOffset.y;
701 if(pT->AdjustScrollOffset(x, y))
702 {
703 // Children will be moved in SetScrollOffset, if needed
704 pT->ScrollWindowEx(m_ptOffset.x - x, m_ptOffset.y - y, (m_uScrollFlags & ~SCRL_SCROLLCHILDREN));
705 SetScrollOffset(x, y, FALSE);
706 }
707 }
708
709 void DoScroll(int nType, int nScrollCode, int& cxyOffset, int cxySizeAll, int cxySizePage, int cxySizeLine)
710 {
711 T* pT = static_cast<T*>(this);
712 RECT rect = { 0 };
713 pT->GetClientRect(&rect);
714 int cxyClient = (nType == SB_VERT) ? rect.bottom : rect.right;
715 int cxyMax = cxySizeAll - cxyClient;
716
717 if(cxyMax < 0) // can't scroll, client area is bigger
718 return;
719
720 bool bUpdate = true;
721 int cxyScroll = 0;
722
723 switch(nScrollCode)
724 {
725 case SB_TOP: // top or all left
726 cxyScroll = cxyOffset;
727 cxyOffset = 0;
728 break;
729 case SB_BOTTOM: // bottom or all right
730 cxyScroll = cxyOffset - cxyMax;
731 cxyOffset = cxyMax;
732 break;
733 case SB_LINEUP: // line up or line left
734 if(cxyOffset >= cxySizeLine)
735 {
736 cxyScroll = cxySizeLine;
737 cxyOffset -= cxySizeLine;
738 }
739 else
740 {
741 cxyScroll = cxyOffset;
742 cxyOffset = 0;
743 }
744 break;
745 case SB_LINEDOWN: // line down or line right
746 if(cxyOffset < cxyMax - cxySizeLine)
747 {
748 cxyScroll = -cxySizeLine;
749 cxyOffset += cxySizeLine;
750 }
751 else
752 {
753 cxyScroll = cxyOffset - cxyMax;
754 cxyOffset = cxyMax;
755 }
756 break;
757 case SB_PAGEUP: // page up or page left
758 if(cxyOffset >= cxySizePage)
759 {
760 cxyScroll = cxySizePage;
761 cxyOffset -= cxySizePage;
762 }
763 else
764 {
765 cxyScroll = cxyOffset;
766 cxyOffset = 0;
767 }
768 break;
769 case SB_PAGEDOWN: // page down or page right
770 if(cxyOffset < cxyMax - cxySizePage)
771 {
772 cxyScroll = -cxySizePage;
773 cxyOffset += cxySizePage;
774 }
775 else
776 {
777 cxyScroll = cxyOffset - cxyMax;
778 cxyOffset = cxyMax;
779 }
780 break;
781 case SB_THUMBTRACK:
782 if(IsNoThumbTracking())
783 break;
784 // else fall through
785 case SB_THUMBPOSITION:
786 {
787 SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS };
788 if(pT->GetScrollInfo(nType, &si))
789 {
790 cxyScroll = cxyOffset - si.nTrackPos;
791 cxyOffset = si.nTrackPos;
792 }
793 }
794 break;
795 case SB_ENDSCROLL:
796 default:
797 bUpdate = false;
798 break;
799 }
800
801 if(bUpdate && cxyScroll != 0)
802 {
803 pT->SetScrollPos(nType, cxyOffset, TRUE);
804 if(nType == SB_VERT)
805 pT->ScrollWindowEx(0, cxyScroll, m_uScrollFlags);
806 else
807 pT->ScrollWindowEx(cxyScroll, 0, m_uScrollFlags);
808 }
809 }
810
811 static int CalcLineOrPage(int nVal, int nMax, int nDiv)
812 {
813 if(nVal == 0)
814 {
815 nVal = nMax / nDiv;
816 if(nVal < 1)
817 nVal = 1;
818 }
819 else if(nVal > nMax)
820 {
821 nVal = nMax;
822 }
823
824 return nVal;
825 }
826
827 bool AdjustScrollOffset(int& x, int& y)
828 {
829 int xOld = x;
830 int yOld = y;
831
832 int cxMax = m_sizeAll.cx - m_sizeClient.cx;
833 if(x > cxMax)
834 x = (cxMax >= 0) ? cxMax : 0;
835 else if(x < 0)
836 x = 0;
837
838 int cyMax = m_sizeAll.cy - m_sizeClient.cy;
839 if(y > cyMax)
840 y = (cyMax >= 0) ? cyMax : 0;
841 else if(y < 0)
842 y = 0;
843
844 return (x != xOld || y != yOld);
845 }
846
847 void GetSystemSettings()
848 {
849 #ifndef _WIN32_WCE
850 #ifndef SPI_GETWHEELSCROLLLINES
851 const UINT SPI_GETWHEELSCROLLLINES = 104;
852 #endif // !SPI_GETWHEELSCROLLLINES
853 ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &m_nWheelLines, 0);
854
855 #ifndef SPI_GETWHEELSCROLLCHARS
856 const UINT SPI_GETWHEELSCROLLCHARS = 0x006C;
857 #endif // !SPI_GETWHEELSCROLLCHARS
858 ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &m_nHWheelChars, 0);
859
860 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
861 if(m_uMsgMouseWheel != 0)
862 m_uMsgMouseWheel = ::RegisterWindowMessage(MSH_MOUSEWHEEL);
863
864 HWND hWndWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE);
865 if(::IsWindow(hWndWheel))
866 {
867 UINT uMsgScrollLines = ::RegisterWindowMessage(MSH_SCROLL_LINES);
868 if(uMsgScrollLines != 0)
869 m_nWheelLines = (int)::SendMessage(hWndWheel, uMsgScrollLines, 0, 0L);
870 }
871 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
872 #endif // !_WIN32_WCE
873 }
874
875 bool IsScrollingChildren() const
876 {
877 return (m_dwExtendedStyle & SCRL_SCROLLCHILDREN) != 0;
878 }
879
880 bool IsErasingBackground() const
881 {
882 return (m_dwExtendedStyle & SCRL_ERASEBACKGROUND) != 0;
883 }
884
885 bool IsNoThumbTracking() const
886 {
887 return (m_dwExtendedStyle & SCRL_NOTHUMBTRACKING) != 0;
888 }
889
890 #if (WINVER >= 0x0500)
891 bool IsSmoothScroll() const
892 {
893 return (m_dwExtendedStyle & SCRL_SMOOTHSCROLL) != 0;
894 }
895 #endif // (WINVER >= 0x0500)
896 };
897
898
899 ///////////////////////////////////////////////////////////////////////////////
900 // CScrollWindowImpl - Implements a scrollable window
901
902 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
903 class ATL_NO_VTABLE CScrollWindowImpl : public ATL::CWindowImpl<T, TBase, TWinTraits>, public CScrollImpl< T >
904 {
905 public:
906 BOOL SubclassWindow(HWND hWnd)
907 {
908 #if (_MSC_VER >= 1300)
909 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
910 #else // !(_MSC_VER >= 1300)
911 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
912 BOOL bRet = _baseClass::SubclassWindow(hWnd);
913 #endif // !(_MSC_VER >= 1300)
914 if(bRet != FALSE)
915 {
916 T* pT = static_cast<T*>(this);
917 pT->GetSystemSettings();
918
919 RECT rect = { 0 };
920 GetClientRect(&rect);
921 pT->DoSize(rect.right, rect.bottom);
922 }
923
924 return bRet;
925 }
926
927 BEGIN_MSG_MAP(CScrollWindowImpl)
928 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
929 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
930 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
931 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
932 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
933 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)) && !defined(_WIN32_WCE)
934 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
935 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
936 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
937 MESSAGE_HANDLER(WM_PAINT, CScrollImpl< T >::OnPaint)
938 #ifndef _WIN32_WCE
939 MESSAGE_HANDLER(WM_PRINTCLIENT, CScrollImpl< T >::OnPaint)
940 #endif // !_WIN32_WCE
941 ALT_MSG_MAP(1)
942 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
943 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
944 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
945 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
946 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
947 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
948 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
949 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
950 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
951 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
952 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
953 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
954 END_MSG_MAP()
955 };
956
957
958 ///////////////////////////////////////////////////////////////////////////////
959 // CMapScrollImpl - Provides mapping and scrolling support to any window
960
961 #ifndef _WIN32_WCE
962
963 template <class T>
964 class CMapScrollImpl : public CScrollImpl< T >
965 {
966 public:
967 int m_nMapMode;
968 RECT m_rectLogAll;
969 SIZE m_sizeLogLine;
970 SIZE m_sizeLogPage;
971
972 // Constructor
973 CMapScrollImpl() : m_nMapMode(MM_TEXT)
974 {
975 ::SetRectEmpty(&m_rectLogAll);
976 m_sizeLogPage.cx = 0;
977 m_sizeLogPage.cy = 0;
978 m_sizeLogLine.cx = 0;
979 m_sizeLogLine.cy = 0;
980 }
981
982 // Attributes & Operations
983 // mapping mode operations
984 void SetScrollMapMode(int nMapMode)
985 {
986 ATLASSERT(nMapMode >= MM_MIN && nMapMode <= MM_MAX_FIXEDSCALE);
987 m_nMapMode = nMapMode;
988 }
989
990 int GetScrollMapMode() const
991 {
992 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
993 return m_nMapMode;
994 }
995
996 // offset operations
997 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
998 {
999 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1000 POINT ptOff = { x, y };
1001 // block: convert logical to device units
1002 {
1003 CWindowDC dc(NULL);
1004 dc.SetMapMode(m_nMapMode);
1005 dc.LPtoDP(&ptOff);
1006 }
1007 CScrollImpl< T >::SetScrollOffset(ptOff, bRedraw);
1008 }
1009
1010 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
1011 {
1012 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
1013 }
1014
1015 void GetScrollOffset(POINT& ptOffset) const
1016 {
1017 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1018 ptOffset = m_ptOffset;
1019 // block: convert device to logical units
1020 {
1021 CWindowDC dc(NULL);
1022 dc.SetMapMode(m_nMapMode);
1023 dc.DPtoLP(&ptOffset);
1024 }
1025 }
1026
1027 // size operations
1028 void SetScrollSize(int xMin, int yMin, int xMax, int yMax, BOOL bRedraw = TRUE, bool bResetOffset = true)
1029 {
1030 ATLASSERT(xMax > xMin && yMax > yMin);
1031 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1032
1033 ::SetRect(&m_rectLogAll, xMin, yMin, xMax, yMax);
1034
1035 SIZE sizeAll = { 0 };
1036 sizeAll.cx = xMax - xMin + 1;
1037 sizeAll.cy = yMax - yMin + 1;
1038 // block: convert logical to device units
1039 {
1040 CWindowDC dc(NULL);
1041 dc.SetMapMode(m_nMapMode);
1042 dc.LPtoDP(&sizeAll);
1043 }
1044 CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
1045 SetScrollLine(0, 0);
1046 SetScrollPage(0, 0);
1047 }
1048
1049 void SetScrollSize(RECT& rcScroll, BOOL bRedraw = TRUE, bool bResetOffset = true)
1050 {
1051 SetScrollSize(rcScroll.left, rcScroll.top, rcScroll.right, rcScroll.bottom, bRedraw, bResetOffset);
1052 }
1053
1054 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE, bool bResetOffset = true)
1055 {
1056 SetScrollSize(0, 0, cx, cy, bRedraw, bResetOffset);
1057 }
1058
1059 void SetScrollSize(SIZE size, BOOL bRedraw = TRUE, bool bResetOffset = true)
1060 {
1061 SetScrollSize(0, 0, size.cx, size.cy, bRedraw, bResetOffset);
1062 }
1063
1064 void GetScrollSize(RECT& rcScroll) const
1065 {
1066 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1067 rcScroll = m_rectLogAll;
1068 }
1069
1070 // line operations
1071 void SetScrollLine(int cxLine, int cyLine)
1072 {
1073 ATLASSERT(cxLine >= 0 && cyLine >= 0);
1074 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1075
1076 m_sizeLogLine.cx = cxLine;
1077 m_sizeLogLine.cy = cyLine;
1078 SIZE sizeLine = m_sizeLogLine;
1079 // block: convert logical to device units
1080 {
1081 CWindowDC dc(NULL);
1082 dc.SetMapMode(m_nMapMode);
1083 dc.LPtoDP(&sizeLine);
1084 }
1085 CScrollImpl< T >::SetScrollLine(sizeLine);
1086 }
1087
1088 void SetScrollLine(SIZE sizeLine)
1089 {
1090 SetScrollLine(sizeLine.cx, sizeLine.cy);
1091 }
1092
1093 void GetScrollLine(SIZE& sizeLine) const
1094 {
1095 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1096 sizeLine = m_sizeLogLine;
1097 }
1098
1099 // page operations
1100 void SetScrollPage(int cxPage, int cyPage)
1101 {
1102 ATLASSERT(cxPage >= 0 && cyPage >= 0);
1103 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1104
1105 m_sizeLogPage.cx = cxPage;
1106 m_sizeLogPage.cy = cyPage;
1107 SIZE sizePage = m_sizeLogPage;
1108 // block: convert logical to device units
1109 {
1110 CWindowDC dc(NULL);
1111 dc.SetMapMode(m_nMapMode);
1112 dc.LPtoDP(&sizePage);
1113 }
1114 CScrollImpl< T >::SetScrollPage(sizePage);
1115 }
1116
1117 void SetScrollPage(SIZE sizePage)
1118 {
1119 SetScrollPage(sizePage.cx, sizePage.cy);
1120 }
1121
1122 void GetScrollPage(SIZE& sizePage) const
1123 {
1124 ATLASSERT(m_nMapMode >= MM_MIN && m_nMapMode <= MM_MAX_FIXEDSCALE);
1125 sizePage = m_sizeLogPage;
1126 }
1127
1128 BEGIN_MSG_MAP(CMapScrollImpl)
1129 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1130 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1131 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1132 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1133 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1134 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1135 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1136 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1137 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1138 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1139 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1140 ALT_MSG_MAP(1)
1141 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1142 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1143 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1144 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1145 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1146 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1147 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1148 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1149 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1150 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1151 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1152 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1153 END_MSG_MAP()
1154
1155 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1156 {
1157 T* pT = static_cast<T*>(this);
1158 ATLASSERT(::IsWindow(pT->m_hWnd));
1159 if(wParam != NULL)
1160 {
1161 CDCHandle dc = (HDC)wParam;
1162 int nMapModeSav = dc.GetMapMode();
1163 dc.SetMapMode(m_nMapMode);
1164 POINT ptViewportOrg = { 0, 0 };
1165 if(m_nMapMode == MM_TEXT)
1166 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1167 else
1168 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy, &ptViewportOrg);
1169 POINT ptWindowOrg = { 0, 0 };
1170 dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top, &ptWindowOrg);
1171
1172 pT->DoPaint(dc);
1173
1174 dc.SetMapMode(nMapModeSav);
1175 dc.SetViewportOrg(ptViewportOrg);
1176 dc.SetWindowOrg(ptWindowOrg);
1177 }
1178 else
1179 {
1180 CPaintDC dc(pT->m_hWnd);
1181 dc.SetMapMode(m_nMapMode);
1182 if(m_nMapMode == MM_TEXT)
1183 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
1184 else
1185 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y + m_sizeAll.cy);
1186 dc.SetWindowOrg(m_rectLogAll.left, m_rectLogAll.top);
1187 pT->DoPaint(dc.m_hDC);
1188 }
1189 return 0;
1190 }
1191 };
1192
1193 #endif // !_WIN32_WCE
1194
1195
1196 ///////////////////////////////////////////////////////////////////////////////
1197 // CMapScrollWindowImpl - Implements scrolling window with mapping
1198
1199 #ifndef _WIN32_WCE
1200
1201 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1202 class ATL_NO_VTABLE CMapScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CMapScrollImpl< T >
1203 {
1204 public:
1205 BOOL SubclassWindow(HWND hWnd)
1206 {
1207 #if (_MSC_VER >= 1300)
1208 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1209 #else // !(_MSC_VER >= 1300)
1210 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1211 BOOL bRet = _baseClass::SubclassWindow(hWnd);
1212 #endif // !(_MSC_VER >= 1300)
1213 if(bRet != FALSE)
1214 {
1215 T* pT = static_cast<T*>(this);
1216 pT->GetSystemSettings();
1217
1218 RECT rect = { 0 };
1219 GetClientRect(&rect);
1220 pT->DoSize(rect.right, rect.bottom);
1221 }
1222
1223 return bRet;
1224 }
1225
1226 BEGIN_MSG_MAP(CMapScrollWindowImpl)
1227 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1228 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1229 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1230 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1231 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1232 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1233 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1234 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1235 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1236 MESSAGE_HANDLER(WM_PAINT, CMapScrollImpl< T >::OnPaint)
1237 MESSAGE_HANDLER(WM_PRINTCLIENT, CMapScrollImpl< T >::OnPaint)
1238 ALT_MSG_MAP(1)
1239 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1240 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1241 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1242 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1243 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1244 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1245 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1246 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1247 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1248 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1249 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1250 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1251 END_MSG_MAP()
1252 };
1253
1254 #endif // !_WIN32_WCE
1255
1256
1257 ///////////////////////////////////////////////////////////////////////////////
1258 // CFSBWindow - Use as a base instead of CWindow to get flat scroll bar support
1259
1260 #if defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
1261
1262 template <class TBase = ATL::CWindow>
1263 class CFSBWindowT : public TBase, public CFlatScrollBarImpl<CFSBWindowT< TBase > >
1264 {
1265 public:
1266 // Constructors
1267 CFSBWindowT(HWND hWnd = NULL) : TBase(hWnd)
1268 { }
1269
1270 CFSBWindowT< TBase >& operator =(HWND hWnd)
1271 {
1272 m_hWnd = hWnd;
1273 return *this;
1274 }
1275
1276 // CWindow overrides that use flat scroll bar API
1277 // (only those methods that are used by scroll window classes)
1278 int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
1279 {
1280 ATLASSERT(::IsWindow(m_hWnd));
1281 return FlatSB_SetScrollPos(nBar, nPos, bRedraw);
1282 }
1283
1284 BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
1285 {
1286 ATLASSERT(::IsWindow(m_hWnd));
1287 return FlatSB_GetScrollInfo(nBar, lpScrollInfo);
1288 }
1289
1290 BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
1291 {
1292 ATLASSERT(::IsWindow(m_hWnd));
1293 return FlatSB_SetScrollInfo(nBar, lpScrollInfo, bRedraw);
1294 }
1295 };
1296
1297 typedef CFSBWindowT<ATL::CWindow> CFSBWindow;
1298
1299 #endif // defined(__ATLCTRLS_H__) && (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
1300
1301
1302 ///////////////////////////////////////////////////////////////////////////////
1303 // CZoomScrollImpl - Provides zooming and scrolling support to any window
1304
1305 #ifndef _WIN32_WCE
1306
1307 // The zoom modes that can be set with the SetZoomMode method
1308 enum
1309 {
1310 ZOOMMODE_OFF,
1311 ZOOMMODE_IN, // If left mouse button is clicked or dragged, zoom in on point clicked or rectangle dragged.
1312 ZOOMMODE_OUT // If left mouse button clicked, zoom out on point clicked.
1313 };
1314
1315 // Notification to parent that zoom scale changed as a result of user mouse action.
1316 #define ZSN_ZOOMCHANGED (NM_FIRST - 50)
1317
1318 template <class T>
1319 class CZoomScrollImpl : public CScrollImpl< T >
1320 {
1321 public:
1322 enum { m_cxyMinZoomRect = 12 }; // min rect size to zoom in on rect.
1323
1324 struct _ChildPlacement
1325 {
1326 HWND hWnd;
1327 int x;
1328 int y;
1329 int cx;
1330 int cy;
1331
1332 bool operator ==(const _ChildPlacement& cp) const { return (memcmp(this, &cp, sizeof(_ChildPlacement)) == 0); }
1333 };
1334
1335 // Data members
1336 SIZE m_sizeLogAll;
1337 SIZE m_sizeLogLine;
1338 SIZE m_sizeLogPage;
1339 float m_fZoomScale;
1340 float m_fZoomScaleMin;
1341 float m_fZoomScaleMax;
1342 float m_fZoomDelta; // Used in ZOOMMODE_IN and ZOOMMODE_OUT on left-button click.
1343 int m_nZoomMode;
1344 RECT m_rcTrack;
1345 bool m_bTracking;
1346
1347 bool m_bZoomChildren;
1348 ATL::CSimpleArray<_ChildPlacement> m_arrChildren;
1349
1350 // Constructor
1351 CZoomScrollImpl(): m_fZoomScale(1.0f), m_fZoomScaleMin(0.1f), m_fZoomScaleMax(100.0f), m_fZoomDelta(0.5f),
1352 m_nZoomMode(ZOOMMODE_OFF), m_bTracking(false), m_bZoomChildren(false)
1353 {
1354 m_sizeLogAll.cx = 0;
1355 m_sizeLogAll.cy = 0;
1356 m_sizeLogPage.cx = 0;
1357 m_sizeLogPage.cy = 0;
1358 m_sizeLogLine.cx = 0;
1359 m_sizeLogLine.cy = 0;
1360 ::SetRectEmpty(&m_rcTrack);
1361 }
1362
1363 // Attributes & Operations
1364 // size operations
1365 void SetScrollSize(int cxLog, int cyLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
1366 {
1367 ATLASSERT(cxLog >= 0 && cyLog >= 0);
1368
1369 // Set up the defaults
1370 if((cxLog == 0) && (cyLog == 0))
1371 {
1372 cxLog = 1;
1373 cyLog = 1;
1374 }
1375
1376 m_sizeLogAll.cx = cxLog;
1377 m_sizeLogAll.cy = cyLog;
1378 SIZE sizeAll = { 0 };
1379 sizeAll.cx = (int)((float)m_sizeLogAll.cx * m_fZoomScale);
1380 sizeAll.cy = (int)((float)m_sizeLogAll.cy * m_fZoomScale);
1381
1382 CScrollImpl< T >::SetScrollSize(sizeAll, bRedraw, bResetOffset);
1383 }
1384
1385 void SetScrollSize(SIZE sizeLog, BOOL bRedraw = TRUE, bool bResetOffset = true)
1386 {
1387 SetScrollSize(sizeLog.cx, sizeLog.cy, bRedraw, bResetOffset);
1388 }
1389
1390 void GetScrollSize(SIZE& sizeLog) const
1391 {
1392 sizeLog = m_sizeLogAll;
1393 }
1394
1395 // line operations
1396 void SetScrollLine(int cxLogLine, int cyLogLine)
1397 {
1398 ATLASSERT(cxLogLine >= 0 && cyLogLine >= 0);
1399
1400 m_sizeLogLine.cx = cxLogLine;
1401 m_sizeLogLine.cy = cyLogLine;
1402
1403 SIZE sizeLine = { 0 };
1404 sizeLine.cx = (int)((float)m_sizeLogLine.cx * m_fZoomScale);
1405 sizeLine.cy = (int)((float)m_sizeLogLine.cy * m_fZoomScale);
1406 CScrollImpl< T >::SetScrollLine(sizeLine);
1407 }
1408
1409 void SetScrollLine(SIZE sizeLogLine)
1410 {
1411 SetScrollLine(sizeLogLine.cx, sizeLogLine.cy);
1412 }
1413
1414 void GetScrollLine(SIZE& sizeLogLine) const
1415 {
1416 sizeLogLine = m_sizeLogLine;
1417 }
1418
1419 // page operations
1420 void SetScrollPage(int cxLogPage, int cyLogPage)
1421 {
1422 ATLASSERT((cxLogPage >= 0) && (cyLogPage >= 0));
1423
1424 m_sizeLogPage.cx = cxLogPage;
1425 m_sizeLogPage.cy = cyLogPage;
1426
1427 SIZE sizePage = { 0 };
1428 sizePage.cx = (int)((float)m_sizeLogPage.cx * m_fZoomScale);
1429 sizePage.cy = (int)((float)m_sizeLogPage.cy * m_fZoomScale);
1430
1431 CScrollImpl< T >::SetScrollPage(sizePage);
1432 }
1433
1434 void SetScrollPage(SIZE sizeLogPage)
1435 {
1436 SetScrollPage(sizeLogPage.cx, sizeLogPage.cy);
1437 }
1438
1439 void GetScrollPage(SIZE& sizeLogPage) const
1440 {
1441 sizeLogPage = m_sizeLogPage;
1442 }
1443
1444 void SetZoomScale(float fZoomScale)
1445 {
1446 ATLASSERT(fZoomScale > 0.0f);
1447 if(fZoomScale <= 0.0f)
1448 return;
1449
1450 m_fZoomScale = fZoomScale;
1451 if(m_fZoomScale < m_fZoomScaleMin)
1452 m_fZoomScale = m_fZoomScaleMin;
1453 else if(m_fZoomScale > m_fZoomScaleMax)
1454 m_fZoomScale = m_fZoomScaleMax;
1455 }
1456
1457 float GetZoomScale() const
1458 {
1459 return m_fZoomScale;
1460 }
1461
1462 void SetZoomScaleMin(float fZoomScaleMin)
1463 {
1464 ATLASSERT(fZoomScaleMin > 0.0f);
1465 ATLASSERT(fZoomScaleMin <= m_fZoomScaleMax);
1466
1467 m_fZoomScaleMin = fZoomScaleMin;
1468 }
1469
1470 float GetZoomScaleMin() const
1471 {
1472 return m_fZoomScaleMin;
1473 }
1474
1475 void SetZoomScaleMax(float fZoomScaleMax)
1476 {
1477 ATLASSERT(fZoomScaleMax > 0.0f);
1478 ATLASSERT(m_fZoomScaleMin <= fZoomScaleMax);
1479
1480 m_fZoomScaleMax = fZoomScaleMax;
1481 }
1482
1483 float GetZoomScaleMax() const
1484 {
1485 return m_fZoomScaleMax;
1486 }
1487
1488 void SetZoomDelta(float fZoomDelta)
1489 {
1490 ATLASSERT(fZoomDelta >= 0.0f);
1491
1492 if(fZoomDelta >= 0.0f)
1493 m_fZoomDelta = fZoomDelta;
1494 }
1495
1496 float GetZoomDelta() const
1497 {
1498 return m_fZoomDelta;
1499 }
1500
1501 void SetZoomMode(int nZoomMode)
1502 {
1503 m_nZoomMode = nZoomMode;
1504 }
1505
1506 int GetZoomMode() const
1507 {
1508 return m_nZoomMode;
1509 }
1510
1511 void SetZoomChildren(bool bEnable = true)
1512 {
1513 T* pT = static_cast<T*>(this);
1514 ATLASSERT(::IsWindow(pT->m_hWnd));
1515
1516 m_bZoomChildren = bEnable;
1517
1518 m_arrChildren.RemoveAll();
1519 if(m_bZoomChildren)
1520 {
1521 for(HWND hWndChild = ::GetWindow(pT->m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
1522 {
1523 RECT rect = { 0 };
1524 ::GetWindowRect(hWndChild, &rect);
1525 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rect, 2);
1526
1527 _ChildPlacement cp = { 0 };
1528 cp.hWnd = hWndChild;
1529 cp.x = rect.left;
1530 cp.y = rect.top;
1531 cp.cx = rect.right - rect.left;
1532 cp.cy = rect.bottom - rect.top;
1533 m_arrChildren.Add(cp);
1534 }
1535 }
1536 }
1537
1538 bool GetZoomChildren() const
1539 {
1540 return m_bZoomChildren;
1541 }
1542
1543 void Zoom(int x, int y, float fZoomScale)
1544 {
1545 if(fZoomScale <= 0.0f)
1546 return;
1547
1548 if(fZoomScale < m_fZoomScaleMin)
1549 fZoomScale = m_fZoomScaleMin;
1550 else if(fZoomScale > m_fZoomScaleMax)
1551 fZoomScale = m_fZoomScaleMax;
1552
1553 T* pT = static_cast<T*>(this);
1554 POINT pt = { x, y };
1555 if(!pT->PtInDevRect(pt))
1556 return;
1557
1558 pT->ViewDPtoLP(&pt);
1559 pT->Zoom(fZoomScale, false);
1560 pT->CenterOnLogicalPoint(pt);
1561 }
1562
1563 void Zoom(POINT pt, float fZoomScale)
1564 {
1565 T* pT = static_cast<T*>(this);
1566 pT->Zoom(pt.x, pt.y, fZoomScale);
1567 }
1568
1569 void Zoom(RECT& rc)
1570 {
1571 T* pT = static_cast<T*>(this);
1572 RECT rcZoom = rc;
1573 pT->NormalizeRect(rcZoom);
1574 SIZE size = { rcZoom.right - rcZoom.left, rcZoom.bottom - rcZoom.top };
1575 POINT pt = { rcZoom.left + size.cx / 2, rcZoom.top + size.cy / 2 };
1576 if(size.cx < m_cxyMinZoomRect || size.cy < m_cxyMinZoomRect)
1577 {
1578 pT->Zoom(pt, m_fZoomScale + m_fZoomDelta);
1579 return;
1580 }
1581
1582 ATLASSERT((size.cx > 0) && (size.cy > 0));
1583
1584 float fScaleH = (float)(m_sizeClient.cx + 1) / (float)size.cx;
1585 float fScaleV = (float)(m_sizeClient.cy + 1) / (float)size.cy;
1586 float fZoomScale = __min(fScaleH, fScaleV) * m_fZoomScale;
1587 pT->Zoom(pt, fZoomScale);
1588 }
1589
1590 void Zoom(float fZoomScale, bool bCenter = true)
1591 {
1592 if(fZoomScale <= 0.0f)
1593 return;
1594
1595 if(fZoomScale < m_fZoomScaleMin)
1596 fZoomScale = m_fZoomScaleMin;
1597 else if(fZoomScale > m_fZoomScaleMax)
1598 fZoomScale = m_fZoomScaleMax;
1599
1600 T* pT = static_cast<T*>(this);
1601 POINT pt = { 0 };
1602 if(bCenter)
1603 {
1604 RECT rcClient = { 0 };
1605 ::GetClientRect(pT->m_hWnd, &rcClient);
1606 pt.x = rcClient.right / 2;
1607 pt.y = rcClient.bottom / 2;
1608 pT->ViewDPtoLP(&pt);
1609 }
1610
1611 // Modify the Viewport extent
1612 SIZE sizeAll = { 0 };
1613 sizeAll.cx = (int)((float)m_sizeLogAll.cx * fZoomScale);
1614 sizeAll.cy = (int)((float)m_sizeLogAll.cy * fZoomScale);
1615
1616 // Update scroll bars and window
1617 CScrollImpl< T >::SetScrollSize(sizeAll);
1618
1619 // Zoom all children if needed
1620 if(m_bZoomChildren && (m_fZoomScale != fZoomScale))
1621 {
1622 for(int i = 0; i < m_arrChildren.GetSize(); i++)
1623 {
1624 ATLASSERT(::IsWindow(m_arrChildren[i].hWnd));
1625
1626 ::SetWindowPos(m_arrChildren[i].hWnd, NULL,
1627 (int)((float)m_arrChildren[i].x * fZoomScale + 0.5f),
1628 (int)((float)m_arrChildren[i].y * fZoomScale + 0.5f),
1629 (int)((float)m_arrChildren[i].cx * fZoomScale + 0.5f),
1630 (int)((float)m_arrChildren[i].cy * fZoomScale + 0.5f),
1631 SWP_NOZORDER | SWP_NOACTIVATE);
1632 }
1633 }
1634
1635 // Set new zoom scale
1636 m_fZoomScale = fZoomScale;
1637
1638 if(bCenter)
1639 pT->CenterOnLogicalPoint(pt);
1640 }
1641
1642 // Helper functions
1643 void PrepareDC(CDCHandle dc)
1644 {
1645 ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
1646 dc.SetMapMode(MM_ANISOTROPIC);
1647 dc.SetWindowExt(m_sizeLogAll);
1648 dc.SetViewportExt(m_sizeAll);
1649 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
1650 }
1651
1652 void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
1653 {
1654 ATLASSERT(lpPoints);
1655 T* pT = static_cast<T*>(this);
1656 ATLASSERT(::IsWindow(pT->m_hWnd));
1657
1658 CWindowDC dc(pT->m_hWnd);
1659 pT->PrepareDC(dc.m_hDC);
1660 dc.DPtoLP(lpPoints, nCount);
1661 }
1662
1663 void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
1664 {
1665 ATLASSERT(lpPoints);
1666 T* pT = static_cast<T*>(this);
1667 ATLASSERT(::IsWindow(pT->m_hWnd));
1668
1669 CWindowDC dc(pT->m_hWnd);
1670 pT->PrepareDC(dc.m_hDC);
1671 dc.LPtoDP(lpPoints, nCount);
1672 }
1673
1674 void ClientToDevice(POINT &pt)
1675 {
1676 pt.x += m_ptOffset.x;
1677 pt.y += m_ptOffset.y;
1678 }
1679
1680 void DeviceToClient(POINT &pt)
1681 {
1682 pt.x -= m_ptOffset.x;
1683 pt.y -= m_ptOffset.y;
1684 }
1685
1686 void CenterOnPoint(POINT pt)
1687 {
1688 T* pT = static_cast<T*>(this);
1689 RECT rect = { 0 };
1690 pT->GetClientRect(&rect);
1691
1692 int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x;
1693 if(xOfs < 0)
1694 {
1695 xOfs = 0;
1696 }
1697 else
1698 {
1699 int xMax = __max((int)(m_sizeAll.cx - rect.right), 0);
1700 if(xOfs > xMax)
1701 xOfs = xMax;
1702 }
1703
1704 int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y;
1705 if(yOfs < 0)
1706 {
1707 yOfs = 0;
1708 }
1709 else
1710 {
1711 int yMax = __max((int)(m_sizeAll.cy - rect.bottom), 0);
1712 if(yOfs > yMax)
1713 yOfs = yMax;
1714 }
1715
1716 CScrollImpl< T >::SetScrollOffset(xOfs, yOfs);
1717 }
1718
1719 void CenterOnLogicalPoint(POINT ptLog)
1720 {
1721 T* pT = static_cast<T*>(this);
1722 pT->ViewLPtoDP(&ptLog);
1723 pT->DeviceToClient(ptLog);
1724 pT->CenterOnPoint(ptLog);
1725 }
1726
1727 BOOL PtInDevRect(POINT pt)
1728 {
1729 RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy };
1730 ::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y);
1731 return ::PtInRect(&rc, pt);
1732 }
1733
1734 void NormalizeRect(RECT& rc)
1735 {
1736 if(rc.left > rc.right)
1737 {
1738 int r = rc.right;
1739 rc.right = rc.left;
1740 rc.left = r;
1741 }
1742
1743 if(rc.top > rc.bottom)
1744 {
1745 int b = rc.bottom;
1746 rc.bottom = rc.top;
1747 rc.top = b;
1748 }
1749 }
1750
1751 void DrawTrackRect()
1752 {
1753 T* pT = static_cast<T*>(this);
1754 const SIZE sizeLines = { 2, 2 };
1755 RECT rc = m_rcTrack;
1756 pT->NormalizeRect(rc);
1757 if(!::IsRectEmpty(&rc))
1758 {
1759 ::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2);
1760 CWindowDC dc(NULL);
1761 dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
1762 }
1763 }
1764
1765 void NotifyParentZoomChanged()
1766 {
1767 T* pT = static_cast<T*>(this);
1768 int nId = pT->GetDlgCtrlID();
1769 NMHDR nmhdr = { pT->m_hWnd, (UINT_PTR)nId, ZSN_ZOOMCHANGED };
1770 ::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
1771 }
1772
1773 BEGIN_MSG_MAP(CZoomScrollImpl)
1774 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
1775 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1776 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1777 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1778 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1779 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1780 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1781 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1782 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1783 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1784 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1785 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1786 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
1787 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
1788 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
1789 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
1790 ALT_MSG_MAP(1)
1791 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1792 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1793 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1794 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1795 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1796 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1797 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1798 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1799 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1800 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1801 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1802 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1803 END_MSG_MAP()
1804
1805 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1806 {
1807 T* pT = static_cast<T*>(this);
1808 ATLASSERT(::IsWindow(pT->m_hWnd));
1809 ATLASSERT((m_sizeLogAll.cx >= 0) && (m_sizeLogAll.cy >= 0));
1810 ATLASSERT((m_sizeAll.cx >= 0) && (m_sizeAll.cy >= 0));
1811
1812 if(wParam != NULL)
1813 {
1814 CDCHandle dc = (HDC)wParam;
1815 int nMapModeSav = dc.GetMapMode();
1816 dc.SetMapMode(MM_ANISOTROPIC);
1817 SIZE szWindowExt = { 0, 0 };
1818 dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
1819 SIZE szViewportExt = { 0, 0 };
1820 dc.SetViewportExt(m_sizeAll, &szViewportExt);
1821 POINT ptViewportOrg = { 0, 0 };
1822 dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
1823
1824 pT->DoPaint(dc);
1825
1826 dc.SetMapMode(nMapModeSav);
1827 dc.SetWindowExt(szWindowExt);
1828 dc.SetViewportExt(szViewportExt);
1829 dc.SetViewportOrg(ptViewportOrg);
1830 }
1831 else
1832 {
1833 CPaintDC dc(pT->m_hWnd);
1834 pT->PrepareDC(dc.m_hDC);
1835 pT->DoPaint(dc.m_hDC);
1836 }
1837
1838 return 0;
1839 }
1840
1841 LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1842 {
1843 if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking)
1844 {
1845 T* pT = static_cast<T*>(this);
1846 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1847 if(pT->PtInDevRect(pt))
1848 {
1849 pT->SetCapture();
1850 m_bTracking = true;
1851 ::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
1852 }
1853 }
1854
1855 bHandled = FALSE;
1856 return 0;
1857 }
1858
1859 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1860 {
1861 if(m_bTracking)
1862 {
1863 T* pT = static_cast<T*>(this);
1864 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
1865 if(pT->PtInDevRect(pt))
1866 {
1867 pT->DrawTrackRect();
1868 m_rcTrack.right = pt.x;
1869 m_rcTrack.bottom = pt.y;
1870 pT->DrawTrackRect();
1871 }
1872 }
1873
1874 bHandled = FALSE;
1875 return 0;
1876 }
1877
1878 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
1879 {
1880 ::ReleaseCapture();
1881 if(m_nZoomMode == ZOOMMODE_OUT)
1882 {
1883 T* pT = static_cast<T*>(this);
1884 pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
1885 pT->NotifyParentZoomChanged();
1886 }
1887
1888 bHandled = FALSE;
1889 return 0;
1890 }
1891
1892 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1893 {
1894 if(m_bTracking)
1895 {
1896 m_bTracking = false;
1897 T* pT = static_cast<T*>(this);
1898 pT->DrawTrackRect();
1899 pT->Zoom(m_rcTrack);
1900 pT->NotifyParentZoomChanged();
1901 ::SetRectEmpty(&m_rcTrack);
1902 }
1903
1904 bHandled = FALSE;
1905 return 0;
1906 }
1907
1908 LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1909 {
1910 if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF)
1911 {
1912 T* pT = static_cast<T*>(this);
1913 if((HWND)wParam == pT->m_hWnd)
1914 {
1915 DWORD dwPos = ::GetMessagePos();
1916 POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
1917 pT->ScreenToClient(&pt);
1918 if(pT->PtInDevRect(pt))
1919 {
1920 ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
1921 return 1;
1922 }
1923 }
1924 }
1925
1926 bHandled = FALSE;
1927 return 0;
1928 }
1929 };
1930
1931 ///////////////////////////////////////////////////////////////////////////////
1932 // CZoomScrollWindowImpl - Implements scrolling window with zooming
1933
1934 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1935 class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
1936 {
1937 public:
1938 BOOL SubclassWindow(HWND hWnd)
1939 {
1940 #if (_MSC_VER >= 1300)
1941 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1942 #else // !(_MSC_VER >= 1300)
1943 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1944 BOOL bRet = _baseClass::SubclassWindow(hWnd);
1945 #endif // !(_MSC_VER >= 1300)
1946 if(bRet != FALSE)
1947 {
1948 T* pT = static_cast<T*>(this);
1949 pT->GetSystemSettings();
1950
1951 RECT rect = { 0 };
1952 GetClientRect(&rect);
1953 pT->DoSize(rect.right, rect.bottom);
1954 }
1955
1956 return bRet;
1957 }
1958
1959 BEGIN_MSG_MAP(CZoomScrollWindowImpl)
1960 MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
1961 MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
1962 MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
1963 MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
1964 #if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1965 MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
1966 #endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
1967 MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
1968 MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
1969 MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
1970 MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
1971 MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
1972 MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
1973 MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
1974 MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
1975 MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
1976 ALT_MSG_MAP(1)
1977 COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
1978 COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
1979 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
1980 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
1981 COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
1982 COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
1983 COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
1984 COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
1985 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
1986 COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
1987 COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
1988 COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
1989 END_MSG_MAP()
1990 };
1991
1992 #endif // !_WIN32_WCE
1993
1994
1995 ///////////////////////////////////////////////////////////////////////////////
1996 // CScrollContainer
1997
1998 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1999 class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
2000 {
2001 public:
2002 DECLARE_WND_CLASS_EX(NULL, 0, -1)
2003
2004 typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass;
2005
2006 // Data members
2007 ATL::CWindow m_wndClient;
2008 bool m_bAutoSizeClient;
2009 bool m_bDrawEdgeIfEmpty;
2010
2011 // Constructor
2012 CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
2013 {
2014 // Set CScrollWindowImpl extended style
2015 SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
2016 }
2017
2018 // Attributes
2019 HWND GetClient() const
2020 {
2021 return m_wndClient;
2022 }
2023
2024 HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
2025 {
2026 ATLASSERT(::IsWindow(m_hWnd));
2027
2028 HWND hWndOldClient = m_wndClient;
2029 m_wndClient = hWndClient;
2030
2031 SetRedraw(FALSE);
2032 SetScrollSize(1, 1, FALSE);
2033
2034 if(m_wndClient.m_hWnd != NULL)
2035 {
2036 m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
2037
2038 if(bClientSizeAsMin)
2039 {
2040 RECT rect = { 0 };
2041 m_wndClient.GetWindowRect(&rect);
2042 if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0)
2043 SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
2044 }
2045
2046 T* pT = static_cast<T*>(this);
2047 pT->UpdateLayout();
2048 }
2049
2050 SetRedraw(TRUE);
2051 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
2052
2053 return hWndOldClient;
2054 }
2055
2056 // Message map and handlers
2057 BEGIN_MSG_MAP(CScrollContainerImpl)
2058 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
2059 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
2060 CHAIN_MSG_MAP(_baseClass)
2061 FORWARD_NOTIFICATIONS()
2062 ALT_MSG_MAP(1)
2063 CHAIN_MSG_MAP_ALT(_baseClass, 1)
2064 END_MSG_MAP()
2065
2066 LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2067 {
2068 if(m_wndClient.m_hWnd != NULL)
2069 m_wndClient.SetFocus();
2070
2071 return 0;
2072 }
2073
2074 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2075 {
2076 return 1; // no background needed
2077 }
2078
2079 // Overrides for CScrollWindowImpl
2080 void DoSize(int cx, int cy)
2081 {
2082 _baseClass::DoSize(cx, cy);
2083
2084 T* pT = static_cast<T*>(this);
2085 pT->UpdateLayout();
2086 }
2087
2088 void DoPaint(CDCHandle dc)
2089 {
2090 if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL)
2091 {
2092 T* pT = static_cast<T*>(this);
2093 RECT rect = { 0 };
2094 pT->GetContainerRect(rect);
2095
2096 if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL)
2097 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
2098
2099 dc.FillRect(&rect, COLOR_APPWORKSPACE);
2100 }
2101 }
2102
2103 void ScrollToView(POINT pt)
2104 {
2105 CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt);
2106 }
2107
2108 void ScrollToView(RECT& rect)
2109 {
2110 CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect);
2111 }
2112
2113 void ScrollToView(HWND hWnd) // client window coordinates
2114 {
2115 T* pT = static_cast<T*>(this);
2116 pT; // avoid level 4 warning
2117 ATLASSERT(::IsWindow(pT->m_hWnd));
2118 ATLASSERT(m_wndClient.IsWindow());
2119
2120 RECT rect = { 0 };
2121 ::GetWindowRect(hWnd, &rect);
2122 ::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
2123 ScrollToView(rect);
2124 }
2125
2126 // Implementation - overrideable methods
2127 void UpdateLayout()
2128 {
2129 ATLASSERT(::IsWindow(m_hWnd));
2130
2131 if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL)
2132 {
2133 T* pT = static_cast<T*>(this);
2134 RECT rect = { 0 };
2135 pT->GetContainerRect(rect);
2136
2137 m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
2138 }
2139 else
2140 {
2141 Invalidate();
2142 }
2143 }
2144
2145 void GetContainerRect(RECT& rect)
2146 {
2147 GetClientRect(&rect);
2148
2149 if(rect.right < m_sizeAll.cx)
2150 rect.right = m_sizeAll.cx;
2151
2152 if(rect.bottom < m_sizeAll.cy)
2153 rect.bottom = m_sizeAll.cy;
2154 }
2155 };
2156
2157 class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
2158 {
2159 public:
2160 DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
2161 };
2162
2163 }; // namespace WTL
2164
2165 #endif // __ATLSCRL_H__
+0
-1130
src/third_party/wtl/Include/atlsplit.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLSPLIT_H__
9 #define __ATLSPLIT_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlsplit.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLWIN_H__
18 #error atlsplit.h requires atlwin.h to be included first
19 #endif
20
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // Classes in this file:
24 //
25 // CSplitterImpl<T>
26 // CSplitterWindowImpl<T, TBase, TWinTraits>
27 // CSplitterWindowT<t_bVertical> - CSplitterWindow, CHorSplitterWindow
28
29
30 namespace WTL
31 {
32
33 ///////////////////////////////////////////////////////////////////////////////
34 // CSplitterImpl - Provides splitter support to any window
35
36 // Splitter panes constants
37 #define SPLIT_PANE_LEFT 0
38 #define SPLIT_PANE_RIGHT 1
39 #define SPLIT_PANE_TOP SPLIT_PANE_LEFT
40 #define SPLIT_PANE_BOTTOM SPLIT_PANE_RIGHT
41 #define SPLIT_PANE_NONE -1
42
43 // Splitter extended styles
44 #define SPLIT_PROPORTIONAL 0x00000001
45 #define SPLIT_NONINTERACTIVE 0x00000002
46 #define SPLIT_RIGHTALIGNED 0x00000004
47 #define SPLIT_BOTTOMALIGNED SPLIT_RIGHTALIGNED
48 #define SPLIT_GRADIENTBAR 0x00000008
49 #define SPLIT_FIXEDBARSIZE 0x00000010
50
51 // Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are
52 // mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL.
53 // SPLIT_GRADIENTBAR doesn't work with _ATL_NO_MSIMG
54
55
56 template <class T>
57 class CSplitterImpl
58 {
59 public:
60 enum { m_nPanesCount = 2, m_nPropMax = 10000, m_cxyStep = 10 };
61
62 bool m_bVertical;
63 HWND m_hWndPane[m_nPanesCount];
64 RECT m_rcSplitter;
65 int m_xySplitterPos; // splitter bar position
66 int m_xySplitterPosNew; // internal - new position while moving
67 HWND m_hWndFocusSave;
68 int m_nDefActivePane;
69 int m_cxySplitBar; // splitter bar width/height
70 HCURSOR m_hCursor;
71 int m_cxyMin; // minimum pane size
72 int m_cxyBarEdge; // splitter bar edge
73 bool m_bFullDrag;
74 int m_cxyDragOffset; // internal
75 int m_nProportionalPos;
76 bool m_bUpdateProportionalPos;
77 DWORD m_dwExtendedStyle; // splitter specific extended styles
78 int m_nSinglePane; // single pane mode
79 int m_xySplitterDefPos; // default position
80 bool m_bProportionalDefPos; // porportinal def pos
81
82 // Constructor
83 CSplitterImpl(bool bVertical = true) :
84 m_bVertical(bVertical), m_xySplitterPos(-1), m_xySplitterPosNew(-1), m_hWndFocusSave(NULL),
85 m_nDefActivePane(SPLIT_PANE_NONE), m_cxySplitBar(4), m_hCursor(NULL), m_cxyMin(0), m_cxyBarEdge(0),
86 m_bFullDrag(true), m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true),
87 m_dwExtendedStyle(SPLIT_PROPORTIONAL), m_nSinglePane(SPLIT_PANE_NONE),
88 m_xySplitterDefPos(-1), m_bProportionalDefPos(false)
89 {
90 m_hWndPane[SPLIT_PANE_LEFT] = NULL;
91 m_hWndPane[SPLIT_PANE_RIGHT] = NULL;
92
93 ::SetRectEmpty(&m_rcSplitter);
94 }
95
96 // Attributes
97 void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true)
98 {
99 if(lpRect == NULL)
100 {
101 T* pT = static_cast<T*>(this);
102 pT->GetClientRect(&m_rcSplitter);
103 }
104 else
105 {
106 m_rcSplitter = *lpRect;
107 }
108
109 if(IsProportional())
110 UpdateProportionalPos();
111 else if(IsRightAligned())
112 UpdateRightAlignPos();
113
114 if(bUpdate)
115 UpdateSplitterLayout();
116 }
117
118 void GetSplitterRect(LPRECT lpRect) const
119 {
120 ATLASSERT(lpRect != NULL);
121 *lpRect = m_rcSplitter;
122 }
123
124 bool SetSplitterPos(int xyPos = -1, bool bUpdate = true)
125 {
126 if(xyPos == -1) // -1 == default position
127 {
128 if(m_bProportionalDefPos)
129 {
130 ATLASSERT((m_xySplitterDefPos >= 0) && (m_xySplitterDefPos <= m_nPropMax));
131
132 if(m_bVertical)
133 xyPos = ::MulDiv(m_xySplitterDefPos, m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge, m_nPropMax);
134 else
135 xyPos = ::MulDiv(m_xySplitterDefPos, m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge, m_nPropMax);
136 }
137 else if(m_xySplitterDefPos != -1)
138 {
139 xyPos = m_xySplitterDefPos;
140 }
141 else // not set, use middle position
142 {
143 if(m_bVertical)
144 xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2;
145 else
146 xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2;
147 }
148 }
149
150 // Adjust if out of valid range
151 int cxyMax = 0;
152 if(m_bVertical)
153 cxyMax = m_rcSplitter.right - m_rcSplitter.left;
154 else
155 cxyMax = m_rcSplitter.bottom - m_rcSplitter.top;
156
157 if(xyPos < m_cxyMin + m_cxyBarEdge)
158 xyPos = m_cxyMin;
159 else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
160 xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
161
162 // Set new position and update if requested
163 bool bRet = (m_xySplitterPos != xyPos);
164 m_xySplitterPos = xyPos;
165
166 if(m_bUpdateProportionalPos)
167 {
168 if(IsProportional())
169 StoreProportionalPos();
170 else if(IsRightAligned())
171 StoreRightAlignPos();
172 }
173 else
174 {
175 m_bUpdateProportionalPos = true;
176 }
177
178 if(bUpdate && bRet)
179 UpdateSplitterLayout();
180
181 return bRet;
182 }
183
184 int GetSplitterPos() const
185 {
186 return m_xySplitterPos;
187 }
188
189 void SetSplitterPosPct(int nPct, bool bUpdate = true)
190 {
191 ATLASSERT((nPct >= 0) && (nPct <= 100));
192
193 m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100);
194 UpdateProportionalPos();
195
196 if(bUpdate)
197 UpdateSplitterLayout();
198 }
199
200 int GetSplitterPosPct() const
201 {
202 int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
203 return ((cxyTotal > 0) && (m_xySplitterPos >= 0)) ? (::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal) / 100) : -1;
204 }
205
206 bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE)
207 {
208 ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT) || (nPane == SPLIT_PANE_NONE));
209 if(!((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT) || (nPane == SPLIT_PANE_NONE)))
210 return false;
211
212 if(nPane != SPLIT_PANE_NONE)
213 {
214 if(::IsWindowVisible(m_hWndPane[nPane]) == FALSE)
215 ::ShowWindow(m_hWndPane[nPane], SW_SHOW);
216 int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
217 ::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE);
218 if(m_nDefActivePane != nPane)
219 m_nDefActivePane = nPane;
220 }
221 else if(m_nSinglePane != SPLIT_PANE_NONE)
222 {
223 int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
224 ::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW);
225 }
226
227 m_nSinglePane = nPane;
228 UpdateSplitterLayout();
229
230 return true;
231 }
232
233 int GetSinglePaneMode() const
234 {
235 return m_nSinglePane;
236 }
237
238 DWORD GetSplitterExtendedStyle() const
239 {
240 return m_dwExtendedStyle;
241 }
242
243 DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
244 {
245 DWORD dwPrevStyle = m_dwExtendedStyle;
246 if(dwMask == 0)
247 m_dwExtendedStyle = dwExtendedStyle;
248 else
249 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
250
251 #ifdef _DEBUG
252 if(IsProportional() && IsRightAligned())
253 ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n"));
254 #endif // _DEBUG
255
256 return dwPrevStyle;
257 }
258
259 void SetSplitterDefaultPos(int xyPos = -1)
260 {
261 m_xySplitterDefPos = xyPos;
262 m_bProportionalDefPos = false;
263 }
264
265 void SetSplitterDefaultPosPct(int nPct)
266 {
267 ATLASSERT((nPct >= 0) && (nPct <= 100));
268
269 m_xySplitterDefPos = ::MulDiv(nPct, m_nPropMax, 100);
270 m_bProportionalDefPos = true;
271 }
272
273 // Splitter operations
274 void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true)
275 {
276 m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop;
277 m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom;
278 ATLASSERT((m_hWndPane[SPLIT_PANE_LEFT] == NULL) || (m_hWndPane[SPLIT_PANE_RIGHT] == NULL) || (m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]));
279 if(bUpdate)
280 UpdateSplitterLayout();
281 }
282
283 bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true)
284 {
285 ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
286 if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
287 return false;
288
289 m_hWndPane[nPane] = hWnd;
290 ATLASSERT((m_hWndPane[SPLIT_PANE_LEFT] == NULL) || (m_hWndPane[SPLIT_PANE_RIGHT] == NULL) || (m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]));
291 if(bUpdate)
292 UpdateSplitterLayout();
293
294 return true;
295 }
296
297 HWND GetSplitterPane(int nPane) const
298 {
299 ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
300 if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
301 return NULL;
302
303 return m_hWndPane[nPane];
304 }
305
306 bool SetActivePane(int nPane)
307 {
308 ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
309 if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
310 return false;
311 if((m_nSinglePane != SPLIT_PANE_NONE) && (nPane != m_nSinglePane))
312 return false;
313
314 ::SetFocus(m_hWndPane[nPane]);
315 m_nDefActivePane = nPane;
316
317 return true;
318 }
319
320 int GetActivePane() const
321 {
322 int nRet = SPLIT_PANE_NONE;
323 HWND hWndFocus = ::GetFocus();
324 if(hWndFocus != NULL)
325 {
326 for(int nPane = 0; nPane < m_nPanesCount; nPane++)
327 {
328 if((hWndFocus == m_hWndPane[nPane]) || (::IsChild(m_hWndPane[nPane], hWndFocus) != FALSE))
329 {
330 nRet = nPane;
331 break;
332 }
333 }
334 }
335
336 return nRet;
337 }
338
339 bool ActivateNextPane(bool bNext = true)
340 {
341 int nPane = m_nSinglePane;
342 if(nPane == SPLIT_PANE_NONE)
343 {
344 switch(GetActivePane())
345 {
346 case SPLIT_PANE_LEFT:
347 nPane = SPLIT_PANE_RIGHT;
348 break;
349 case SPLIT_PANE_RIGHT:
350 nPane = SPLIT_PANE_LEFT;
351 break;
352 default:
353 nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT;
354 break;
355 }
356 }
357
358 return SetActivePane(nPane);
359 }
360
361 bool SetDefaultActivePane(int nPane)
362 {
363 ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
364 if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
365 return false;
366
367 m_nDefActivePane = nPane;
368
369 return true;
370 }
371
372 bool SetDefaultActivePane(HWND hWnd)
373 {
374 for(int nPane = 0; nPane < m_nPanesCount; nPane++)
375 {
376 if(hWnd == m_hWndPane[nPane])
377 {
378 m_nDefActivePane = nPane;
379 return true;
380 }
381 }
382
383 return false; // not found
384 }
385
386 int GetDefaultActivePane() const
387 {
388 return m_nDefActivePane;
389 }
390
391 void DrawSplitter(CDCHandle dc)
392 {
393 ATLASSERT(dc.m_hDC != NULL);
394 if((m_nSinglePane == SPLIT_PANE_NONE) && (m_xySplitterPos == -1))
395 return;
396
397 T* pT = static_cast<T*>(this);
398 if(m_nSinglePane == SPLIT_PANE_NONE)
399 {
400 pT->DrawSplitterBar(dc);
401
402 for(int nPane = 0; nPane < m_nPanesCount; nPane++)
403 {
404 if(m_hWndPane[nPane] == NULL)
405 pT->DrawSplitterPane(dc, nPane);
406 }
407 }
408 else
409 {
410 if(m_hWndPane[m_nSinglePane] == NULL)
411 pT->DrawSplitterPane(dc, m_nSinglePane);
412 }
413 }
414
415 // call to initiate moving splitter bar with keyboard
416 void MoveSplitterBar()
417 {
418 T* pT = static_cast<T*>(this);
419
420 int x = 0;
421 int y = 0;
422 if(m_bVertical)
423 {
424 x = m_xySplitterPos + (m_cxySplitBar / 2) + m_cxyBarEdge;
425 y = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2;
426 }
427 else
428 {
429 x = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2;
430 y = m_xySplitterPos + (m_cxySplitBar / 2) + m_cxyBarEdge;
431 }
432
433 POINT pt = { x, y };
434 pT->ClientToScreen(&pt);
435 ::SetCursorPos(pt.x, pt.y);
436
437 m_xySplitterPosNew = m_xySplitterPos;
438 pT->SetCapture();
439 m_hWndFocusSave = pT->SetFocus();
440 ::SetCursor(m_hCursor);
441 if(!m_bFullDrag)
442 DrawGhostBar();
443 if(m_bVertical)
444 m_cxyDragOffset = x - m_rcSplitter.left - m_xySplitterPos;
445 else
446 m_cxyDragOffset = y - m_rcSplitter.top - m_xySplitterPos;
447 }
448
449 void SetOrientation(bool bVertical, bool bUpdate = true)
450 {
451 if(m_bVertical != bVertical)
452 {
453 m_bVertical = bVertical;
454
455 m_hCursor = ::LoadCursor(NULL, m_bVertical ? IDC_SIZEWE : IDC_SIZENS);
456
457 T* pT = static_cast<T*>(this);
458 pT->GetSystemSettings(false);
459
460 if(m_bVertical)
461 m_xySplitterPos = ::MulDiv(m_xySplitterPos, m_rcSplitter.right - m_rcSplitter.left, m_rcSplitter.bottom - m_rcSplitter.top);
462 else
463 m_xySplitterPos = ::MulDiv(m_xySplitterPos, m_rcSplitter.bottom - m_rcSplitter.top, m_rcSplitter.right - m_rcSplitter.left);
464 }
465
466 if(bUpdate)
467 UpdateSplitterLayout();
468 }
469
470 // Overrideables
471 void DrawSplitterBar(CDCHandle dc)
472 {
473 RECT rect = { 0 };
474 if(GetSplitterBarRect(&rect))
475 {
476 dc.FillRect(&rect, COLOR_3DFACE);
477
478 #if (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420)
479 if((m_dwExtendedStyle & SPLIT_GRADIENTBAR) != 0)
480 {
481 RECT rect2 = rect;
482 if(m_bVertical)
483 rect2.left = (rect.left + rect.right) / 2 - 1;
484 else
485 rect2.top = (rect.top + rect.bottom) / 2 - 1;
486
487 dc.GradientFillRect(rect2, ::GetSysColor(COLOR_3DFACE), ::GetSysColor(COLOR_3DSHADOW), m_bVertical);
488 }
489 #endif // (!defined(_WIN32_WCE) && !defined(_ATL_NO_MSIMG)) || (_WIN32_WCE >= 420)
490
491 // draw 3D edge if needed
492 T* pT = static_cast<T*>(this);
493 if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)
494 dc.DrawEdge(&rect, EDGE_RAISED, m_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM));
495 }
496 }
497
498 // called only if pane is empty
499 void DrawSplitterPane(CDCHandle dc, int nPane)
500 {
501 RECT rect = { 0 };
502 if(GetSplitterPaneRect(nPane, &rect))
503 {
504 T* pT = static_cast<T*>(this);
505 if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0)
506 dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
507 dc.FillRect(&rect, COLOR_APPWORKSPACE);
508 }
509 }
510
511 // Message map and handlers
512 BEGIN_MSG_MAP(CSplitterImpl)
513 MESSAGE_HANDLER(WM_CREATE, OnCreate)
514 MESSAGE_HANDLER(WM_PAINT, OnPaint)
515 #ifndef _WIN32_WCE
516 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
517 #endif // !_WIN32_WCE
518 if(IsInteractive())
519 {
520 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
521 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
522 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
523 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
524 MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick)
525 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
526 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
527 }
528 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
529 #ifndef _WIN32_WCE
530 MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
531 #endif // !_WIN32_WCE
532 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
533 END_MSG_MAP()
534
535 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
536 {
537 T* pT = static_cast<T*>(this);
538 pT->Init();
539
540 bHandled = FALSE;
541 return 1;
542 }
543
544 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
545 {
546 T* pT = static_cast<T*>(this);
547
548 // try setting position if not set
549 if((m_nSinglePane == SPLIT_PANE_NONE) && (m_xySplitterPos == -1))
550 pT->SetSplitterPos();
551
552 // do painting
553 if(wParam != NULL)
554 {
555 pT->DrawSplitter((HDC)wParam);
556 }
557 else
558 {
559 CPaintDC dc(pT->m_hWnd);
560 pT->DrawSplitter(dc.m_hDC);
561 }
562
563 return 0;
564 }
565
566 LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
567 {
568 T* pT = static_cast<T*>(this);
569 if(((HWND)wParam == pT->m_hWnd) && (LOWORD(lParam) == HTCLIENT))
570 {
571 DWORD dwPos = ::GetMessagePos();
572 POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
573 pT->ScreenToClient(&ptPos);
574 if(IsOverSplitterBar(ptPos.x, ptPos.y))
575 return 1;
576 }
577
578 bHandled = FALSE;
579 return 0;
580 }
581
582 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
583 {
584 T* pT = static_cast<T*>(this);
585 int xPos = GET_X_LPARAM(lParam);
586 int yPos = GET_Y_LPARAM(lParam);
587 if(::GetCapture() == pT->m_hWnd)
588 {
589 int xyNewSplitPos = 0;
590 if(m_bVertical)
591 xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset;
592 else
593 xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset;
594
595 if(xyNewSplitPos == -1) // avoid -1, that means default position
596 xyNewSplitPos = -2;
597
598 if(m_xySplitterPos != xyNewSplitPos)
599 {
600 if(m_bFullDrag)
601 {
602 if(pT->SetSplitterPos(xyNewSplitPos, true))
603 pT->UpdateWindow();
604 }
605 else
606 {
607 DrawGhostBar();
608 pT->SetSplitterPos(xyNewSplitPos, false);
609 DrawGhostBar();
610 }
611 }
612 }
613 else // not dragging, just set cursor
614 {
615 if(IsOverSplitterBar(xPos, yPos))
616 ::SetCursor(m_hCursor);
617 bHandled = FALSE;
618 }
619
620 return 0;
621 }
622
623 LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
624 {
625 T* pT = static_cast<T*>(this);
626 int xPos = GET_X_LPARAM(lParam);
627 int yPos = GET_Y_LPARAM(lParam);
628 if((::GetCapture() != pT->m_hWnd) && IsOverSplitterBar(xPos, yPos))
629 {
630 m_xySplitterPosNew = m_xySplitterPos;
631 pT->SetCapture();
632 m_hWndFocusSave = pT->SetFocus();
633 ::SetCursor(m_hCursor);
634 if(!m_bFullDrag)
635 DrawGhostBar();
636 if(m_bVertical)
637 m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos;
638 else
639 m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos;
640 }
641 else if((::GetCapture() == pT->m_hWnd) && !IsOverSplitterBar(xPos, yPos))
642 {
643 ::ReleaseCapture();
644 }
645
646 bHandled = FALSE;
647 return 1;
648 }
649
650 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
651 {
652 T* pT = static_cast<T*>(this);
653 if(::GetCapture() == pT->m_hWnd)
654 {
655 m_xySplitterPosNew = m_xySplitterPos;
656 ::ReleaseCapture();
657 }
658
659 bHandled = FALSE;
660 return 1;
661 }
662
663 LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
664 {
665 T* pT = static_cast<T*>(this);
666 pT->SetSplitterPos(); // default
667
668 return 0;
669 }
670
671 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
672 {
673 if(!m_bFullDrag)
674 DrawGhostBar();
675
676 if((m_xySplitterPosNew != -1) && (!m_bFullDrag || (m_xySplitterPos != m_xySplitterPosNew)))
677 {
678 m_xySplitterPos = m_xySplitterPosNew;
679 m_xySplitterPosNew = -1;
680 UpdateSplitterLayout();
681 T* pT = static_cast<T*>(this);
682 pT->UpdateWindow();
683 }
684
685 if(m_hWndFocusSave != NULL)
686 ::SetFocus(m_hWndFocusSave);
687
688 return 0;
689 }
690
691 LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
692 {
693 T* pT = static_cast<T*>(this);
694 if(::GetCapture() == pT->m_hWnd)
695 {
696 switch(wParam)
697 {
698 case VK_RETURN:
699 m_xySplitterPosNew = m_xySplitterPos;
700 case VK_ESCAPE:
701 ::ReleaseCapture();
702 break;
703 case VK_LEFT:
704 case VK_RIGHT:
705 if(m_bVertical)
706 {
707 POINT pt = { 0, 0 };
708 ::GetCursorPos(&pt);
709 int xyPos = m_xySplitterPos + ((wParam == VK_LEFT) ? -pT->m_cxyStep : pT->m_cxyStep);
710 int cxyMax = m_rcSplitter.right - m_rcSplitter.left;
711 if(xyPos < (m_cxyMin + m_cxyBarEdge))
712 xyPos = m_cxyMin;
713 else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
714 xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
715 pt.x += xyPos - m_xySplitterPos;
716 ::SetCursorPos(pt.x, pt.y);
717 }
718 break;
719 case VK_UP:
720 case VK_DOWN:
721 if(!m_bVertical)
722 {
723 POINT pt = { 0, 0 };
724 ::GetCursorPos(&pt);
725 int xyPos = m_xySplitterPos + ((wParam == VK_UP) ? -pT->m_cxyStep : pT->m_cxyStep);
726 int cxyMax = m_rcSplitter.bottom - m_rcSplitter.top;
727 if(xyPos < (m_cxyMin + m_cxyBarEdge))
728 xyPos = m_cxyMin;
729 else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
730 xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
731 pt.y += xyPos - m_xySplitterPos;
732 ::SetCursorPos(pt.x, pt.y);
733 }
734 break;
735 default:
736 break;
737 }
738 }
739 else
740 {
741 bHandled = FALSE;
742 }
743
744 return 0;
745 }
746
747 LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled)
748 {
749 T* pT = static_cast<T*>(this);
750 if(::GetCapture() != pT->m_hWnd)
751 {
752 if(m_nSinglePane == SPLIT_PANE_NONE)
753 {
754 if((m_nDefActivePane == SPLIT_PANE_LEFT) || (m_nDefActivePane == SPLIT_PANE_RIGHT))
755 ::SetFocus(m_hWndPane[m_nDefActivePane]);
756 }
757 else
758 {
759 ::SetFocus(m_hWndPane[m_nSinglePane]);
760 }
761 }
762
763 bHandled = FALSE;
764 return 1;
765 }
766
767 #ifndef _WIN32_WCE
768 LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
769 {
770 T* pT = static_cast<T*>(this);
771 LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
772 if((lRet == MA_ACTIVATE) || (lRet == MA_ACTIVATEANDEAT))
773 {
774 DWORD dwPos = ::GetMessagePos();
775 POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
776 pT->ScreenToClient(&pt);
777 RECT rcPane = { 0 };
778 for(int nPane = 0; nPane < m_nPanesCount; nPane++)
779 {
780 if(GetSplitterPaneRect(nPane, &rcPane) && (::PtInRect(&rcPane, pt) != FALSE))
781 {
782 m_nDefActivePane = nPane;
783 break;
784 }
785 }
786 }
787
788 return lRet;
789 }
790 #endif // !_WIN32_WCE
791
792 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
793 {
794 T* pT = static_cast<T*>(this);
795 pT->GetSystemSettings(true);
796
797 return 0;
798 }
799
800 // Implementation - internal helpers
801 void Init()
802 {
803 m_hCursor = ::LoadCursor(NULL, m_bVertical ? IDC_SIZEWE : IDC_SIZENS);
804
805 T* pT = static_cast<T*>(this);
806 pT->GetSystemSettings(false);
807 }
808
809 void UpdateSplitterLayout()
810 {
811 if((m_nSinglePane == SPLIT_PANE_NONE) && (m_xySplitterPos == -1))
812 return;
813
814 T* pT = static_cast<T*>(this);
815 RECT rect = { 0 };
816 if(m_nSinglePane == SPLIT_PANE_NONE)
817 {
818 if(GetSplitterBarRect(&rect))
819 pT->InvalidateRect(&rect);
820
821 for(int nPane = 0; nPane < m_nPanesCount; nPane++)
822 {
823 if(GetSplitterPaneRect(nPane, &rect))
824 {
825 if(m_hWndPane[nPane] != NULL)
826 ::SetWindowPos(m_hWndPane[nPane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
827 else
828 pT->InvalidateRect(&rect);
829 }
830 }
831 }
832 else
833 {
834 if(GetSplitterPaneRect(m_nSinglePane, &rect))
835 {
836 if(m_hWndPane[m_nSinglePane] != NULL)
837 ::SetWindowPos(m_hWndPane[m_nSinglePane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
838 else
839 pT->InvalidateRect(&rect);
840 }
841 }
842 }
843
844 bool GetSplitterBarRect(LPRECT lpRect) const
845 {
846 ATLASSERT(lpRect != NULL);
847 if((m_nSinglePane != SPLIT_PANE_NONE) || (m_xySplitterPos == -1))
848 return false;
849
850 if(m_bVertical)
851 {
852 lpRect->left = m_rcSplitter.left + m_xySplitterPos;
853 lpRect->top = m_rcSplitter.top;
854 lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
855 lpRect->bottom = m_rcSplitter.bottom;
856 }
857 else
858 {
859 lpRect->left = m_rcSplitter.left;
860 lpRect->top = m_rcSplitter.top + m_xySplitterPos;
861 lpRect->right = m_rcSplitter.right;
862 lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
863 }
864
865 return true;
866 }
867
868 bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const
869 {
870 ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
871 ATLASSERT(lpRect != NULL);
872 bool bRet = true;
873 if(m_nSinglePane != SPLIT_PANE_NONE)
874 {
875 if(nPane == m_nSinglePane)
876 *lpRect = m_rcSplitter;
877 else
878 bRet = false;
879 }
880 else if(nPane == SPLIT_PANE_LEFT)
881 {
882 if(m_bVertical)
883 {
884 lpRect->left = m_rcSplitter.left;
885 lpRect->top = m_rcSplitter.top;
886 lpRect->right = m_rcSplitter.left + m_xySplitterPos;
887 lpRect->bottom = m_rcSplitter.bottom;
888 }
889 else
890 {
891 lpRect->left = m_rcSplitter.left;
892 lpRect->top = m_rcSplitter.top;
893 lpRect->right = m_rcSplitter.right;
894 lpRect->bottom = m_rcSplitter.top + m_xySplitterPos;
895 }
896 }
897 else if(nPane == SPLIT_PANE_RIGHT)
898 {
899 if(m_bVertical)
900 {
901 lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
902 lpRect->top = m_rcSplitter.top;
903 lpRect->right = m_rcSplitter.right;
904 lpRect->bottom = m_rcSplitter.bottom;
905 }
906 else
907 {
908 lpRect->left = m_rcSplitter.left;
909 lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
910 lpRect->right = m_rcSplitter.right;
911 lpRect->bottom = m_rcSplitter.bottom;
912 }
913 }
914 else
915 {
916 bRet = false;
917 }
918
919 return bRet;
920 }
921
922 bool IsOverSplitterRect(int x, int y) const
923 {
924 // -1 == don't check
925 return ((x == -1 || (x >= m_rcSplitter.left && x <= m_rcSplitter.right)) &&
926 (y == -1 || (y >= m_rcSplitter.top && y <= m_rcSplitter.bottom)));
927 }
928
929 bool IsOverSplitterBar(int x, int y) const
930 {
931 if(m_nSinglePane != SPLIT_PANE_NONE)
932 return false;
933 if((m_xySplitterPos == -1) || !IsOverSplitterRect(x, y))
934 return false;
935 int xy = m_bVertical ? x : y;
936 int xyOff = m_bVertical ? m_rcSplitter.left : m_rcSplitter.top;
937
938 return ((xy >= (xyOff + m_xySplitterPos)) && (xy < xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge));
939 }
940
941 void DrawGhostBar()
942 {
943 RECT rect = { 0 };
944 if(GetSplitterBarRect(&rect))
945 {
946 // convert client to window coordinates
947 T* pT = static_cast<T*>(this);
948 RECT rcWnd = { 0 };
949 pT->GetWindowRect(&rcWnd);
950 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcWnd, 2);
951 ::OffsetRect(&rect, -rcWnd.left, -rcWnd.top);
952
953 // invert the brush pattern (looks just like frame window sizing)
954 CWindowDC dc(pT->m_hWnd);
955 CBrush brush = CDCHandle::GetHalftoneBrush();
956 if(brush.m_hBrush != NULL)
957 {
958 CBrushHandle brushOld = dc.SelectBrush(brush);
959 dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
960 dc.SelectBrush(brushOld);
961 }
962 }
963 }
964
965 void GetSystemSettings(bool bUpdate)
966 {
967 if((m_dwExtendedStyle & SPLIT_FIXEDBARSIZE) == 0)
968 {
969 #ifndef _WIN32_WCE
970 m_cxySplitBar = ::GetSystemMetrics(m_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME);
971 #else // CE specific
972 m_cxySplitBar = 2 * ::GetSystemMetrics(m_bVertical ? SM_CXEDGE : SM_CYEDGE);
973 #endif // _WIN32_WCE
974 }
975
976 T* pT = static_cast<T*>(this);
977 if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)
978 {
979 m_cxyBarEdge = 2 * ::GetSystemMetrics(m_bVertical ? SM_CXEDGE : SM_CYEDGE);
980 m_cxyMin = 0;
981 }
982 else
983 {
984 m_cxyBarEdge = 0;
985 m_cxyMin = 2 * ::GetSystemMetrics(m_bVertical ? SM_CXEDGE : SM_CYEDGE);
986 }
987
988 #ifndef _WIN32_WCE
989 ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0);
990 #endif // !_WIN32_WCE
991
992 if(bUpdate)
993 UpdateSplitterLayout();
994 }
995
996 bool IsProportional() const
997 {
998 return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0);
999 }
1000
1001 void StoreProportionalPos()
1002 {
1003 int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
1004 if(cxyTotal > 0)
1005 m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal);
1006 else
1007 m_nProportionalPos = 0;
1008 ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreProportionalPos - %i\n"), m_nProportionalPos);
1009 }
1010
1011 void UpdateProportionalPos()
1012 {
1013 int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
1014 if(cxyTotal > 0)
1015 {
1016 int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax);
1017 m_bUpdateProportionalPos = false;
1018 T* pT = static_cast<T*>(this);
1019 pT->SetSplitterPos(xyNewPos, false);
1020 }
1021 }
1022
1023 bool IsRightAligned() const
1024 {
1025 return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0);
1026 }
1027
1028 void StoreRightAlignPos()
1029 {
1030 int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
1031 if(cxyTotal > 0)
1032 m_nProportionalPos = cxyTotal - m_xySplitterPos;
1033 else
1034 m_nProportionalPos = 0;
1035 ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreRightAlignPos - %i\n"), m_nProportionalPos);
1036 }
1037
1038 void UpdateRightAlignPos()
1039 {
1040 int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
1041 if(cxyTotal > 0)
1042 {
1043 m_bUpdateProportionalPos = false;
1044 T* pT = static_cast<T*>(this);
1045 pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false);
1046 }
1047 }
1048
1049 bool IsInteractive() const
1050 {
1051 return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0);
1052 }
1053 };
1054
1055
1056 ///////////////////////////////////////////////////////////////////////////////
1057 // CSplitterWindowImpl - Implements a splitter window
1058
1059 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1060 class ATL_NO_VTABLE CSplitterWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T >
1061 {
1062 public:
1063 DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW)
1064
1065 CSplitterWindowImpl(bool bVertical = true) : CSplitterImpl< T >(bVertical)
1066 { }
1067
1068 BOOL SubclassWindow(HWND hWnd)
1069 {
1070 #if (_MSC_VER >= 1300)
1071 BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
1072 #else // !(_MSC_VER >= 1300)
1073 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
1074 BOOL bRet = _baseClass::SubclassWindow(hWnd);
1075 #endif // !(_MSC_VER >= 1300)
1076 if(bRet != FALSE)
1077 {
1078 T* pT = static_cast<T*>(this);
1079 pT->Init();
1080
1081 SetSplitterRect();
1082 }
1083
1084 return bRet;
1085 }
1086
1087 BEGIN_MSG_MAP(CSplitterWindowImpl)
1088 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
1089 MESSAGE_HANDLER(WM_SIZE, OnSize)
1090 CHAIN_MSG_MAP(CSplitterImpl< T >)
1091 FORWARD_NOTIFICATIONS()
1092 END_MSG_MAP()
1093
1094 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1095 {
1096 // handled, no background painting needed
1097 return 1;
1098 }
1099
1100 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1101 {
1102 if(wParam != SIZE_MINIMIZED)
1103 SetSplitterRect();
1104
1105 bHandled = FALSE;
1106 return 1;
1107 }
1108 };
1109
1110
1111 ///////////////////////////////////////////////////////////////////////////////
1112 // CSplitterWindow/CHorSplitterWindow - Implements splitter windows to be used as is
1113
1114 template <bool t_bVertical = true>
1115 class CSplitterWindowT : public CSplitterWindowImpl<CSplitterWindowT<t_bVertical> >
1116 {
1117 public:
1118 DECLARE_WND_CLASS_EX(_T("WTL_SplitterWindow"), CS_DBLCLKS, COLOR_WINDOW)
1119
1120 CSplitterWindowT() : CSplitterWindowImpl<CSplitterWindowT<t_bVertical> >(t_bVertical)
1121 { }
1122 };
1123
1124 typedef CSplitterWindowT<true> CSplitterWindow;
1125 typedef CSplitterWindowT<false> CHorSplitterWindow;
1126
1127 }; // namespace WTL
1128
1129 #endif // __ATLSPLIT_H__
+0
-1257
src/third_party/wtl/Include/atltheme.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLTHEME_H__
9 #define __ATLTHEME_H__
10
11 #pragma once
12
13 #ifdef _WIN32_WCE
14 #error atltheme.h is not supported on Windows CE
15 #endif
16
17 #ifndef __ATLAPP_H__
18 #error atltheme.h requires atlapp.h to be included first
19 #endif
20
21 #ifndef __ATLWIN_H__
22 #error atltheme.h requires atlwin.h to be included first
23 #endif
24
25 #if (_WIN32_WINNT < 0x0501)
26 #error atltheme.h requires _WIN32_WINNT >= 0x0501
27 #endif // (_WIN32_WINNT < 0x0501)
28
29 #if defined(_WTL_USE_VSSYM32) || (defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN))
30 #include <vssym32.h>
31 #else
32 #ifndef TMSCHEMA_H
33 #include <tmschema.h>
34 #endif
35 #endif
36
37 #include <uxtheme.h>
38 #pragma comment(lib, "uxtheme.lib")
39
40 // Note: To create an application that also runs on older versions of Windows,
41 // use delay load of uxtheme.dll and ensure that no calls to the Theme API are
42 // made if theming is not supported. It is enough to check if m_hTheme is NULL.
43 // Example:
44 // if(m_hTheme != NULL)
45 // {
46 // DrawThemeBackground(dc, BP_PUSHBUTTON, PBS_NORMAL, &rect, NULL);
47 // DrawThemeText(dc, BP_PUSHBUTTON, PBS_NORMAL, L"Button", -1, DT_SINGLELINE | DT_CENTER | DT_VCENTER, 0, &rect);
48 // }
49 // else
50 // {
51 // dc.DrawFrameControl(&rect, DFC_BUTTON, DFCS_BUTTONPUSH);
52 // dc.DrawText(_T("Button"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
53 // }
54 //
55 // Delay load is NOT AUTOMATIC for VC++ 7, you have to link to delayimp.lib,
56 // and add uxtheme.dll in the Linker.Input.Delay Loaded DLLs section of the
57 // project properties.
58 #if (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
59 #pragma comment(lib, "delayimp.lib")
60 #pragma comment(linker, "/delayload:uxtheme.dll")
61 #endif // (_MSC_VER < 1300) && !defined(_WTL_NO_THEME_DELAYLOAD)
62
63 // Hack: Signatures in uxtheme.h changed - the only way to check which variant of uxtheme.h
64 // is included is to check for presence of new defines MAX_THEMECOLOR and MAX_THEMESIZE
65 // Note: In WinSDK 7.0 (and higher) they are defined with #if (_WIN32_WINNT >= 0x0600),
66 // so you have to compile with _WTL_NEW_UXTHEME defined for _WIN32_WINNT < 0x0600
67 #ifndef _WTL_NEW_UXTHEME
68 #if defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE)
69 #define _WTL_NEW_UXTHEME
70 #endif // defined(MAX_THEMECOLOR) && defined(MAX_THEMESIZE)
71 #endif // _WTL_NEW_UXTHEME
72
73
74 ///////////////////////////////////////////////////////////////////////////////
75 // Classes in this file:
76 //
77 // CTheme
78 // CThemeImpl<T, TBase>
79 //
80 // CBufferedPaint
81 // CBufferedPaintImpl<T>
82 // CBufferedPaintWindowImpl<T, TBase, TWinTraits>
83 // CBufferedAnimation
84 // CBufferedAnimationImpl<T, TState>
85 // CBufferedAnimationWindowImpl<T, TState, TBase, TWinTraits>
86 //
87 // Global functions:
88 // AtlDrawThemeClientEdge()
89
90
91 namespace WTL
92 {
93
94 ///////////////////////////////////////////////////////////////////////////////
95 // CTheme - wrapper for theme handle
96
97 class CTheme
98 {
99 public:
100 // Data members
101 HTHEME m_hTheme;
102 static int m_nIsThemingSupported;
103
104 // Constructor
105 CTheme(HTHEME hTheme = NULL) : m_hTheme(hTheme)
106 {
107 IsThemingSupported();
108 }
109
110 // Operators and helpers
111 bool IsThemeNull() const
112 {
113 return (m_hTheme == NULL);
114 }
115
116 CTheme& operator =(HTHEME hTheme)
117 {
118 m_hTheme = hTheme;
119 return *this;
120 }
121
122 operator HTHEME() const
123 {
124 return m_hTheme;
125 }
126
127 void Attach(HTHEME hTheme)
128 {
129 m_hTheme = hTheme;
130 }
131
132 HTHEME Detach()
133 {
134 HTHEME hTheme = m_hTheme;
135 m_hTheme = NULL;
136 return hTheme;
137 }
138
139 // Theme support helper
140 static bool IsThemingSupported()
141 {
142 if(m_nIsThemingSupported == -1)
143 {
144 CStaticDataInitCriticalSectionLock lock;
145 if(FAILED(lock.Lock()))
146 {
147 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CTheme::IsThemingSupported.\n"));
148 ATLASSERT(FALSE);
149 return false;
150 }
151
152 if(m_nIsThemingSupported == -1)
153 {
154 HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll"));
155 m_nIsThemingSupported = (hThemeDLL != NULL) ? 1 : 0;
156 if(hThemeDLL != NULL)
157 ::FreeLibrary(hThemeDLL);
158 }
159
160 lock.Unlock();
161 }
162
163 ATLASSERT(m_nIsThemingSupported != -1);
164 return (m_nIsThemingSupported == 1);
165 }
166
167 // Operations and theme properties
168 HTHEME OpenThemeData(HWND hWnd, LPCWSTR pszClassList)
169 {
170 if(!IsThemingSupported())
171 return NULL;
172
173 ATLASSERT(m_hTheme == NULL);
174 m_hTheme = ::OpenThemeData(hWnd, pszClassList);
175 return m_hTheme;
176 }
177
178 HRESULT CloseThemeData()
179 {
180 HRESULT hRet = S_FALSE;
181 if(m_hTheme != NULL)
182 {
183 hRet = ::CloseThemeData(m_hTheme);
184 if(SUCCEEDED(hRet))
185 m_hTheme = NULL;
186 }
187 return hRet;
188 }
189
190 HRESULT DrawThemeBackground(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, LPCRECT pClipRect = NULL)
191 {
192 ATLASSERT(m_hTheme != NULL);
193 return ::DrawThemeBackground(m_hTheme, hDC, nPartID, nStateID, pRect, pClipRect);
194 }
195
196 // Missing in original uxtheme.h
197 #ifdef DTBG_CLIPRECT
198 HRESULT DrawThemeBackgroundEx(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, const DTBGOPTS* pOptions = NULL)
199 {
200 ATLASSERT(m_hTheme != NULL);
201 return ::DrawThemeBackgroundEx(m_hTheme, hDC, nPartID, nStateID, pRect, pOptions);
202 }
203 #endif // DTBG_CLIPRECT
204
205 HRESULT DrawThemeText(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
206 {
207 ATLASSERT(m_hTheme != NULL);
208 return ::DrawThemeText(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, dwTextFlags2, pRect);
209 }
210
211 HRESULT GetThemeBackgroundContentRect(HDC hDC, int nPartID, int nStateID, LPCRECT pBoundingRect, LPRECT pContentRect) const
212 {
213 ATLASSERT(m_hTheme != NULL);
214 return ::GetThemeBackgroundContentRect(m_hTheme, hDC, nPartID, nStateID, pBoundingRect, pContentRect);
215 }
216
217 HRESULT GetThemeBackgroundExtent(HDC hDC, int nPartID, int nStateID, LPCRECT pContentRect, LPRECT pExtentRect) const
218 {
219 ATLASSERT(m_hTheme != NULL);
220 return ::GetThemeBackgroundExtent(m_hTheme, hDC, nPartID, nStateID, pContentRect, pExtentRect);
221 }
222
223 HRESULT GetThemePartSize(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, enum THEMESIZE eSize, LPSIZE pSize) const
224 {
225 ATLASSERT(m_hTheme != NULL);
226 #ifdef _WTL_NEW_UXTHEME
227 return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, pRect, eSize, pSize);
228 #else // !_WTL_NEW_UXTHEME
229 // Note: The cast to LPRECT is because uxtheme.h incorrectly uses it instead of LPCRECT
230 return ::GetThemePartSize(m_hTheme, hDC, nPartID, nStateID, (LPRECT)pRect, eSize, pSize);
231 #endif // !_WTL_NEW_UXTHEME
232 }
233
234 HRESULT GetThemeTextExtent(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int nCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) const
235 {
236 ATLASSERT(m_hTheme != NULL);
237 return ::GetThemeTextExtent(m_hTheme, hDC, nPartID, nStateID, pszText, nCharCount, dwTextFlags, pBoundingRect, pExtentRect);
238 }
239
240 HRESULT GetThemeTextMetrics(HDC hDC, int nPartID, int nStateID, PTEXTMETRICW pTextMetric) const
241 {
242 ATLASSERT(m_hTheme != NULL);
243 #ifdef _WTL_NEW_UXTHEME
244 return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, pTextMetric);
245 #else // !_WTL_NEW_UXTHEME
246 // Note: The cast to PTEXTMETRIC is because uxtheme.h incorrectly uses it instead of PTEXTMETRICW
247 return ::GetThemeTextMetrics(m_hTheme, hDC, nPartID, nStateID, (PTEXTMETRIC)pTextMetric);
248 #endif // !_WTL_NEW_UXTHEME
249 }
250
251 HRESULT GetThemeBackgroundRegion(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HRGN* pRegion) const
252 {
253 ATLASSERT(m_hTheme != NULL);
254 return ::GetThemeBackgroundRegion(m_hTheme, hDC, nPartID, nStateID, pRect, pRegion);
255 }
256
257 HRESULT HitTestThemeBackground(HDC hDC, int nPartID, int nStateID, DWORD dwOptions, LPCRECT pRect, HRGN hrgn, POINT ptTest, WORD* pwHitTestCode) const
258 {
259 ATLASSERT(m_hTheme != NULL);
260 return ::HitTestThemeBackground(m_hTheme, hDC, nPartID, nStateID, dwOptions, pRect, hrgn, ptTest, pwHitTestCode);
261 }
262
263 HRESULT DrawThemeEdge(HDC hDC, int nPartID, int nStateID, LPCRECT pDestRect, UINT uEdge, UINT uFlags, LPRECT pContentRect = NULL)
264 {
265 ATLASSERT(m_hTheme != NULL);
266 return ::DrawThemeEdge(m_hTheme, hDC, nPartID, nStateID, pDestRect, uEdge, uFlags, pContentRect);
267 }
268
269 HRESULT DrawThemeIcon(HDC hDC, int nPartID, int nStateID, LPCRECT pRect, HIMAGELIST himl, int nImageIndex)
270 {
271 ATLASSERT(m_hTheme != NULL);
272 return ::DrawThemeIcon(m_hTheme, hDC, nPartID, nStateID, pRect, himl, nImageIndex);
273 }
274
275 BOOL IsThemePartDefined(int nPartID, int nStateID) const
276 {
277 ATLASSERT(m_hTheme != NULL);
278 return ::IsThemePartDefined(m_hTheme, nPartID, nStateID);
279 }
280
281 BOOL IsThemeBackgroundPartiallyTransparent(int nPartID, int nStateID) const
282 {
283 ATLASSERT(m_hTheme != NULL);
284 return ::IsThemeBackgroundPartiallyTransparent(m_hTheme, nPartID, nStateID);
285 }
286
287 HRESULT GetThemeColor(int nPartID, int nStateID, int nPropID, COLORREF* pColor) const
288 {
289 ATLASSERT(m_hTheme != NULL);
290 return ::GetThemeColor(m_hTheme, nPartID, nStateID, nPropID, pColor);
291 }
292
293 HRESULT GetThemeMetric(HDC hDC, int nPartID, int nStateID, int nPropID, int* pnVal) const
294 {
295 ATLASSERT(m_hTheme != NULL);
296 return ::GetThemeMetric(m_hTheme, hDC, nPartID, nStateID, nPropID, pnVal);
297 }
298
299 HRESULT GetThemeString(int nPartID, int nStateID, int nPropID, LPWSTR pszBuff, int cchMaxBuffChars) const
300 {
301 ATLASSERT(m_hTheme != NULL);
302 return ::GetThemeString(m_hTheme, nPartID, nStateID, nPropID, pszBuff, cchMaxBuffChars);
303 }
304
305 HRESULT GetThemeBool(int nPartID, int nStateID, int nPropID, BOOL* pfVal) const
306 {
307 ATLASSERT(m_hTheme != NULL);
308 return ::GetThemeBool(m_hTheme, nPartID, nStateID, nPropID, pfVal);
309 }
310
311 HRESULT GetThemeInt(int nPartID, int nStateID, int nPropID, int* pnVal) const
312 {
313 ATLASSERT(m_hTheme != NULL);
314 return ::GetThemeInt(m_hTheme, nPartID, nStateID, nPropID, pnVal);
315 }
316
317 HRESULT GetThemeEnumValue(int nPartID, int nStateID, int nPropID, int* pnVal) const
318 {
319 ATLASSERT(m_hTheme != NULL);
320 return ::GetThemeEnumValue(m_hTheme, nPartID, nStateID, nPropID, pnVal);
321 }
322
323 HRESULT GetThemePosition(int nPartID, int nStateID, int nPropID, LPPOINT pPoint) const
324 {
325 ATLASSERT(m_hTheme != NULL);
326 return ::GetThemePosition(m_hTheme, nPartID, nStateID, nPropID, pPoint);
327 }
328
329 // deprecated
330 HRESULT GetThemeFont(int nPartID, HDC hDC, int nStateID, int nPropID, LOGFONTW* pFont) const
331 {
332 ATLASSERT(m_hTheme != NULL);
333 #ifdef _WTL_NEW_UXTHEME
334 return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
335 #else // !_WTL_NEW_UXTHEME
336 // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW*
337 return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont);
338 #endif // !_WTL_NEW_UXTHEME
339 }
340
341 HRESULT GetThemeFont(HDC hDC, int nPartID, int nStateID, int nPropID, LOGFONTW* pFont) const
342 {
343 ATLASSERT(m_hTheme != NULL);
344 #ifdef _WTL_NEW_UXTHEME
345 return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, pFont);
346 #else // !_WTL_NEW_UXTHEME
347 // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW*
348 return ::GetThemeFont(m_hTheme, hDC, nPartID, nStateID, nPropID, (LOGFONT*)pFont);
349 #endif // !_WTL_NEW_UXTHEME
350 }
351
352 HRESULT GetThemeRect(int nPartID, int nStateID, int nPropID, LPRECT pRect) const
353 {
354 ATLASSERT(m_hTheme != NULL);
355 return ::GetThemeRect(m_hTheme, nPartID, nStateID, nPropID, pRect);
356 }
357
358 HRESULT GetThemeMargins(HDC hDC, int nPartID, int nStateID, int nPropID, LPRECT pRect, PMARGINS pMargins) const
359 {
360 ATLASSERT(m_hTheme != NULL);
361 return ::GetThemeMargins(m_hTheme, hDC, nPartID, nStateID, nPropID, pRect, pMargins);
362 }
363
364 HRESULT GetThemeIntList(int nPartID, int nStateID, int nPropID, INTLIST* pIntList) const
365 {
366 ATLASSERT(m_hTheme != NULL);
367 return ::GetThemeIntList(m_hTheme, nPartID, nStateID, nPropID, pIntList);
368 }
369
370 HRESULT GetThemePropertyOrigin(int nPartID, int nStateID, int nPropID, enum PROPERTYORIGIN* pOrigin) const
371 {
372 ATLASSERT(m_hTheme != NULL);
373 return ::GetThemePropertyOrigin(m_hTheme, nPartID, nStateID, nPropID, pOrigin);
374 }
375
376 HRESULT GetThemeFilename(int nPartID, int nStateID, int nPropID, LPWSTR pszThemeFileName, int cchMaxBuffChars) const
377 {
378 ATLASSERT(m_hTheme != NULL);
379 return ::GetThemeFilename(m_hTheme, nPartID, nStateID, nPropID, pszThemeFileName, cchMaxBuffChars);
380 }
381
382 COLORREF GetThemeSysColor(int nColorID) const
383 {
384 ATLASSERT(m_hTheme != NULL);
385 return ::GetThemeSysColor(m_hTheme, nColorID);
386 }
387
388 HBRUSH GetThemeSysColorBrush(int nColorID) const
389 {
390 ATLASSERT(m_hTheme != NULL);
391 return ::GetThemeSysColorBrush(m_hTheme, nColorID);
392 }
393
394 int GetThemeSysSize(int nSizeID) const
395 {
396 ATLASSERT(m_hTheme != NULL);
397 return ::GetThemeSysSize(m_hTheme, nSizeID);
398 }
399
400 BOOL GetThemeSysBool(int nBoolID) const
401 {
402 ATLASSERT(m_hTheme != NULL);
403 return ::GetThemeSysBool(m_hTheme, nBoolID);
404 }
405
406 HRESULT GetThemeSysFont(int nFontID, LOGFONTW* plf) const
407 {
408 ATLASSERT(m_hTheme != NULL);
409 #ifdef _WTL_NEW_UXTHEME
410 return ::GetThemeSysFont(m_hTheme, nFontID, plf);
411 #else // !_WTL_NEW_UXTHEME
412 // Note: The cast to LOGFONT* is because uxtheme.h incorrectly uses it instead of LOGFONTW*
413 return ::GetThemeSysFont(m_hTheme, nFontID, (LOGFONT*)plf);
414 #endif // !_WTL_NEW_UXTHEME
415 }
416
417 HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const
418 {
419 ATLASSERT(m_hTheme != NULL);
420 return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars);
421 }
422
423 HRESULT GetThemeSysInt(int nIntID, int* pnValue) const
424 {
425 ATLASSERT(m_hTheme != NULL);
426 return ::GetThemeSysInt(m_hTheme, nIntID, pnValue);
427 }
428
429 #ifdef _WTL_NEW_UXTHEME
430 HTHEME OpenThemeDataEx(HWND hWnd, LPCWSTR pszClassList, DWORD dwFlags)
431 {
432 if(!IsThemingSupported())
433 return NULL;
434
435 ATLASSERT(m_hTheme == NULL);
436 m_hTheme = ::OpenThemeDataEx(hWnd, pszClassList, dwFlags);
437 return m_hTheme;
438 }
439
440 #if (_WIN32_WINNT >= 0x0600)
441 HRESULT DrawThemeTextEx(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT lpRect, const DTTOPTS* pOptions)
442 {
443 ATLASSERT(m_hTheme != NULL);
444 return ::DrawThemeTextEx(m_hTheme, hDC, nPartID, nStateID, pszText, cchText, dwTextFlags, lpRect, pOptions);
445 }
446
447 HRESULT GetThemeTransitionDuration(int nPartID, int nFromStateID, int nToStateID, int nPropID, DWORD& dwDuration)
448 {
449 ATLASSERT(m_hTheme != NULL);
450 return ::GetThemeTransitionDuration(m_hTheme, nPartID, nFromStateID, nToStateID, nPropID, &dwDuration);
451 }
452 #endif // (_WIN32_WINNT >= 0x0600)
453 #endif // _WTL_NEW_UXTHEME
454
455 #if (_WIN32_WINNT >= 0x0600)
456 HRESULT GetThemeBitmap(int nPartID, int nStateID, int nPropID, ULONG uFlags, HBITMAP& hBitmap)
457 {
458 ATLASSERT(m_hTheme != NULL);
459 return ::GetThemeBitmap(m_hTheme, nPartID, nStateID, nPropID, uFlags, &hBitmap);
460 }
461
462 HRESULT GetThemeStream(int nPartID, int nStateID, int nPropID, VOID** ppvStream, DWORD* pcbStream, HINSTANCE hInstance)
463 {
464 ATLASSERT(m_hTheme != NULL);
465 return ::GetThemeStream(m_hTheme, nPartID, nStateID, nPropID, ppvStream, pcbStream, hInstance);
466 }
467 #endif // (_WIN32_WINNT >= 0x0600)
468
469 #if (_WIN32_WINNT >= 0x0602)
470 HRESULT GetThemeAnimationProperty(int iStoryboardId, int iTargetId, TA_PROPERTY eProperty, VOID* pvProperty, DWORD cbSize, DWORD* pcbSizeOut)
471 {
472 ATLASSERT(m_hTheme != NULL);
473 return ::GetThemeAnimationProperty(m_hTheme, iStoryboardId, iTargetId, eProperty, pvProperty, cbSize, pcbSizeOut);
474 }
475
476 HRESULT GetThemeAnimationTransform(int iStoryboardId, int iTargetId, DWORD dwTransformIndex, TA_TRANSFORM* pTransform, DWORD cbSize, DWORD* pcbSizeOut)
477 {
478 ATLASSERT(m_hTheme != NULL);
479 return ::GetThemeAnimationTransform(m_hTheme, iStoryboardId, iTargetId, dwTransformIndex, pTransform, cbSize, pcbSizeOut);
480 }
481
482 HRESULT GetThemeTimingFunction(int iTimingFunctionId, TA_TIMINGFUNCTION* pTimingFunction, DWORD cbSize, DWORD* pcbSizeOut)
483 {
484 ATLASSERT(m_hTheme != NULL);
485 return ::GetThemeTimingFunction(m_hTheme, iTimingFunctionId, pTimingFunction, cbSize, pcbSizeOut);
486 }
487 #endif // (_WIN32_WINNT >= 0x0602)
488 };
489
490 __declspec(selectany) int CTheme::m_nIsThemingSupported = -1;
491
492
493 ///////////////////////////////////////////////////////////////////////////////
494 // CThemeImpl - theme support implementation
495
496 // Derive from this class to implement window with theme support.
497 // Example:
498 // class CMyThemeWindow : public CWindowImpl<CMyThemeWindow>, public CThemeImpl<CMyThemeWindow>
499 // {
500 // ...
501 // BEGIN_MSG_MAP(CMyThemeWindow)
502 // CHAIN_MSG_MAP(CThemeImpl<CMyThemeWindow>)
503 // ...
504 // END_MSG_MAP()
505 // ...
506 // };
507 //
508 // If you set theme class list, the class will automaticaly open/close/reopen theme data.
509
510
511 // Helper for drawing theme client edge
512 inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0)
513 {
514 ATLASSERT(hTheme != NULL);
515 ATLASSERT(::IsWindow(hWnd));
516
517 CWindowDC dc(hWnd);
518 if(dc.IsNull())
519 return false;
520
521 // Get border size
522 int cxBorder = ::GetSystemMetrics(SM_CXBORDER);
523 int cyBorder = ::GetSystemMetrics(SM_CYBORDER);
524 if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder)))
525 cyBorder = cxBorder;
526
527 RECT rect = { 0 };
528 ::GetWindowRect(hWnd, &rect);
529
530 // Remove the client edge from the update region
531 int cxEdge = ::GetSystemMetrics(SM_CXEDGE);
532 int cyEdge = ::GetSystemMetrics(SM_CYEDGE);
533 ::InflateRect(&rect, -cxEdge, -cyEdge);
534 CRgn rgn;
535 rgn.CreateRectRgnIndirect(&rect);
536 if(rgn.IsNull())
537 return false;
538
539 if(hRgnUpdate != NULL)
540 rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND);
541
542 ::OffsetRect(&rect, -rect.left, -rect.top);
543
544 ::OffsetRect(&rect, cxEdge, cyEdge);
545 dc.ExcludeClipRect(&rect);
546 ::InflateRect(&rect, cxEdge, cyEdge);
547
548 ::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL);
549
550 // Use background brush too, since theme border might not cover everything
551 if((cxBorder < cxEdge) && (cyBorder < cyEdge))
552 {
553 if(hBrush == NULL)
554 // need conditional code because types don't match in winuser.h
555 #ifdef _WIN64
556 hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
557 #else
558 hBrush = (HBRUSH)UlongToPtr(::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND));
559 #endif
560
561 ::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge);
562 dc.FillRect(&rect, hBrush);
563 }
564
565 ::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L);
566
567 return true;
568 }
569
570
571 // Theme extended styles
572 #define THEME_EX_3DCLIENTEDGE 0x00000001
573 #define THEME_EX_THEMECLIENTEDGE 0x00000002
574
575 template <class T, class TBase = CTheme>
576 class CThemeImpl : public TBase
577 {
578 public:
579 // Data members
580 LPWSTR m_lpstrThemeClassList;
581 DWORD m_dwExtendedStyle; // theme specific extended styles
582
583 // Constructor & destructor
584 CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0)
585 { }
586
587 ~CThemeImpl()
588 {
589 delete [] m_lpstrThemeClassList;
590 }
591
592 // Attributes
593 bool SetThemeClassList(LPCWSTR lpstrThemeClassList)
594 {
595 if(m_lpstrThemeClassList != NULL)
596 {
597 delete [] m_lpstrThemeClassList;
598 m_lpstrThemeClassList = NULL;
599 }
600
601 if(lpstrThemeClassList == NULL)
602 return true;
603
604 int cchLen = lstrlenW(lpstrThemeClassList) + 1;
605 ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]);
606 if(m_lpstrThemeClassList == NULL)
607 return false;
608
609 SecureHelper::strcpyW_x(m_lpstrThemeClassList, cchLen, lpstrThemeClassList);
610
611 return true;
612 }
613
614 bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const
615 {
616 int cchLen = lstrlenW(m_lpstrThemeClassList) + 1;
617 if(cchListBuffer < cchLen)
618 return false;
619
620 SecureHelper::strcpyW_x(lpstrThemeClassList, cchListBuffer, m_lpstrThemeClassList);
621
622 return true;
623 }
624
625 LPCWSTR GetThemeClassList() const
626 {
627 return m_lpstrThemeClassList;
628 }
629
630 DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
631 {
632 DWORD dwPrevStyle = m_dwExtendedStyle;
633 if(dwMask == 0)
634 m_dwExtendedStyle = dwExtendedStyle;
635 else
636 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
637
638 return dwPrevStyle;
639 }
640
641 DWORD GetThemeExtendedStyle() const
642 {
643 return m_dwExtendedStyle;
644 }
645
646 // Operations
647 HTHEME OpenThemeData()
648 {
649 T* pT = static_cast<T*>(this);
650 ATLASSERT(::IsWindow(pT->m_hWnd));
651 ATLASSERT(m_lpstrThemeClassList != NULL);
652 if(m_lpstrThemeClassList == NULL)
653 return NULL;
654 CloseThemeData();
655
656 return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList);
657 }
658
659 HTHEME OpenThemeData(LPCWSTR pszClassList)
660 {
661 if(!SetThemeClassList(pszClassList))
662 return NULL;
663
664 return OpenThemeData();
665 }
666
667 HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList)
668 {
669 if(!IsThemingSupported())
670 return S_FALSE;
671
672 T* pT = static_cast<T*>(this);
673 ATLASSERT(::IsWindow(pT->m_hWnd));
674 return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList);
675 }
676
677 HTHEME GetWindowTheme() const
678 {
679 if(!IsThemingSupported())
680 return NULL;
681
682 const T* pT = static_cast<const T*>(this);
683 ATLASSERT(::IsWindow(pT->m_hWnd));
684 return ::GetWindowTheme(pT->m_hWnd);
685 }
686
687 HRESULT EnableThemeDialogTexture(DWORD dwFlags)
688 {
689 if(!IsThemingSupported())
690 return S_FALSE;
691
692 T* pT = static_cast<T*>(this);
693 ATLASSERT(::IsWindow(pT->m_hWnd));
694 return ::EnableThemeDialogTexture(pT->m_hWnd, dwFlags);
695 }
696
697 BOOL IsThemeDialogTextureEnabled() const
698 {
699 if(!IsThemingSupported())
700 return FALSE;
701
702 const T* pT = static_cast<const T*>(this);
703 ATLASSERT(::IsWindow(pT->m_hWnd));
704 return ::IsThemeDialogTextureEnabled(pT->m_hWnd);
705 }
706
707 HRESULT DrawThemeParentBackground(HDC hDC, const RECT* pRect = NULL)
708 {
709 if(!IsThemingSupported())
710 return S_FALSE;
711
712 T* pT = static_cast<T*>(this);
713 ATLASSERT(::IsWindow(pT->m_hWnd));
714 #ifdef _WTL_NEW_UXTHEME
715 return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect);
716 #else
717 return ::DrawThemeParentBackground(pT->m_hWnd, hDC, (RECT*)pRect);
718 #endif
719 }
720
721 #if defined(_WTL_NEW_UXTHEME) && (_WIN32_WINNT >= 0x0600)
722 HRESULT SetWindowThemeAttribute(WINDOWTHEMEATTRIBUTETYPE type, PVOID pvAttribute, DWORD cbAttribute)
723 {
724 if(!IsThemingSupported())
725 return S_FALSE;
726
727 T* pT = static_cast<T*>(this);
728 ATLASSERT(::IsWindow(pT->m_hWnd));
729 return ::SetWindowThemeAttribute(pT->m_hWnd, type, pvAttribute, cbAttribute);
730 }
731
732 HRESULT SetWindowThemeNonClientAttributes(DWORD dwAttributes, DWORD dwMask)
733 {
734 if(!IsThemingSupported())
735 return S_FALSE;
736
737 T* pT = static_cast<T*>(this);
738 ATLASSERT(::IsWindow(pT->m_hWnd));
739 WTA_OPTIONS opt = { dwAttributes, dwMask };
740 return ::SetWindowThemeAttribute(pT->m_hWnd, WTA_NONCLIENT, (PVOID)&opt, sizeof(opt));
741 }
742
743 HRESULT DrawThemeParentBackgroundEx(HDC hDC, DWORD dwFlags, const RECT* lpRect = NULL)
744 {
745 if(!IsThemingSupported())
746 return S_FALSE;
747
748 T* pT = static_cast<T*>(this);
749 ATLASSERT(::IsWindow(pT->m_hWnd));
750 return ::DrawThemeParentBackgroundEx(pT->m_hWnd, hDC, dwFlags, lpRect);
751 }
752 #endif // defined(_WTL_NEW_UXTHEME) && (_WIN32_WINNT >= 0x0600)
753
754 // Message map and handlers
755 // Note: If you handle any of these messages in your derived class,
756 // it is better to put CHAIN_MSG_MAP at the start of your message map.
757 BEGIN_MSG_MAP(CThemeImpl)
758 MESSAGE_HANDLER(WM_CREATE, OnCreate)
759 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
760 MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
761 MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
762 END_MSG_MAP()
763
764 LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
765 {
766 if(m_lpstrThemeClassList != NULL)
767 OpenThemeData();
768
769 bHandled = FALSE;
770 return 1;
771 }
772
773 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
774 {
775 CloseThemeData();
776
777 bHandled = FALSE;
778 return 1;
779 }
780
781 LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
782 {
783 CloseThemeData();
784 if(m_lpstrThemeClassList != NULL)
785 OpenThemeData();
786
787 bHandled = FALSE;
788 return 1;
789 }
790
791 LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
792 {
793 T* pT = static_cast<T*>(this);
794 ATLASSERT(::IsWindow(pT->m_hWnd));
795 LRESULT lRet = 0;
796 bHandled = FALSE;
797 if(IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0))
798 {
799 if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0)
800 {
801 lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam);
802 bHandled = TRUE;
803 }
804 else if((m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0))
805 {
806 HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL;
807 if(pT->DrawThemeClientEdge(hRgn))
808 bHandled = TRUE;
809 }
810 }
811
812 return lRet;
813 }
814
815 // Drawing helper
816 bool DrawThemeClientEdge(HRGN hRgnUpdate)
817 {
818 T* pT = static_cast<T*>(this);
819 return AtlDrawThemeClientEdge(m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0);
820 }
821 };
822
823 ///////////////////////////////////////////////////////////////////////////////
824 // Buffered Paint and Animation
825
826 #if defined(_WTL_NEW_UXTHEME) && (_WIN32_WINNT >= 0x0600)
827
828 ///////////////////////////////////////////////////////////////////////////////
829 // CBufferedPaintBase - Buffered Paint support for othe classes
830
831 class CBufferedPaintBase
832 {
833 public:
834 static int m_nIsBufferedPaintSupported;
835
836 CBufferedPaintBase()
837 {
838 if(IsBufferedPaintSupported())
839 ATLVERIFY(SUCCEEDED(::BufferedPaintInit()));
840 }
841
842 ~CBufferedPaintBase()
843 {
844 if(IsBufferedPaintSupported())
845 ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit()));
846 }
847
848 static bool IsBufferedPaintSupported()
849 {
850 if(m_nIsBufferedPaintSupported == -1)
851 {
852 CStaticDataInitCriticalSectionLock lock;
853 if(FAILED(lock.Lock()))
854 {
855 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CBufferedPaintBase::IsBufferedPaintSupported.\n"));
856 ATLASSERT(FALSE);
857 return false;
858 }
859
860 if(m_nIsBufferedPaintSupported == -1)
861 m_nIsBufferedPaintSupported = RunTimeHelper::IsVista() ? 1 : 0;
862
863 lock.Unlock();
864 }
865
866 ATLASSERT(m_nIsBufferedPaintSupported != -1);
867 return (m_nIsBufferedPaintSupported == 1);
868 }
869 };
870
871 __declspec(selectany) int CBufferedPaintBase::m_nIsBufferedPaintSupported = -1;
872
873
874 ///////////////////////////////////////////////////////////////////////////////
875 // CBufferedPaint - support for buffered paint functions
876
877 class CBufferedPaint
878 {
879 public:
880 HPAINTBUFFER m_hPaintBuffer;
881
882 CBufferedPaint() : m_hPaintBuffer(NULL)
883 { }
884
885 ~CBufferedPaint()
886 {
887 ATLVERIFY(SUCCEEDED(End()));
888 }
889
890 bool IsNull() const
891 {
892 return (m_hPaintBuffer == NULL);
893 }
894
895 HPAINTBUFFER Begin(HDC hdcTarget, const RECT* prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, HDC* phdcPaint)
896 {
897 ATLASSERT(m_hPaintBuffer == NULL);
898 m_hPaintBuffer = ::BeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcPaint);
899 return m_hPaintBuffer;
900 }
901
902 HRESULT End(BOOL bUpdate = TRUE)
903 {
904 HRESULT hRet = S_FALSE;
905 if(m_hPaintBuffer != NULL)
906 {
907 hRet = ::EndBufferedPaint(m_hPaintBuffer, bUpdate);
908 m_hPaintBuffer = NULL;
909 }
910 return hRet;
911 }
912
913 HRESULT GetTargetRect(LPRECT pRect) const
914 {
915 ATLASSERT(m_hPaintBuffer != NULL);
916 return ::GetBufferedPaintTargetRect(m_hPaintBuffer, pRect);
917 }
918
919 HDC GetTargetDC() const
920 {
921 ATLASSERT(m_hPaintBuffer != NULL);
922 return ::GetBufferedPaintTargetDC(m_hPaintBuffer);
923 }
924
925 HDC GetPaintDC() const
926 {
927 ATLASSERT(m_hPaintBuffer != NULL);
928 return ::GetBufferedPaintDC(m_hPaintBuffer);
929 }
930
931 HRESULT GetBits(RGBQUAD** ppbBuffer, int* pcxRow) const
932 {
933 ATLASSERT(m_hPaintBuffer != NULL);
934 return ::GetBufferedPaintBits(m_hPaintBuffer, ppbBuffer, pcxRow);
935 }
936
937 HRESULT Clear(const RECT* pRect = NULL)
938 {
939 ATLASSERT(m_hPaintBuffer != NULL);
940 return ::BufferedPaintClear(m_hPaintBuffer, pRect);
941 }
942
943 HRESULT SetAlpha(BYTE alpha, const RECT* pRect = NULL)
944 {
945 ATLASSERT(m_hPaintBuffer != NULL);
946 return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, alpha);
947 }
948
949 HRESULT MakeOpaque(const RECT* pRect = NULL)
950 {
951 ATLASSERT(m_hPaintBuffer != NULL);
952 return ::BufferedPaintSetAlpha(m_hPaintBuffer, pRect, 255);
953 }
954 };
955
956
957 ///////////////////////////////////////////////////////////////////////////////
958 // CBufferedPaintImpl - provides buffered paint for any window
959
960 template <class T>
961 class ATL_NO_VTABLE CBufferedPaintImpl : public CBufferedPaintBase
962 {
963 public:
964 CBufferedPaint m_BufferedPaint;
965 BP_BUFFERFORMAT m_dwFormat;
966 BP_PAINTPARAMS m_PaintParams;
967
968 CBufferedPaintImpl() : m_dwFormat(BPBF_TOPDOWNDIB)
969 {
970 memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS));
971 m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS);
972 }
973
974 // Message map and handlers
975 BEGIN_MSG_MAP(CBufferedPaintImpl)
976 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
977 MESSAGE_HANDLER(WM_PAINT, OnPaint)
978 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
979 END_MSG_MAP()
980
981 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
982 {
983 return 1; // no background needed
984 }
985
986 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
987 {
988 T* pT = static_cast<T*>(this);
989 if(wParam != NULL)
990 {
991 RECT rect = { 0 };
992 pT->GetClientRect(&rect);
993 pT->DoPaint((HDC)wParam, rect);
994 }
995 else
996 {
997 CPaintDC dc(pT->m_hWnd);
998 pT->DoBufferedPaint(dc.m_hDC, dc.m_ps.rcPaint);
999 }
1000
1001 return 0;
1002 }
1003
1004 // Overrideables
1005 void DoBufferedPaint(CDCHandle dc, RECT& rect)
1006 {
1007 HDC hDCPaint = NULL;
1008 if(IsBufferedPaintSupported())
1009 m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint);
1010
1011 T* pT = static_cast<T*>(this);
1012 if(hDCPaint != NULL)
1013 pT->DoPaint(hDCPaint, rect);
1014 else
1015 pT->DoPaint(dc.m_hDC, rect);
1016
1017 if(IsBufferedPaintSupported())
1018 m_BufferedPaint.End();
1019 }
1020
1021 void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/)
1022 {
1023 // must be implemented in a derived class
1024 ATLASSERT(FALSE);
1025 }
1026 };
1027
1028
1029 ///////////////////////////////////////////////////////////////////////////////
1030 // CBufferedPaintWindowImpl - implements a window that uses buffered paint
1031
1032 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1033 class ATL_NO_VTABLE CBufferedPaintWindowImpl :
1034 public ATL::CWindowImpl<T, TBase, TWinTraits>,
1035 public CBufferedPaintImpl< T >
1036 {
1037 public:
1038 BEGIN_MSG_MAP(CBufferedPaintWindowImpl)
1039 CHAIN_MSG_MAP(CBufferedPaintImpl< T >)
1040 END_MSG_MAP()
1041 };
1042
1043
1044 ///////////////////////////////////////////////////////////////////////////////
1045 // CBufferedAnimation - support for buffered animation
1046
1047 class CBufferedAnimation
1048 {
1049 public:
1050 HANIMATIONBUFFER m_hAnimationBuffer;
1051
1052 CBufferedAnimation() : m_hAnimationBuffer(NULL)
1053 { }
1054
1055 ~CBufferedAnimation()
1056 {
1057 ATLVERIFY(SUCCEEDED(End()));
1058 }
1059
1060 bool IsNull() const
1061 {
1062 return (m_hAnimationBuffer == NULL);
1063 }
1064
1065 HANIMATIONBUFFER Begin(HWND hWnd, HDC hDCTarget, const RECT* pRectTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS* pPaintParams, BP_ANIMATIONPARAMS* pAnimationParams, HDC* phdcFrom, HDC* phdcTo)
1066 {
1067 ATLASSERT(m_hAnimationBuffer == NULL);
1068 m_hAnimationBuffer = ::BeginBufferedAnimation(hWnd, hDCTarget, pRectTarget, dwFormat, pPaintParams, pAnimationParams, phdcFrom, phdcTo);
1069 return m_hAnimationBuffer;
1070 }
1071
1072 HRESULT End(BOOL bUpdate = TRUE)
1073 {
1074 HRESULT hRet = S_FALSE;
1075 if(m_hAnimationBuffer != NULL)
1076 {
1077 hRet = ::EndBufferedAnimation(m_hAnimationBuffer, bUpdate);
1078 m_hAnimationBuffer = NULL;
1079 }
1080 return hRet;
1081 }
1082
1083 static bool IsRendering(HWND hWnd, HDC hDC)
1084 {
1085 return (::BufferedPaintRenderAnimation(hWnd, hDC) != FALSE);
1086 }
1087
1088 static HRESULT StopAllAnimations(HWND hWnd)
1089 {
1090 return ::BufferedPaintStopAllAnimations(hWnd);
1091 }
1092 };
1093
1094
1095 ///////////////////////////////////////////////////////////////////////////////
1096 // CBufferedAnimationImpl - provides buffered animation support for any window
1097
1098 // Note: You can either use m_State and m_NewState to store the state information
1099 // for the animation change, or map your state to those data members. DoPaint()
1100 // should only rely on the state information that is passed to it.
1101
1102 template <class T, class TState = DWORD_PTR>
1103 class ATL_NO_VTABLE CBufferedAnimationImpl : public CBufferedPaintBase
1104 {
1105 public:
1106 BP_BUFFERFORMAT m_dwFormat;
1107 BP_PAINTPARAMS m_PaintParams;
1108 BP_ANIMATIONPARAMS m_AnimationParams;
1109
1110 TState m_State;
1111 TState m_NewState;
1112
1113 CBufferedAnimationImpl(TState InitialState) : m_dwFormat(BPBF_TOPDOWNDIB)
1114 {
1115 memset(&m_PaintParams, 0, sizeof(BP_PAINTPARAMS));
1116 m_PaintParams.cbSize = sizeof(BP_PAINTPARAMS);
1117
1118 memset(&m_AnimationParams, 0, sizeof(BP_ANIMATIONPARAMS));
1119 m_AnimationParams.cbSize = sizeof(BP_ANIMATIONPARAMS);
1120 m_AnimationParams.style = BPAS_LINEAR;
1121 m_AnimationParams.dwDuration = 500;
1122
1123 T* pT = static_cast<T*>(this);
1124 pT->SetState(InitialState);
1125 pT->SetNewState(InitialState);
1126 }
1127
1128 DWORD GetDuration() const
1129 {
1130 return m_AnimationParams.dwDuration;
1131 }
1132
1133 void SetDuration(DWORD dwDuration)
1134 {
1135 m_AnimationParams.dwDuration = dwDuration;
1136 }
1137
1138 void DoAnimation(TState NewState, const RECT* pRect = NULL)
1139 {
1140 T* pT = static_cast<T*>(this);
1141 pT->SetNewState(NewState);
1142
1143 pT->InvalidateRect(pRect, FALSE);
1144 pT->UpdateWindow();
1145
1146 pT->SetState(NewState);
1147 }
1148
1149 // Message map and handlers
1150 BEGIN_MSG_MAP(CBufferedAnimationImpl)
1151 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
1152 MESSAGE_HANDLER(WM_PAINT, OnPaint)
1153 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
1154 END_MSG_MAP()
1155
1156 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1157 {
1158 return 1; // no background needed
1159 }
1160
1161 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1162 {
1163 T* pT = static_cast<T*>(this);
1164 if(wParam != NULL)
1165 {
1166 RECT rect = { 0 };
1167 pT->GetClientRect(&rect);
1168 pT->DoPaint((HDC)wParam, rect, m_NewState);
1169 }
1170 else
1171 {
1172 CPaintDC dc(pT->m_hWnd);
1173 pT->DoAnimationPaint(dc.m_hDC, dc.m_ps.rcPaint);
1174 }
1175
1176 return 0;
1177 }
1178
1179 // Overrideables
1180 void SetState(TState State)
1181 {
1182 m_State = State;
1183 }
1184
1185 void SetNewState(TState State)
1186 {
1187 m_NewState = State;
1188 }
1189
1190 bool AreStatesEqual() const
1191 {
1192 return (m_State == m_NewState);
1193 }
1194
1195 void DoAnimationPaint(CDCHandle dc, RECT& rect)
1196 {
1197 T* pT = static_cast<T*>(this);
1198 if(IsBufferedPaintSupported() && CBufferedAnimation::IsRendering(pT->m_hWnd, dc))
1199 return;
1200
1201 DWORD dwDurationSave = m_AnimationParams.dwDuration;
1202 if(pT->AreStatesEqual())
1203 m_AnimationParams.dwDuration = 0;
1204
1205 HDC hdcFrom = NULL, hdcTo = NULL;
1206 CBufferedAnimation ba;
1207 if(IsBufferedPaintSupported())
1208 ba.Begin(pT->m_hWnd, dc, &rect, m_dwFormat, &m_PaintParams, &m_AnimationParams, &hdcFrom, &hdcTo);
1209
1210 if(!ba.IsNull())
1211 {
1212 if(hdcFrom != NULL)
1213 pT->DoPaint(hdcFrom, rect, m_State);
1214
1215 if (hdcTo != NULL)
1216 pT->DoPaint(hdcTo, rect, m_NewState);
1217 }
1218 else
1219 {
1220 pT->DoPaint(dc.m_hDC, rect, m_NewState);
1221 }
1222
1223 m_AnimationParams.dwDuration = dwDurationSave;
1224 }
1225
1226 void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/, TState /*State*/)
1227 {
1228 // must be implemented in a derived class
1229 ATLASSERT(FALSE);
1230 }
1231 };
1232
1233
1234 ///////////////////////////////////////////////////////////////////////////////
1235 // CBufferedAnimationWindowImpl - implements a window that uses buffered animation
1236
1237 template <class T, class TState = DWORD_PTR, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1238 class ATL_NO_VTABLE CBufferedAnimationWindowImpl :
1239 public ATL::CWindowImpl<T, TBase, TWinTraits>,
1240 public CBufferedAnimationImpl< T, TState >
1241 {
1242 public:
1243 CBufferedAnimationWindowImpl(TState InitialState) : CBufferedAnimationImpl< T, TState >(InitialState)
1244 { }
1245
1246 typedef CBufferedAnimationImpl< T, TState > _baseBufferedAnimation;
1247 BEGIN_MSG_MAP(CBufferedAnimationWindowImpl)
1248 CHAIN_MSG_MAP(_baseBufferedAnimation)
1249 END_MSG_MAP()
1250 };
1251
1252 #endif // defined(_WTL_NEW_UXTHEME) && (_WIN32_WINNT >= 0x0600)
1253
1254 }; // namespace WTL
1255
1256 #endif // __ATLTHEME_H__
+0
-1387
src/third_party/wtl/Include/atluser.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLUSER_H__
9 #define __ATLUSER_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atluser.h requires atlapp.h to be included first
15 #endif
16
17
18 ///////////////////////////////////////////////////////////////////////////////
19 // Classes in this file:
20 //
21 // CMenuItemInfo
22 // CMenuT<t_bManaged>
23 // CAcceleratorT<t_bManaged>
24 // CIconT<t_bManaged>
25 // CCursorT<t_bManaged>
26 // CResource
27 //
28 // Global functions:
29 // AtlMessageBox()
30 //
31 // AtlLoadAccelerators()
32 // AtlLoadMenu()
33 // AtlLoadBitmap()
34 // AtlLoadSysBitmap()
35 // AtlLoadCursor()
36 // AtlLoadSysCursor()
37 // AtlLoadIcon()
38 // AtlLoadSysIcon()
39 // AtlLoadBitmapImage()
40 // AtlLoadCursorImage()
41 // AtlLoadIconImage()
42 // AtlLoadSysBitmapImage()
43 // AtlLoadSysCursorImage()
44 // AtlLoadSysIconImage()
45 // AtlLoadString()
46
47
48 namespace WTL
49 {
50
51 ///////////////////////////////////////////////////////////////////////////////
52 // AtlMessageBox - accepts both memory and resource based strings
53
54 inline int AtlMessageBox(HWND hWndOwner, ATL::_U_STRINGorID message, ATL::_U_STRINGorID title = (LPCTSTR)NULL, UINT uType = MB_OK | MB_ICONINFORMATION)
55 {
56 ATLASSERT(hWndOwner == NULL || ::IsWindow(hWndOwner));
57
58 LPTSTR lpstrMessage = NULL;
59 if(IS_INTRESOURCE(message.m_lpstr))
60 {
61 for(int nLen = 256; ; nLen *= 2)
62 {
63 ATLTRY(lpstrMessage = new TCHAR[nLen]);
64 if(lpstrMessage == NULL)
65 {
66 ATLASSERT(FALSE);
67 return 0;
68 }
69 int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(message.m_lpstr), lpstrMessage, nLen);
70 if(nRes < nLen - 1)
71 break;
72 delete [] lpstrMessage;
73 lpstrMessage = NULL;
74 }
75
76 message.m_lpstr = lpstrMessage;
77 }
78
79 LPTSTR lpstrTitle = NULL;
80 if(IS_INTRESOURCE(title.m_lpstr) && LOWORD(title.m_lpstr) != 0)
81 {
82 for(int nLen = 256; ; nLen *= 2)
83 {
84 ATLTRY(lpstrTitle = new TCHAR[nLen]);
85 if(lpstrTitle == NULL)
86 {
87 ATLASSERT(FALSE);
88 return 0;
89 }
90 int nRes = ::LoadString(ModuleHelper::GetResourceInstance(), LOWORD(title.m_lpstr), lpstrTitle, nLen);
91 if(nRes < nLen - 1)
92 break;
93 delete [] lpstrTitle;
94 lpstrTitle = NULL;
95 }
96
97 title.m_lpstr = lpstrTitle;
98 }
99
100 int nRet = ::MessageBox(hWndOwner, message.m_lpstr, title.m_lpstr, uType);
101
102 delete [] lpstrMessage;
103 delete [] lpstrTitle;
104
105 return nRet;
106 }
107
108
109 ///////////////////////////////////////////////////////////////////////////////
110 // CMenu
111
112 #if (WINVER >= 0x0500)
113 #ifndef MII_SIZEOF_STRUCT
114 #define MII_SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
115 #endif
116 #define MENUITEMINFO_SIZE_VERSION_400A MII_SIZEOF_STRUCT(MENUITEMINFOA, cch)
117 #define MENUITEMINFO_SIZE_VERSION_400W MII_SIZEOF_STRUCT(MENUITEMINFOW, cch)
118 #ifdef UNICODE
119 #define MENUITEMINFO_SIZE_VERSION_400 MENUITEMINFO_SIZE_VERSION_400W
120 #else
121 #define MENUITEMINFO_SIZE_VERSION_400 MENUITEMINFO_SIZE_VERSION_400A
122 #endif // !UNICODE
123 #endif // (WINVER >= 0x0500)
124
125 class CMenuItemInfo : public MENUITEMINFO
126 {
127 public:
128 CMenuItemInfo()
129 {
130 memset(this, 0, sizeof(MENUITEMINFO));
131 cbSize = sizeof(MENUITEMINFO);
132 #if (WINVER >= 0x0500)
133 // adjust struct size if running on older version of Windows
134 if(AtlIsOldWindows())
135 {
136 ATLASSERT(cbSize > MENUITEMINFO_SIZE_VERSION_400); // must be
137 cbSize = MENUITEMINFO_SIZE_VERSION_400;
138 }
139 #endif // (WINVER >= 0x0500)
140 }
141 };
142
143
144 // forward declarations
145 template <bool t_bManaged> class CMenuT;
146 typedef CMenuT<false> CMenuHandle;
147 typedef CMenuT<true> CMenu;
148
149
150 template <bool t_bManaged>
151 class CMenuT
152 {
153 public:
154 // Data members
155 HMENU m_hMenu;
156
157 // Constructor/destructor/operators
158 CMenuT(HMENU hMenu = NULL) : m_hMenu(hMenu)
159 { }
160
161 ~CMenuT()
162 {
163 if(t_bManaged && m_hMenu != NULL)
164 DestroyMenu();
165 }
166
167 CMenuT<t_bManaged>& operator =(HMENU hMenu)
168 {
169 Attach(hMenu);
170 return *this;
171 }
172
173 void Attach(HMENU hMenuNew)
174 {
175 ATLASSERT(::IsMenu(hMenuNew));
176 if(t_bManaged && m_hMenu != NULL && m_hMenu != hMenuNew)
177 ::DestroyMenu(m_hMenu);
178 m_hMenu = hMenuNew;
179 }
180
181 HMENU Detach()
182 {
183 HMENU hMenu = m_hMenu;
184 m_hMenu = NULL;
185 return hMenu;
186 }
187
188 operator HMENU() const { return m_hMenu; }
189
190 bool IsNull() const { return (m_hMenu == NULL); }
191
192 BOOL IsMenu() const
193 {
194 return ::IsMenu(m_hMenu);
195 }
196
197 // Create/destroy methods
198 BOOL CreateMenu()
199 {
200 ATLASSERT(m_hMenu == NULL);
201 m_hMenu = ::CreateMenu();
202 return (m_hMenu != NULL) ? TRUE : FALSE;
203 }
204
205 BOOL CreatePopupMenu()
206 {
207 ATLASSERT(m_hMenu == NULL);
208 m_hMenu = ::CreatePopupMenu();
209 return (m_hMenu != NULL) ? TRUE : FALSE;
210 }
211
212 BOOL LoadMenu(ATL::_U_STRINGorID menu)
213 {
214 ATLASSERT(m_hMenu == NULL);
215 m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr);
216 return (m_hMenu != NULL) ? TRUE : FALSE;
217 }
218
219 #ifndef _WIN32_WCE
220 BOOL LoadMenuIndirect(const void* lpMenuTemplate)
221 {
222 ATLASSERT(m_hMenu == NULL);
223 m_hMenu = ::LoadMenuIndirect(lpMenuTemplate);
224 return (m_hMenu != NULL) ? TRUE : FALSE;
225 }
226 #endif // !_WIN32_WCE
227
228 BOOL DestroyMenu()
229 {
230 if (m_hMenu == NULL)
231 return FALSE;
232 BOOL bRet = ::DestroyMenu(m_hMenu);
233 if(bRet)
234 m_hMenu = NULL;
235 return bRet;
236 }
237
238 // Menu Operations
239 BOOL DeleteMenu(UINT nPosition, UINT nFlags)
240 {
241 ATLASSERT(::IsMenu(m_hMenu));
242 return ::DeleteMenu(m_hMenu, nPosition, nFlags);
243 }
244
245 BOOL TrackPopupMenu(UINT nFlags, int x, int y, HWND hWnd, LPCRECT lpRect = NULL)
246 {
247 ATLASSERT(::IsMenu(m_hMenu));
248 #ifndef _WIN32_WCE
249 #if (WINVER >= 0x0500)
250 x = _FixTrackMenuPopupX(x, y);
251 #endif // !(WINVER >= 0x0500)
252 return ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0, hWnd, lpRect);
253 #else // CE specific
254 lpRect;
255 return ::TrackPopupMenuEx(m_hMenu, nFlags, x, y, hWnd, NULL);
256 #endif // _WIN32_WCE
257 }
258
259 BOOL TrackPopupMenuEx(UINT uFlags, int x, int y, HWND hWnd, LPTPMPARAMS lptpm = NULL)
260 {
261 ATLASSERT(::IsMenu(m_hMenu));
262 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
263 x = _FixTrackMenuPopupX(x, y);
264 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
265 return ::TrackPopupMenuEx(m_hMenu, uFlags, x, y, hWnd, lptpm);
266 }
267
268 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
269 // helper that fixes popup menu X position when it's off-screen
270 static int _FixTrackMenuPopupX(int x, int y)
271 {
272 POINT pt = { x, y };
273 HMONITOR hMonitor = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
274 if(hMonitor == NULL)
275 {
276 HMONITOR hMonitorNear = ::MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
277 if(hMonitorNear != NULL)
278 {
279 MONITORINFO mi = { sizeof(MONITORINFO) };
280 if(::GetMonitorInfo(hMonitorNear, &mi) != FALSE)
281 {
282 if(x < mi.rcWork.left)
283 x = mi.rcWork.left;
284 else if(x > mi.rcWork.right)
285 x = mi.rcWork.right;
286 }
287 }
288 }
289
290 return x;
291 }
292
293 BOOL GetMenuInfo(LPMENUINFO lpMenuInfo) const
294 {
295 ATLASSERT(::IsMenu(m_hMenu));
296 return ::GetMenuInfo(m_hMenu, lpMenuInfo);
297 }
298
299 BOOL SetMenuInfo(LPCMENUINFO lpMenuInfo)
300 {
301 ATLASSERT(::IsMenu(m_hMenu));
302 return ::SetMenuInfo(m_hMenu, lpMenuInfo);
303 }
304 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
305
306 // Menu Item Operations
307 BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL)
308 {
309 ATLASSERT(::IsMenu(m_hMenu));
310 return ::AppendMenu(m_hMenu, nFlags, nIDNewItem, lpszNewItem);
311 }
312
313 BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem)
314 {
315 ATLASSERT(::IsMenu(m_hMenu));
316 ATLASSERT(::IsMenu(hSubMenu));
317 return ::AppendMenu(m_hMenu, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem);
318 }
319
320 #ifndef _WIN32_WCE
321 BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp)
322 {
323 ATLASSERT(::IsMenu(m_hMenu));
324 return ::AppendMenu(m_hMenu, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp);
325 }
326
327 BOOL AppendMenu(UINT nFlags, HMENU hSubMenu, HBITMAP hBmp)
328 {
329 ATLASSERT(::IsMenu(m_hMenu));
330 ATLASSERT(::IsMenu(hSubMenu));
331 return ::AppendMenu(m_hMenu, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp);
332 }
333 #endif // !_WIN32_WCE
334
335 UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck)
336 {
337 ATLASSERT(::IsMenu(m_hMenu));
338 return (UINT)::CheckMenuItem(m_hMenu, nIDCheckItem, nCheck);
339 }
340
341 UINT EnableMenuItem(UINT nIDEnableItem, UINT nEnable)
342 {
343 ATLASSERT(::IsMenu(m_hMenu));
344 return ::EnableMenuItem(m_hMenu, nIDEnableItem, nEnable);
345 }
346
347 #ifndef _WIN32_WCE
348 BOOL HiliteMenuItem(HWND hWnd, UINT uIDHiliteItem, UINT uHilite)
349 {
350 ATLASSERT(::IsMenu(m_hMenu));
351 return ::HiliteMenuItem(hWnd, m_hMenu, uIDHiliteItem, uHilite);
352 }
353
354 int GetMenuItemCount() const
355 {
356 ATLASSERT(::IsMenu(m_hMenu));
357 return ::GetMenuItemCount(m_hMenu);
358 }
359
360 UINT GetMenuItemID(int nPos) const
361 {
362 ATLASSERT(::IsMenu(m_hMenu));
363 return ::GetMenuItemID(m_hMenu, nPos);
364 }
365
366 UINT GetMenuState(UINT nID, UINT nFlags) const
367 {
368 ATLASSERT(::IsMenu(m_hMenu));
369 return ::GetMenuState(m_hMenu, nID, nFlags);
370 }
371
372 int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const
373 {
374 ATLASSERT(::IsMenu(m_hMenu));
375 return ::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags);
376 }
377
378 int GetMenuStringLen(UINT nIDItem, UINT nFlags) const
379 {
380 ATLASSERT(::IsMenu(m_hMenu));
381 return ::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags);
382 }
383
384 #ifndef _ATL_NO_COM
385 BOOL GetMenuString(UINT nIDItem, BSTR& bstrText, UINT nFlags) const
386 {
387 USES_CONVERSION;
388 ATLASSERT(::IsMenu(m_hMenu));
389 ATLASSERT(bstrText == NULL);
390
391 int nLen = GetMenuStringLen(nIDItem, nFlags);
392 if(nLen == 0)
393 {
394 bstrText = ::SysAllocString(OLESTR(""));
395 return (bstrText != NULL) ? TRUE : FALSE;
396 }
397
398 nLen++; // increment to include terminating NULL char
399 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
400 LPTSTR lpszText = buff.Allocate(nLen);
401 if(lpszText == NULL)
402 return FALSE;
403
404 if(!GetMenuString(nIDItem, lpszText, nLen, nFlags))
405 return FALSE;
406
407 bstrText = ::SysAllocString(T2OLE(lpszText));
408 return (bstrText != NULL) ? TRUE : FALSE;
409 }
410 #endif // !_ATL_NO_COM
411
412 #elif (_ATL_VER >= 0x0800)
413 int GetMenuItemCount() const
414 {
415 ATLASSERT(::IsMenu(m_hMenu));
416 return ATL::GetMenuItemCount(m_hMenu);
417 }
418
419 UINT GetMenuItemID(int nPos) const
420 {
421 ATLASSERT(::IsMenu(m_hMenu));
422 return ATL::GetMenuItemID(m_hMenu, nPos);
423 }
424
425 UINT GetMenuState(UINT nID, UINT nFlags) const
426 {
427 ATLASSERT(::IsMenu(m_hMenu));
428 return ATL::GetMenuState(m_hMenu, nID, nFlags);
429 }
430
431 int GetMenuString(UINT nIDItem, LPTSTR lpString, int nMaxCount, UINT nFlags) const
432 {
433 ATLASSERT(::IsMenu(m_hMenu));
434 return ATL::GetMenuString(m_hMenu, nIDItem, lpString, nMaxCount, nFlags);
435 }
436
437 int GetMenuStringLen(UINT nIDItem, UINT nFlags) const
438 {
439 ATLASSERT(::IsMenu(m_hMenu));
440 return ATL::GetMenuString(m_hMenu, nIDItem, NULL, 0, nFlags);
441 }
442 #endif // (_ATL_VER >= 0x0800)
443
444 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
445 int GetMenuString(UINT nIDItem, _CSTRING_NS::CString& strText, UINT nFlags) const
446 {
447 ATLASSERT(::IsMenu(m_hMenu));
448
449 int nLen = GetMenuStringLen(nIDItem, nFlags);
450 if(nLen == 0)
451 return 0;
452
453 nLen++; // increment to include terminating NULL char
454 LPTSTR lpstr = strText.GetBufferSetLength(nLen);
455 if(lpstr == NULL)
456 return 0;
457 int nRet = GetMenuString(nIDItem, lpstr, nLen, nFlags);
458 strText.ReleaseBuffer();
459 return nRet;
460 }
461 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
462
463 CMenuHandle GetSubMenu(int nPos) const
464 {
465 ATLASSERT(::IsMenu(m_hMenu));
466 return CMenuHandle(::GetSubMenu(m_hMenu, nPos));
467 }
468
469 BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL)
470 {
471 ATLASSERT(::IsMenu(m_hMenu));
472 return ::InsertMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem);
473 }
474
475 BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem)
476 {
477 ATLASSERT(::IsMenu(m_hMenu));
478 ATLASSERT(::IsMenu(hSubMenu));
479 return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem);
480 }
481
482 #ifndef _WIN32_WCE
483 BOOL InsertMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp)
484 {
485 ATLASSERT(::IsMenu(m_hMenu));
486 return ::InsertMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp);
487 }
488
489 BOOL InsertMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp)
490 {
491 ATLASSERT(::IsMenu(m_hMenu));
492 ATLASSERT(::IsMenu(hSubMenu));
493 return ::InsertMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp);
494 }
495
496 BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL)
497 {
498 ATLASSERT(::IsMenu(m_hMenu));
499 return ::ModifyMenu(m_hMenu, nPosition, nFlags, nIDNewItem, lpszNewItem);
500 }
501
502 BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, LPCTSTR lpszNewItem)
503 {
504 ATLASSERT(::IsMenu(m_hMenu));
505 ATLASSERT(::IsMenu(hSubMenu));
506 return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_POPUP, (UINT_PTR)hSubMenu, lpszNewItem);
507 }
508
509 BOOL ModifyMenu(UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem, HBITMAP hBmp)
510 {
511 ATLASSERT(::IsMenu(m_hMenu));
512 return ::ModifyMenu(m_hMenu, nPosition, nFlags | MF_BITMAP, nIDNewItem, (LPCTSTR)hBmp);
513 }
514
515 BOOL ModifyMenu(UINT nPosition, UINT nFlags, HMENU hSubMenu, HBITMAP hBmp)
516 {
517 ATLASSERT(::IsMenu(m_hMenu));
518 ATLASSERT(::IsMenu(hSubMenu));
519 return ::ModifyMenu(m_hMenu, nPosition, nFlags | (MF_BITMAP | MF_POPUP), (UINT_PTR)hSubMenu, (LPCTSTR)hBmp);
520 }
521 #endif // !_WIN32_WCE
522
523 BOOL RemoveMenu(UINT nPosition, UINT nFlags)
524 {
525 ATLASSERT(::IsMenu(m_hMenu));
526 return ::RemoveMenu(m_hMenu, nPosition, nFlags);
527 }
528
529 #ifndef _WIN32_WCE
530 BOOL SetMenuItemBitmaps(UINT nPosition, UINT nFlags, HBITMAP hBmpUnchecked, HBITMAP hBmpChecked)
531 {
532 ATLASSERT(::IsMenu(m_hMenu));
533 return ::SetMenuItemBitmaps(m_hMenu, nPosition, nFlags, hBmpUnchecked, hBmpChecked);
534 }
535 #endif // !_WIN32_WCE
536
537 BOOL CheckMenuRadioItem(UINT nIDFirst, UINT nIDLast, UINT nIDItem, UINT nFlags)
538 {
539 ATLASSERT(::IsMenu(m_hMenu));
540 return ::CheckMenuRadioItem(m_hMenu, nIDFirst, nIDLast, nIDItem, nFlags);
541 }
542
543 BOOL GetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii) const
544 {
545 ATLASSERT(::IsMenu(m_hMenu));
546 return (BOOL)::GetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii);
547 }
548
549 BOOL SetMenuItemInfo(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii)
550 {
551 ATLASSERT(::IsMenu(m_hMenu));
552 return (BOOL)::SetMenuItemInfo(m_hMenu, uItem, bByPosition, lpmii);
553 }
554
555 #ifndef _WIN32_WCE
556 BOOL InsertMenuItem(UINT uItem, BOOL bByPosition, LPMENUITEMINFO lpmii)
557 {
558 ATLASSERT(::IsMenu(m_hMenu));
559 return (BOOL)::InsertMenuItem(m_hMenu, uItem, bByPosition, lpmii);
560 }
561
562 UINT GetMenuDefaultItem(BOOL bByPosition = FALSE, UINT uFlags = 0U) const
563 {
564 ATLASSERT(::IsMenu(m_hMenu));
565 return ::GetMenuDefaultItem(m_hMenu, (UINT)bByPosition, uFlags);
566 }
567
568 BOOL SetMenuDefaultItem(UINT uItem = (UINT)-1, BOOL bByPosition = FALSE)
569 {
570 ATLASSERT(::IsMenu(m_hMenu));
571 return ::SetMenuDefaultItem(m_hMenu, uItem, (UINT)bByPosition);
572 }
573
574 BOOL GetMenuItemRect(HWND hWnd, UINT uItem, LPRECT lprcItem) const
575 {
576 ATLASSERT(::IsMenu(m_hMenu));
577 return ::GetMenuItemRect(hWnd, m_hMenu, uItem, lprcItem);
578 }
579
580 int MenuItemFromPoint(HWND hWnd, POINT point) const
581 {
582 ATLASSERT(::IsMenu(m_hMenu));
583 return ::MenuItemFromPoint(hWnd, m_hMenu, point);
584 }
585
586 // Context Help Functions
587 BOOL SetMenuContextHelpId(DWORD dwContextHelpId)
588 {
589 ATLASSERT(::IsMenu(m_hMenu));
590 return ::SetMenuContextHelpId(m_hMenu, dwContextHelpId);
591 }
592
593 DWORD GetMenuContextHelpId() const
594 {
595 ATLASSERT(::IsMenu(m_hMenu));
596 return ::GetMenuContextHelpId(m_hMenu);
597 }
598 #endif // !_WIN32_WCE
599 };
600
601
602 ///////////////////////////////////////////////////////////////////////////////
603 // CAccelerator
604
605 template <bool t_bManaged>
606 class CAcceleratorT
607 {
608 public:
609 HACCEL m_hAccel;
610
611 // Constructor/destructor/operators
612 CAcceleratorT(HACCEL hAccel = NULL) : m_hAccel(hAccel)
613 { }
614
615 ~CAcceleratorT()
616 {
617 if(t_bManaged && m_hAccel != NULL)
618 ::DestroyAcceleratorTable(m_hAccel);
619 }
620
621 CAcceleratorT<t_bManaged>& operator =(HACCEL hAccel)
622 {
623 Attach(hAccel);
624 return *this;
625 }
626
627 void Attach(HACCEL hAccel)
628 {
629 if(t_bManaged && m_hAccel != NULL)
630 ::DestroyAcceleratorTable(m_hAccel);
631 m_hAccel = hAccel;
632 }
633
634 HACCEL Detach()
635 {
636 HACCEL hAccel = m_hAccel;
637 m_hAccel = NULL;
638 return hAccel;
639 }
640
641 operator HACCEL() const { return m_hAccel; }
642
643 bool IsNull() const { return m_hAccel == NULL; }
644
645 // Create/destroy methods
646 HACCEL LoadAccelerators(ATL::_U_STRINGorID accel)
647 {
648 ATLASSERT(m_hAccel == NULL);
649 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), accel.m_lpstr);
650 return m_hAccel;
651 }
652
653 HACCEL CreateAcceleratorTable(LPACCEL pAccel, int cEntries)
654 {
655 ATLASSERT(m_hAccel == NULL);
656 ATLASSERT(pAccel != NULL);
657 m_hAccel = ::CreateAcceleratorTable(pAccel, cEntries);
658 return m_hAccel;
659 }
660
661 void DestroyObject()
662 {
663 if(m_hAccel != NULL)
664 {
665 ::DestroyAcceleratorTable(m_hAccel);
666 m_hAccel = NULL;
667 }
668 }
669
670 // Operations
671 #ifndef _WIN32_WCE
672 int CopyAcceleratorTable(LPACCEL lpAccelDst, int cEntries)
673 {
674 ATLASSERT(m_hAccel != NULL);
675 ATLASSERT(lpAccelDst != NULL);
676 return ::CopyAcceleratorTable(m_hAccel, lpAccelDst, cEntries);
677 }
678
679 int GetEntriesCount() const
680 {
681 ATLASSERT(m_hAccel != NULL);
682 return ::CopyAcceleratorTable(m_hAccel, NULL, 0);
683 }
684 #endif // !_WIN32_WCE
685
686 BOOL TranslateAccelerator(HWND hWnd, LPMSG pMsg)
687 {
688 ATLASSERT(m_hAccel != NULL);
689 ATLASSERT(::IsWindow(hWnd));
690 ATLASSERT(pMsg != NULL);
691 return ::TranslateAccelerator(hWnd, m_hAccel, pMsg);
692 }
693 };
694
695 typedef CAcceleratorT<false> CAcceleratorHandle;
696 typedef CAcceleratorT<true> CAccelerator;
697
698
699 ///////////////////////////////////////////////////////////////////////////////
700 // CIcon
701
702 template <bool t_bManaged>
703 class CIconT
704 {
705 public:
706 HICON m_hIcon;
707
708 // Constructor/destructor/operators
709 CIconT(HICON hIcon = NULL) : m_hIcon(hIcon)
710 { }
711
712 ~CIconT()
713 {
714 if(t_bManaged && m_hIcon != NULL)
715 ::DestroyIcon(m_hIcon);
716 }
717
718 CIconT<t_bManaged>& operator =(HICON hIcon)
719 {
720 Attach(hIcon);
721 return *this;
722 }
723
724 void Attach(HICON hIcon)
725 {
726 if(t_bManaged && m_hIcon != NULL)
727 ::DestroyIcon(m_hIcon);
728 m_hIcon = hIcon;
729 }
730
731 HICON Detach()
732 {
733 HICON hIcon = m_hIcon;
734 m_hIcon = NULL;
735 return hIcon;
736 }
737
738 operator HICON() const { return m_hIcon; }
739
740 bool IsNull() const { return m_hIcon == NULL; }
741
742 // Create/destroy methods
743 HICON LoadIcon(ATL::_U_STRINGorID icon)
744 {
745 ATLASSERT(m_hIcon == NULL);
746 m_hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
747 return m_hIcon;
748 }
749
750 HICON LoadIcon(ATL::_U_STRINGorID icon, int cxDesired, int cyDesired, UINT fuLoad = 0)
751 {
752 ATLASSERT(m_hIcon == NULL);
753 m_hIcon = (HICON) ::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
754 return m_hIcon;
755 }
756
757 #ifndef _WIN32_WCE
758 HICON LoadOEMIcon(LPCTSTR lpstrIconName)
759 {
760 ATLASSERT(m_hIcon == NULL);
761 ATLASSERT(IsOEMIcon(lpstrIconName));
762 m_hIcon = ::LoadIcon(NULL, lpstrIconName);
763 return m_hIcon;
764 }
765
766 HICON CreateIcon(int nWidth, int nHeight, BYTE cPlanes, BYTE cBitsPixel, CONST BYTE* lpbANDbits, CONST BYTE *lpbXORbits)
767 {
768 ATLASSERT(m_hIcon == NULL);
769 ATLASSERT(lpbANDbits != NULL);
770 ATLASSERT(lpbXORbits != NULL);
771 m_hIcon = ::CreateIcon(ModuleHelper::GetResourceInstance(), nWidth, nHeight, cPlanes, cBitsPixel, lpbANDbits, lpbXORbits);
772 return m_hIcon;
773 }
774
775 HICON CreateIconFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000)
776 {
777 ATLASSERT(m_hIcon == NULL);
778 ATLASSERT(pBits != NULL);
779 m_hIcon = ::CreateIconFromResource(pBits, dwResSize, TRUE, dwVersion);
780 return m_hIcon;
781 }
782
783 HICON CreateIconFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR)
784 {
785 ATLASSERT(m_hIcon == NULL);
786 ATLASSERT(pbBits != NULL);
787 ATLASSERT(cbBits > 0);
788 m_hIcon = ::CreateIconFromResourceEx(pbBits, cbBits, TRUE, dwVersion, cxDesired, cyDesired, uFlags);
789 return m_hIcon;
790 }
791 #endif // !_WIN32_WCE
792
793 HICON CreateIconIndirect(PICONINFO pIconInfo)
794 {
795 ATLASSERT(m_hIcon == NULL);
796 ATLASSERT(pIconInfo != NULL);
797 m_hIcon = ::CreateIconIndirect(pIconInfo);
798 return m_hIcon;
799 }
800
801 #ifndef _WIN32_WCE
802 HICON ExtractIcon(LPCTSTR lpszExeFileName, UINT nIconIndex)
803 {
804 ATLASSERT(m_hIcon == NULL);
805 ATLASSERT(lpszExeFileName != NULL);
806 m_hIcon = ::ExtractIcon(ModuleHelper::GetModuleInstance(), lpszExeFileName, nIconIndex);
807 return m_hIcon;
808 }
809
810 HICON ExtractAssociatedIcon(HINSTANCE hInst, LPTSTR lpIconPath, LPWORD lpiIcon)
811 {
812 ATLASSERT(m_hIcon == NULL);
813 ATLASSERT(lpIconPath != NULL);
814 ATLASSERT(lpiIcon != NULL);
815 m_hIcon = ::ExtractAssociatedIcon(hInst, lpIconPath, lpiIcon);
816 return m_hIcon;
817 }
818 #endif // !_WIN32_WCE
819
820 BOOL DestroyIcon()
821 {
822 ATLASSERT(m_hIcon != NULL);
823 BOOL bRet = ::DestroyIcon(m_hIcon);
824 if(bRet != FALSE)
825 m_hIcon = NULL;
826 return bRet;
827 }
828
829 // Operations
830 #ifndef _WIN32_WCE
831 HICON CopyIcon()
832 {
833 ATLASSERT(m_hIcon != NULL);
834 return ::CopyIcon(m_hIcon);
835 }
836
837 HICON DuplicateIcon()
838 {
839 ATLASSERT(m_hIcon != NULL);
840 return ::DuplicateIcon(NULL, m_hIcon);
841 }
842 #endif // !_WIN32_WCE
843
844 BOOL DrawIcon(HDC hDC, int x, int y)
845 {
846 ATLASSERT(m_hIcon != NULL);
847 #ifndef _WIN32_WCE
848 return ::DrawIcon(hDC, x, y, m_hIcon);
849 #else // CE specific
850 return ::DrawIconEx(hDC, x, y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL);
851 #endif // _WIN32_WCE
852 }
853
854 BOOL DrawIcon(HDC hDC, POINT pt)
855 {
856 ATLASSERT(m_hIcon != NULL);
857 #ifndef _WIN32_WCE
858 return ::DrawIcon(hDC, pt.x, pt.y, m_hIcon);
859 #else // CE specific
860 return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, 0, 0, 0, NULL, DI_NORMAL);
861 #endif // _WIN32_WCE
862 }
863
864 BOOL DrawIconEx(HDC hDC, int x, int y, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
865 {
866 ATLASSERT(m_hIcon != NULL);
867 return ::DrawIconEx(hDC, x, y, m_hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
868 }
869
870 BOOL DrawIconEx(HDC hDC, POINT pt, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
871 {
872 ATLASSERT(m_hIcon != NULL);
873 return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
874 }
875
876 #ifndef _WIN32_WCE
877 BOOL GetIconInfo(PICONINFO pIconInfo) const
878 {
879 ATLASSERT(m_hIcon != NULL);
880 ATLASSERT(pIconInfo != NULL);
881 return ::GetIconInfo(m_hIcon, pIconInfo);
882 }
883
884 #if (_WIN32_WINNT >= 0x0600)
885 BOOL GetIconInfoEx(PICONINFOEX pIconInfo) const
886 {
887 ATLASSERT(m_hIcon != NULL);
888 ATLASSERT(pIconInfo != NULL);
889 return ::GetIconInfoEx(m_hIcon, pIconInfo);
890 }
891 #endif // (_WIN32_WINNT >= 0x0600)
892
893 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
894 HRESULT LoadIconMetric(ATL::_U_STRINGorID icon, int lims)
895 {
896 ATLASSERT(m_hIcon == NULL);
897 USES_CONVERSION;
898 return ::LoadIconMetric(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), lims, &m_hIcon);
899 }
900
901 HRESULT LoadIconWithScaleDown(ATL::_U_STRINGorID icon, int cx, int cy)
902 {
903 ATLASSERT(m_hIcon == NULL);
904 USES_CONVERSION;
905 return ::LoadIconWithScaleDown(ModuleHelper::GetResourceInstance(), T2CW(icon.m_lpstr), cx, cy, &m_hIcon);
906 }
907
908 HRESULT LoadOEMIconMetric(LPCTSTR lpstrIconName, int lims)
909 {
910 ATLASSERT(m_hIcon == NULL);
911 ATLASSERT(IsOEMIcon(lpstrIconName));
912 return ::LoadIconMetric(NULL, (LPCWSTR)lpstrIconName, lims, &m_hIcon);
913 }
914
915 HRESULT LoadOEMIconWithScaleDown(LPCTSTR lpstrIconName, int cx, int cy)
916 {
917 ATLASSERT(m_hIcon == NULL);
918 ATLASSERT(IsOEMIcon(lpstrIconName));
919 USES_CONVERSION;
920 return ::LoadIconWithScaleDown(NULL, (LPCWSTR)lpstrIconName, cx, cy, &m_hIcon);
921 }
922 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
923 #endif // !_WIN32_WCE
924
925 // Helper
926 #ifndef _WIN32_WCE
927 static bool IsOEMIcon(LPCTSTR lpstrIconName)
928 {
929 #if (WINVER >= 0x0600)
930 return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION ||
931 lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO ||
932 lpstrIconName == IDI_SHIELD);
933 #else // !(WINVER >= 0x0600)
934 return (lpstrIconName == IDI_APPLICATION || lpstrIconName == IDI_ASTERISK || lpstrIconName == IDI_EXCLAMATION ||
935 lpstrIconName == IDI_HAND || lpstrIconName == IDI_QUESTION || lpstrIconName == IDI_WINLOGO);
936 #endif // !(WINVER >= 0x0600)
937 }
938 #endif // !_WIN32_WCE
939 };
940
941 typedef CIconT<false> CIconHandle;
942 typedef CIconT<true> CIcon;
943
944
945 ///////////////////////////////////////////////////////////////////////////////
946 // CCursor
947
948 // protect template member from a winuser.h macro
949 #ifdef CopyCursor
950 #undef CopyCursor
951 #endif
952
953 template <bool t_bManaged>
954 class CCursorT
955 {
956 public:
957 HCURSOR m_hCursor;
958
959 // Constructor/destructor/operators
960 CCursorT(HCURSOR hCursor = NULL) : m_hCursor(hCursor)
961 { }
962
963 ~CCursorT()
964 {
965 if(t_bManaged && m_hCursor != NULL)
966 DestroyCursor();
967 }
968
969 CCursorT<t_bManaged>& operator =(HCURSOR hCursor)
970 {
971 Attach(hCursor);
972 return *this;
973 }
974
975 void Attach(HCURSOR hCursor)
976 {
977 if(t_bManaged && m_hCursor != NULL)
978 DestroyCursor();
979 m_hCursor = hCursor;
980 }
981
982 HCURSOR Detach()
983 {
984 HCURSOR hCursor = m_hCursor;
985 m_hCursor = NULL;
986 return hCursor;
987 }
988
989 operator HCURSOR() const { return m_hCursor; }
990
991 bool IsNull() const { return m_hCursor == NULL; }
992
993 // Create/destroy methods
994 HCURSOR LoadCursor(ATL::_U_STRINGorID cursor)
995 {
996 ATLASSERT(m_hCursor == NULL);
997 m_hCursor = ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr);
998 return m_hCursor;
999 }
1000
1001 HCURSOR LoadSysCursor(LPCTSTR lpstrCursorName)
1002 {
1003 ATLASSERT(m_hCursor == NULL);
1004 #if (WINVER >= 0x0500)
1005 ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT ||
1006 lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE ||
1007 lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW ||
1008 lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL ||
1009 lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP ||
1010 lpstrCursorName == IDC_HAND);
1011 #else // !(WINVER >= 0x0500)
1012 ATLASSERT(lpstrCursorName == IDC_ARROW || lpstrCursorName == IDC_IBEAM || lpstrCursorName == IDC_WAIT ||
1013 lpstrCursorName == IDC_CROSS || lpstrCursorName == IDC_UPARROW || lpstrCursorName == IDC_SIZE ||
1014 lpstrCursorName == IDC_ICON || lpstrCursorName == IDC_SIZENWSE || lpstrCursorName == IDC_SIZENESW ||
1015 lpstrCursorName == IDC_SIZEWE || lpstrCursorName == IDC_SIZENS || lpstrCursorName == IDC_SIZEALL ||
1016 lpstrCursorName == IDC_NO || lpstrCursorName == IDC_APPSTARTING || lpstrCursorName == IDC_HELP);
1017 #endif // !(WINVER >= 0x0500)
1018 m_hCursor = ::LoadCursor(NULL, lpstrCursorName);
1019 return m_hCursor;
1020 }
1021
1022 // deprecated
1023 HCURSOR LoadOEMCursor(LPCTSTR lpstrCursorName)
1024 {
1025 return LoadSysCursor(lpstrCursorName);
1026 }
1027
1028 HCURSOR LoadCursor(ATL::_U_STRINGorID cursor, int cxDesired, int cyDesired, UINT fuLoad = 0)
1029 {
1030 ATLASSERT(m_hCursor == NULL);
1031 m_hCursor = (HCURSOR) ::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
1032 return m_hCursor;
1033 }
1034
1035 #ifndef _WIN32_WCE
1036 HCURSOR LoadCursorFromFile(LPCTSTR pstrFilename)
1037 {
1038 ATLASSERT(m_hCursor == NULL);
1039 ATLASSERT(pstrFilename != NULL);
1040 m_hCursor = ::LoadCursorFromFile(pstrFilename);
1041 return m_hCursor;
1042 }
1043 #endif // !_WIN32_WCE
1044
1045 #if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
1046 HCURSOR CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, CONST VOID *pvANDPlane, CONST VOID *pvXORPlane)
1047 {
1048 ATLASSERT(m_hCursor == NULL);
1049 m_hCursor = ::CreateCursor(ModuleHelper::GetResourceInstance(), xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane);
1050 return m_hCursor;
1051 }
1052 #endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
1053
1054 #ifndef _WIN32_WCE
1055 HCURSOR CreateCursorFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000)
1056 {
1057 ATLASSERT(m_hCursor == NULL);
1058 ATLASSERT(pBits != NULL);
1059 m_hCursor = (HCURSOR)::CreateIconFromResource(pBits, dwResSize, FALSE, dwVersion);
1060 return m_hCursor;
1061 }
1062
1063 HCURSOR CreateCursorFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR)
1064 {
1065 ATLASSERT(m_hCursor == NULL);
1066 ATLASSERT(pbBits != NULL);
1067 ATLASSERT(cbBits > 0);
1068 m_hCursor = (HCURSOR)::CreateIconFromResourceEx(pbBits, cbBits, FALSE, dwVersion, cxDesired, cyDesired, uFlags);
1069 return m_hCursor;
1070 }
1071 #endif // !_WIN32_WCE
1072
1073 BOOL DestroyCursor()
1074 {
1075 ATLASSERT(m_hCursor != NULL);
1076 #if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
1077 BOOL bRet = ::DestroyCursor(m_hCursor);
1078 if(bRet != FALSE)
1079 m_hCursor = NULL;
1080 return bRet;
1081 #else // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))))
1082 ATLTRACE2(atlTraceUI, 0, _T("Warning: This version of Windows CE does not have ::DestroyCursor()\n"));
1083 return FALSE;
1084 #endif // !(!defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP))))
1085 }
1086
1087 // Operations
1088 #ifndef _WIN32_WCE
1089 HCURSOR CopyCursor()
1090 {
1091 ATLASSERT(m_hCursor != NULL);
1092 return (HCURSOR)::CopyIcon((HICON)m_hCursor);
1093 }
1094 #endif // !_WIN32_WCE
1095
1096 #if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
1097 BOOL GetCursorInfo(LPCURSORINFO pCursorInfo)
1098 {
1099 ATLASSERT(m_hCursor != NULL);
1100 ATLASSERT(pCursorInfo != NULL);
1101 return ::GetCursorInfo(pCursorInfo);
1102 }
1103 #endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)
1104 };
1105
1106 typedef CCursorT<false> CCursorHandle;
1107 typedef CCursorT<true> CCursor;
1108
1109
1110 ///////////////////////////////////////////////////////////////////////////////
1111 // CResource - Wraps a generic Windows resource.
1112 // Use it with custom resource types other than the
1113 // standard RT_CURSOR, RT_BITMAP, etc.
1114
1115 class CResource
1116 {
1117 public:
1118 HGLOBAL m_hGlobal;
1119 HRSRC m_hResource;
1120
1121 // Constructor/destructor
1122 CResource() : m_hGlobal(NULL), m_hResource(NULL)
1123 { }
1124
1125 ~CResource()
1126 {
1127 Release();
1128 }
1129
1130 // Load methods
1131 bool Load(ATL::_U_STRINGorID Type, ATL::_U_STRINGorID ID)
1132 {
1133 ATLASSERT(m_hResource == NULL);
1134 ATLASSERT(m_hGlobal == NULL);
1135
1136 m_hResource = ::FindResource(ModuleHelper::GetResourceInstance(), ID.m_lpstr, Type.m_lpstr);
1137 if(m_hResource == NULL)
1138 return false;
1139
1140 m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource);
1141 if(m_hGlobal == NULL)
1142 {
1143 m_hResource = NULL;
1144 return false;
1145 }
1146
1147 return true;
1148 }
1149
1150 #ifndef _WIN32_WCE
1151 bool LoadEx(ATL::_U_STRINGorID ID, ATL::_U_STRINGorID Type, WORD wLanguage)
1152 {
1153 ATLASSERT(m_hResource == NULL);
1154 ATLASSERT(m_hGlobal == NULL);
1155
1156 m_hResource = ::FindResourceEx(ModuleHelper::GetResourceInstance(), Type.m_lpstr, ID.m_lpstr, wLanguage);
1157 if(m_hResource == NULL)
1158 return false;
1159
1160 m_hGlobal = ::LoadResource(ModuleHelper::GetResourceInstance(), m_hResource);
1161 if(m_hGlobal == NULL)
1162 {
1163 m_hResource = NULL;
1164 return false;
1165 }
1166
1167 return true;
1168 }
1169 #endif // !_WIN32_WCE
1170
1171 // Misc. operations
1172 DWORD GetSize() const
1173 {
1174 ATLASSERT(m_hResource != NULL);
1175 return ::SizeofResource(ModuleHelper::GetResourceInstance(), m_hResource);
1176 }
1177
1178 LPVOID Lock()
1179 {
1180 ATLASSERT(m_hResource != NULL);
1181 ATLASSERT(m_hGlobal != NULL);
1182 LPVOID pVoid = ::LockResource(m_hGlobal);
1183 ATLASSERT(pVoid != NULL);
1184 return pVoid;
1185 }
1186
1187 void Release()
1188 {
1189 if(m_hGlobal != NULL)
1190 {
1191 FreeResource(m_hGlobal);
1192 m_hGlobal = NULL;
1193 m_hResource = NULL;
1194 }
1195 }
1196 };
1197
1198
1199 ///////////////////////////////////////////////////////////////////////////////
1200 // Toolbar resource descriptor
1201
1202 struct _AtlToolBarData
1203 {
1204 WORD wVersion;
1205 WORD wWidth;
1206 WORD wHeight;
1207 WORD wItemCount;
1208
1209 WORD* items()
1210 { return (WORD*)(this+1); }
1211 };
1212
1213
1214 ///////////////////////////////////////////////////////////////////////////////
1215 // Global functions for loading resources
1216
1217 inline HACCEL AtlLoadAccelerators(ATL::_U_STRINGorID table)
1218 {
1219 return ::LoadAccelerators(ModuleHelper::GetResourceInstance(), table.m_lpstr);
1220 }
1221
1222 inline HMENU AtlLoadMenu(ATL::_U_STRINGorID menu)
1223 {
1224 return ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr);
1225 }
1226
1227 inline HBITMAP AtlLoadBitmap(ATL::_U_STRINGorID bitmap)
1228 {
1229 return ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr);
1230 }
1231
1232 #ifdef OEMRESOURCE
1233 inline HBITMAP AtlLoadSysBitmap(ATL::_U_STRINGorID bitmap)
1234 {
1235 #ifdef _DEBUG
1236 WORD wID = LOWORD(bitmap.m_lpstr);
1237 ATLASSERT(wID >= 32734 && wID <= 32767);
1238 #endif // _DEBUG
1239 return ::LoadBitmap(NULL, bitmap.m_lpstr);
1240 }
1241 #endif // OEMRESOURCE
1242
1243 inline HCURSOR AtlLoadCursor(ATL::_U_STRINGorID cursor)
1244 {
1245 return ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr);
1246 }
1247
1248 inline HCURSOR AtlLoadSysCursor(LPCTSTR lpCursorName)
1249 {
1250 #if (WINVER >= 0x0500)
1251 ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT ||
1252 lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE ||
1253 lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW ||
1254 lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL ||
1255 lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP ||
1256 lpCursorName == IDC_HAND);
1257 #else // !(WINVER >= 0x0500)
1258 ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT ||
1259 lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE ||
1260 lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW ||
1261 lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL ||
1262 lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP);
1263 #endif // !(WINVER >= 0x0500)
1264 return ::LoadCursor(NULL, lpCursorName);
1265 }
1266
1267 inline HICON AtlLoadIcon(ATL::_U_STRINGorID icon)
1268 {
1269 return ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr);
1270 }
1271
1272 #ifndef _WIN32_WCE
1273 inline HICON AtlLoadSysIcon(LPCTSTR lpIconName)
1274 {
1275 #if (WINVER >= 0x0600)
1276 ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION ||
1277 lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO ||
1278 lpIconName == IDI_SHIELD);
1279 #else // !(WINVER >= 0x0600)
1280 ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION ||
1281 lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO);
1282 #endif // !(WINVER >= 0x0600)
1283 return ::LoadIcon(NULL, lpIconName);
1284 }
1285 #endif // !_WIN32_WCE
1286
1287 inline HBITMAP AtlLoadBitmapImage(ATL::_U_STRINGorID bitmap, UINT fuLoad = LR_DEFAULTCOLOR)
1288 {
1289 return (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, IMAGE_BITMAP, 0, 0, fuLoad);
1290 }
1291
1292 inline HCURSOR AtlLoadCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
1293 {
1294 return (HCURSOR)::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
1295 }
1296
1297 inline HICON AtlLoadIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
1298 {
1299 return (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
1300 }
1301
1302 #ifdef OEMRESOURCE
1303 inline HBITMAP AtlLoadSysBitmapImage(WORD wBitmapID, UINT fuLoad = LR_DEFAULTCOLOR)
1304 {
1305 ATLASSERT(wBitmapID >= 32734 && wBitmapID <= 32767);
1306 ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file
1307 return (HBITMAP)::LoadImage(NULL, MAKEINTRESOURCE(wBitmapID), IMAGE_BITMAP, 0, 0, fuLoad);
1308 }
1309 #endif // OEMRESOURCE
1310
1311 inline HCURSOR AtlLoadSysCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
1312 {
1313 #ifdef _DEBUG
1314 WORD wID = LOWORD(cursor.m_lpstr);
1315 ATLASSERT((wID >= 32512 && wID <= 32516) || (wID >= 32640 && wID <= 32648) || (wID == 32650) || (wID == 32651));
1316 ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file
1317 #endif // _DEBUG
1318 return (HCURSOR)::LoadImage(NULL, cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
1319 }
1320
1321 inline HICON AtlLoadSysIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0)
1322 {
1323 #ifdef _DEBUG
1324 WORD wID = LOWORD(icon.m_lpstr);
1325 ATLASSERT(wID >= 32512 && wID <= 32517);
1326 ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file
1327 #endif // _DEBUG
1328 return (HICON)::LoadImage(NULL, icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
1329 }
1330
1331 #if (_ATL_VER < 0x0700)
1332 inline int AtlLoadString(UINT uID, LPTSTR lpBuffer, int nBufferMax)
1333 {
1334 return ::LoadString(ModuleHelper::GetResourceInstance(), uID, lpBuffer, nBufferMax);
1335 }
1336 #else
1337
1338 using ATL::AtlLoadString;
1339
1340 #endif // (_ATL_VER < 0x0700)
1341
1342 #ifdef _WIN32_WCE // CE only direct access to the resource
1343 inline LPCTSTR AtlLoadString(UINT uID)
1344 {
1345 LPCTSTR s = (LPCTSTR)::LoadString(ModuleHelper::GetResourceInstance(), uID, NULL, 0);
1346 #ifdef DEBUG // Check for null-termination
1347 if(s != NULL)
1348 // Note: RC -n <file.rc> compiles null-terminated resource strings
1349 ATLASSERT(s[*((WORD*)s -1) - 1] == L'\0');
1350 #endif
1351 return s;
1352 }
1353 #endif // _WIN32_WCE
1354
1355 inline bool AtlLoadString(UINT uID, BSTR& bstrText)
1356 {
1357 USES_CONVERSION;
1358 ATLASSERT(bstrText == NULL);
1359
1360 LPTSTR lpstrText = NULL;
1361 int nRes = 0;
1362 for(int nLen = 256; ; nLen *= 2)
1363 {
1364 ATLTRY(lpstrText = new TCHAR[nLen]);
1365 if(lpstrText == NULL)
1366 break;
1367 nRes = ::LoadString(ModuleHelper::GetResourceInstance(), uID, lpstrText, nLen);
1368 if(nRes < nLen - 1)
1369 break;
1370 delete [] lpstrText;
1371 lpstrText = NULL;
1372 }
1373
1374 if(lpstrText != NULL)
1375 {
1376 if(nRes != 0)
1377 bstrText = ::SysAllocString(T2OLE(lpstrText));
1378 delete [] lpstrText;
1379 }
1380
1381 return (bstrText != NULL) ? true : false;
1382 }
1383
1384 }; // namespace WTL
1385
1386 #endif // __ATLUSER_H__
+0
-2981
src/third_party/wtl/Include/atlwince.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLWINCE_H__
9 #define __ATLWINCE_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlwince.h requires atlapp.h to be included first
15 #endif
16
17 #ifndef __ATLWIN_H__
18 #error atlwince.h requires atlwin.h to be included first
19 #endif
20
21 #ifndef _WIN32_WCE
22 #error atlwince.h compiles under Windows CE only
23 #endif
24
25 #if (_WIN32_WCE < 300)
26 #error atlwince.h requires Windows CE 3.0 or higher.
27 #endif
28
29 #if defined(WIN32_PLATFORM_WFSP) && _MSC_VER < 1400 // EVC compiling SmartPhone code
30 #if (WIN32_PLATFORM_WFSP < 200)
31 #error atlwince.h requires Smartphone 2003 or higher
32 #endif
33 #endif // WIN32_PLATFORM_WFSP
34
35 #if defined(WIN32_PLATFORM_PSPC) && _MSC_VER < 1400 // EVC compiling Pocket PC code
36 #if (WIN32_PLATFORM_PSPC < 310)
37 #error atlwince.h requires Pocket PC 2002 or higher
38 #endif
39 #endif // WIN32_PLATFORM_PSPC
40
41 #if !defined(_AYGSHELL_H_) && !defined(__AYGSHELL_H__)
42 #error atlwince.h requires aygshell.h to be included first
43 #else
44 #if defined(WIN32_PLATFORM_WFSP) && !defined(_TPCSHELL_H_)
45 #error SmartPhone dialog classes require tpcshell.h to be included first
46 #endif
47 #endif
48
49 #if (_MSC_VER >= 1400) // VS2005
50 #include <DeviceResolutionAware.h>
51 #define _WTL_CE_DRA
52 #endif // (_MSC_VER >= 1400)
53
54 #if !defined(_WTL_CE_NO_DIALOGS) && !defined(__ATLFRAME_H__)
55 #error Orientation aware dialog classes require atlframe.h to be included first
56 #endif
57
58 #if !defined(_WTL_CE_NO_APPWINDOW) && !defined(__ATLFRAME_H__)
59 #error Application window class require atlframe.h to be included first
60 #endif
61
62 #if !defined(_WTL_CE_NO_ZOOMSCROLL) && !defined(__ATLSCRL_H__)
63 #error ZoomScroll implementation requires atlscrl.h to be included first
64 #endif
65
66 #if !defined(_WTL_CE_NO_ZOOMSCROLL)
67 #if !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES)))
68 #error ZoomScroll requires _WTL_NO_WTYPES not to be defined and either atlmisc.h or atltypes.h to be included first
69 #endif // !(defined(__ATLTYPES_H__) || (defined(__ATLMISC_H__) && !defined(_WTL_NO_WTYPES)))
70 #endif // !defined(_WTL_CE_NO_ZOOMSCROLL)
71
72 #if !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC)
73 #define _WTL_CE_NO_CONTROLS
74 #endif // !defined(WIN32_PLATFORM_WFSP) && !defined(WIN32_PLATFORM_PSPC)
75
76 #ifndef _WTL_CE_NO_CONTROLS
77 #ifndef __ATLCTRLS_H__
78 #error The PPC/SmartPhone controls classes require atlctrls.h to be included first
79 #endif
80
81 #include <htmlctrl.h>
82 #pragma comment(lib, "htmlview.lib")
83
84 #include <voicectl.h>
85 #pragma comment(lib, "voicectl.lib")
86
87 #ifdef WIN32_PLATFORM_PSPC
88 #include <richink.h>
89 #pragma comment(lib, "richink.lib")
90
91 #include <inkx.h>
92 #pragma comment(lib, "inkx.lib")
93
94 #include <doclist.h>
95 #pragma comment(lib, "doclist.lib")
96 #endif
97 #endif
98
99
100 ///////////////////////////////////////////////////////////////////////////////
101 // Classes in this file:
102 //
103 // CStdDialogBase<T, t_shidiFlags, t_bModal> : Standard PPC/SmartPhone dialog base class
104 // CStdDialogImplBase - Base implementation of standard dialog
105 // CStdDialogImpl<T, t_shidiFlags, t_bModal> : Standard dialog implementation
106 // CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog
107 // CStdAxDialogImpl<T, t_shidiFlags, t_bModal> : Standard AxDialog implementation
108 // CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags> : Standard simple dialog
109 // CStdDialogResizeImplBase - Base implementation of orientation resizing standard dialog
110 // CStdDialogResizeImpl<T, t_shidiFlags, t_bModal> : Orientation resizing standard dialog implementation
111 // CStdAxDialogResizeImpl - implementation of orientation resizing standard AxDialog
112 // CStdSimpleDialogResizeImpl<T, t_wDlgTemplateID, t_shidiFlags> : Standard resizing simple dialog implementation
113 // CStdOrientedDialogBase - Oriented PPC standard dialog base class
114 // CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation
115 // CStdOrientedDialogImpl<T, t_shidiFlags, t_bModal> : Oriented PPC standard dialog implementation
116 // CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation
117 // CStdSimpleOrientedDialog<t_wDlgTemplateID, t_wDlgLandscapeID, t_shidiFlags> : Standard simple orientable dialog
118 //
119 // CAppInfoBase : Helper for application state save/restore to registry
120 // CAppInfoT<T> : CAppInfoBase constructed from a CAppWindow<T>
121 // CAppWindowBase<T> : Base class for PPC/SmartPhone well-behaved application window or dialog
122 // CAppWindow<T> : PPC/SmartPhone well-behaved application window class
123 // CAppDialog<T> : PPC/SmartPhone well-behaved application dialog class
124 // CAppStdDialogImplBase - Base implementation of standard application dialogs
125 // CAppStdDialogImpl<T, t_shidiFlags, t_bModal> : Implementation of standard application dialog
126 // CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog
127 // CAppStdAxDialogImpl - Implementation of standard application AxDialog
128 // CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog
129 // CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog
130 // CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog
131 //
132 // CFullScreenFrame<T, t_bHasSip> : Full screen frame class
133 //
134 // CZoomScrollImpl<T> : WinCE zooming implementation
135 //
136 // CBottomTabViewImpl<T, TBase, TWinTraits> - CBottomTabView
137 // CHtmlCtrlT<TBase> - CHtmlCtrl
138 // CRichInkCtrlT<TBase> - CRichInkCtrl
139 // CInkXCtrlT<TBase> - CInkXCtrl
140 // CVoiceRecorderCtrlT<TBase> - CVoiceRecorderCtrl
141 // CDocListCtrlT<TBase> - CDocListCtrl
142 // CCapEditT<TBase> - CCapEdit
143 // CTTStaticT<TBase> - CTTStatic
144 // CTTButtonT<TBase> - CTTButton
145 //
146 // CSpinCtrlT<TBase> - CSpinCtrl : SmartPhone specific UpDown control
147 // CSpinned<TBase, t_bExpandOnly> : SmartPhone association of control and Spin
148 // CSpinListBox : SmartPhone spinned ListBox control
149 // CExpandListBox : SmartPhone expandable ListBox control
150 // CExpandEdit : SmartPhone expandable Edit control
151 // CExpandCapEdit : SmartPhone expandable CapEdit control
152 //
153 // Global functions:
154 // AtlCreateMenuBar()
155 // AtlCreateEmptyMenuBar()
156 // AtlIsEditFocus()
157 // AtlActivateBackKey()
158
159 namespace WTL
160 {
161
162 ///////////////////////////////////////////////////////////////////////////////
163 // MenuBar creation functions for property sheets and dialogs
164 // Frame windows use CreateSimpleCEMenuBar
165
166 inline HWND AtlCreateMenuBar(SHMENUBARINFO& mbi)
167 {
168 ATLASSERT(::IsWindow(mbi.hwndParent));
169 ATLVERIFY(::SHCreateMenuBar(&mbi) != FALSE);
170 return mbi.hwndMB;
171 };
172
173 inline HWND AtlCreateMenuBar(HWND hWnd, UINT nToolBarId = ATL_IDW_TOOLBAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0, COLORREF clrBk = 0)
174 {
175 SHMENUBARINFO mbi = { sizeof(mbi), hWnd, dwFlags, nToolBarId, ModuleHelper::GetResourceInstance(), nBmpId, cBmpImages, 0, clrBk };
176 return AtlCreateMenuBar(mbi);
177 }
178
179 inline HWND AtlCreateEmptyMenuBar(HWND hWnd, bool bSip = true)
180 {
181 SHMENUBARINFO embi = { sizeof(SHMENUBARINFO), hWnd, SHCMBF_EMPTYBAR };
182 if (!bSip)
183 embi.dwFlags |= SHCMBF_HIDESIPBUTTON;
184
185 return AtlCreateMenuBar(embi);
186 }
187
188 ///////////////////////////////////////////////////////////////////////////////
189 // Helper functions for SmartPhone back key handling
190
191 inline bool AtlIsEditFocus()
192 {
193 ATL::CWindow wCtrl = GetFocus();
194 if (wCtrl.IsWindow())
195 {
196 TCHAR szClassName[8] = {0};
197 ATLVERIFY(::GetClassName(wCtrl.m_hWnd, szClassName, 8));
198 return !_tcscmp(szClassName, _T("Edit")) || !_tcscmp(szClassName, WC_CAPEDIT);
199 }
200 return false;
201 }
202
203 #if defined WIN32_PLATFORM_WFSP
204 inline void AtlActivateBackKey(HWND hMenuBar)
205 {
206 ATLASSERT(::IsWindow(hMenuBar));
207 ::SendMessage(hMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK,
208 MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
209 }
210 #endif // WIN32_PLATFORM_WFSP
211
212 // --- Standard PPC/SmartPhone dialogs ---
213
214 #ifndef _WTL_CE_NO_DIALOGS
215
216 ///////////////////////////////////////////////////////////////////////////////
217 // CStdDialogBase - base class for standard PPC/SmartPhone dialogs
218
219 #define WTL_STD_SHIDIF SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN
220 #define WTL_SP_SHIDIF SHIDIF_SIZEDLGFULLSCREEN
221
222 // Title setting macros
223 #define WTL_DLG_TITLEHEIGHT(iHeight) static const int GetTitleHeight(){return iHeight;}
224 #define WTL_DLG_NOTITLE WTL_DLG_TITLEHEIGHT(0)
225
226 ///////////////////////////////////////////////////////////////////////////////
227 // CStdDialogBase - Base class for standard PPC/SmartPhone dialog
228
229 template <class T, UINT t_shidiFlags, bool t_bModal = true>
230 class CStdDialogBase
231 {
232 public:
233 #ifdef WIN32_PLATFORM_PSPC
234 // Pocket PC only Dialog title handling
235 const int nTitleHeight;
236
237 CStdDialogBase() : nTitleHeight(T::GetTitleHeight())
238 { }
239
240 // Overloads
241 BOOL GetClientRect(LPRECT lpRect)
242 {
243 T* pT = static_cast<T*>(this);
244 ATLASSERT(pT->IsWindow());
245 BOOL bRes = ::GetClientRect(pT->m_hWnd, lpRect);
246 if (nTitleHeight)
247 lpRect->top += nTitleHeight + 1;
248 return bRes;
249 }
250
251 BOOL SetWindowText(LPCTSTR lpszString)
252 {
253 T* pT = static_cast<T*>(this);
254 ATLASSERT(pT->IsWindow());
255 BOOL bRes = ::SetWindowText(pT->m_hWnd, lpszString);
256 if (nTitleHeight != 0)
257 pT->DoPaintTitle();
258 return bRes;
259 }
260
261 // Overrideables
262 static const int GetTitleHeight()
263 {
264 #ifdef _WTL_CE_DRA
265 return DRA::SCALEY(24);
266 #else // !_WTL_CE_DRA
267 CWindowDC dc(NULL);
268 return dc.GetDeviceCaps(LOGPIXELSY) >> 2; // LOGPIXELSY * 24 / 96,
269 #endif // !_WTL_CE_DRA
270 }
271
272 // Title painting
273 bool DoPaintTitle()
274 {
275 T* pT = static_cast<T*>(this);
276 ATLASSERT(pT->IsWindow());
277 TCHAR sTitle[48] = { 0 };
278
279 // Preparation
280 CPaintDC dc(pT->m_hWnd);
281 CFont fontTitle = AtlCreateBoldFont();
282 CFontHandle fontOld = dc.SelectFont(fontTitle);
283 dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHT));
284 int nLen = pT->GetWindowText(sTitle, 48);
285 int nWidth = dc.GetDeviceCaps(HORZRES);
286
287 // Display title text
288 RECT rTitle = { 0, 0, nWidth, nTitleHeight };
289 dc.FillRect(&rTitle, COLOR_3DHIGHLIGHT);
290 #ifdef _WTL_CE_DRA
291 rTitle.left = DRA::SCALEX(8);
292 #else // !_WTL_CE_DRA
293 rTitle.left = nTitleHeight / 3; // 8 == 24 / 3
294 #endif // !_WTL_CE_DRA
295 dc.DrawText(sTitle, nLen, &rTitle, DT_VCENTER | DT_SINGLELINE);
296 dc.SelectFont(fontOld);
297
298 // Draw bottom line, 2 pixels thick if HI_RES_AWARE
299 CPenHandle penOld = dc.SelectStockPen(BLACK_PEN);
300 POINT line[4] = {{0, nTitleHeight}, {nWidth, nTitleHeight}, {0, nTitleHeight - 1}, {nWidth, nTitleHeight - 1}};
301
302 #ifdef _WTL_CE_DRA
303 int nSeg = DRA::SCALEY(1);
304 #else // !_WTL_CE_DRA
305 int nSeg = nTitleHeight / 24;
306 #endif // !_WTL_CE_DRA
307
308 dc.Polyline(line, nSeg <= 2 ? nSeg * 2 : 4);
309 dc.SelectPen(penOld);
310
311 return false;
312 }
313
314 // Title preparation: move the dialog controls down to make room for title
315 void DialogTitleInit()
316 {
317 T* pT = static_cast<T*>(this);
318 ATLASSERT(pT->IsWindow());
319
320 ATL::CWindow wCtl = pT->GetWindow(GW_CHILD);
321 while (wCtl.IsWindow())
322 {
323 RECT rCtl = { 0 };
324 wCtl.GetWindowRect(&rCtl);
325 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rCtl, 2);
326 ::OffsetRect(&rCtl, 0, nTitleHeight);
327 wCtl.MoveWindow(&rCtl, FALSE);
328 wCtl = wCtl.GetWindow(GW_HWNDNEXT);
329 }
330 }
331
332 // SIP management
333 void DoSipInfo()
334 {
335 T* pT = static_cast<T*>(this);
336 ATLASSERT(pT->IsWindow());
337
338 SIPINFO si = {sizeof(SIPINFO)};
339 SipGetInfo(&si);
340 if ((si.fdwFlags & SIPF_ON) ^ SIPF_ON)
341 si.rcVisibleDesktop.bottom = si.rcSipRect.bottom;
342 pT->MoveWindow(&si.rcVisibleDesktop, FALSE);
343 }
344
345 // Title painting handler
346 LRESULT OnPaintTitle(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
347 {
348 T* pT = static_cast<T*>(this);
349 return bHandled = nTitleHeight ? pT->DoPaintTitle() : FALSE;
350 }
351
352 // SIP handler
353 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
354 {
355 T* pT = static_cast<T*>(this);
356 if (wParam == SPI_SETSIPINFO)
357 {
358 pT->DoSipInfo();
359 return TRUE;
360 }
361 return bHandled = FALSE;
362 }
363
364 #elif defined WIN32_PLATFORM_WFSP
365 // SmartPhone VK_TBACK key standard management
366 LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
367 {
368 T* pT = static_cast<T*>(this);
369 const UINT uModif = (UINT)LOWORD(lParam);
370 const UINT uVirtKey = (UINT)HIWORD(lParam);
371
372 if(uVirtKey == VK_TBACK)
373 if (AtlIsEditFocus())
374 ::SHSendBackToFocusWindow(uMsg, wParam, lParam);
375 else if (uModif & MOD_KEYUP)
376 pT->StdCloseDialog(IDCANCEL);
377 return 1;
378 }
379
380 // SmartPhone MenuBar and VK_TBACK key initialization
381 void StdSPInit()
382 {
383 T* pT = static_cast<T*>(this);
384 HWND hMenuBar = ::SHFindMenuBar(pT->m_hWnd);
385
386 if (!hMenuBar && (t_shidiFlags & SHIDIF_DONEBUTTON))
387 hMenuBar = CreateMenuBar(ATL_IDM_MENU_DONE);
388
389 if(hMenuBar != NULL)
390 AtlActivateBackKey(hMenuBar);
391 }
392
393 void SetStaticBold()
394 {
395 T* pT = static_cast<T*>(this);
396 ATLASSERT(pT->IsWindow());
397
398 CFontHandle fontBold = AtlCreateBoldFont(pT->GetFont());
399
400 ATL::CWindow wCtl = pT->GetWindow(GW_CHILD);
401
402 while (wCtl.IsWindow())
403 {
404 if ((short int)wCtl.GetDlgCtrlID() == IDC_STATIC)
405 wCtl.SetFont(fontBold);
406 wCtl = wCtl.GetWindow(GW_HWNDNEXT);
407 }
408 }
409 #endif // WIN32_PLATFORM_WFSP
410
411 // Platform dependant initialization
412 void StdPlatformInit()
413 {
414 T* pT = static_cast<T*>(this);
415 #ifdef WIN32_PLATFORM_PSPC // Pocket PC title initialization
416 if (nTitleHeight != 0)
417 pT->DialogTitleInit();
418 #elif defined(WIN32_PLATFORM_WFSP)
419 pT->StdSPInit();
420 SetStaticBold();
421 #endif // WIN32_PLATFORM_WFSP
422 }
423
424 // Menu bar creation
425 HWND CreateMenuBar(UINT uiMB = T::IDD, int nBmpImages = 0)
426 {
427 T* pT = static_cast<T*>(this);
428 return AtlCreateMenuBar(pT->m_hWnd, uiMB, 0, nBmpImages ? uiMB : 0, nBmpImages);
429 }
430
431 // Dialog closing
432 void StdCloseDialog(WORD wID)
433 {
434 T* pT = static_cast<T*>(this);
435 if (t_bModal)
436 ::EndDialog(pT->m_hWnd, wID);
437 else
438 pT->DestroyWindow();
439 }
440
441 // Shell dialog layout initialization
442 void StdShidInit()
443 {
444 T* pT = static_cast<T*>(this);
445 SHINITDLGINFO shidi = { SHIDIM_FLAGS, pT->m_hWnd, t_shidiFlags };
446 ::SHInitDialog(&shidi);
447 }
448
449 // IDC_INFOSTATIC background setting
450 LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
451 {
452 if (::GetDlgCtrlID((HWND)lParam) == IDC_INFOSTATIC)
453 {
454 ::SetBkMode((HDC)wParam, TRANSPARENT);
455 return (LRESULT)::GetSysColorBrush(COLOR_INFOBK);
456 }
457 return bHandled = FALSE;
458 }
459
460 // Menu dialog ending
461 LRESULT OnMenuClose(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
462 {
463 T* pT = static_cast<T*>(this);
464 pT->StdCloseDialog((WORD)(wID - ID_MENU_OK + IDOK));
465 return 0;
466 }
467
468 // Standard dialog ending: may be used with any command
469 LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
470 {
471 T* pT = static_cast<T*>(this);
472 pT->StdCloseDialog(wID);
473 return 0;
474 }
475 };
476
477
478 ///////////////////////////////////////////////////////////////////////////////
479 // CStdDialogImplBase - Base implementation of standard PPC/SmartPhone dialog
480
481 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true, class TBase = ATL::CDialogImpl< T > >
482 class ATL_NO_VTABLE CStdDialogImplBase :
483 public TBase,
484 public CStdDialogBase<T, t_shidiFlags, t_bModal>
485 {
486 public:
487 #ifdef WIN32_PLATFORM_PSPC
488 BOOL GetClientRect(LPRECT lpRect)
489 {
490 return CStdDialogBase<T, t_shidiFlags, t_bModal>::GetClientRect(lpRect);
491 }
492
493 BOOL SetWindowText(LPCTSTR lpszString)
494 {
495 return CStdDialogBase<T, t_shidiFlags, t_bModal>::SetWindowText(lpszString);
496 }
497 #endif
498
499 BEGIN_MSG_MAP(CStdDialogImplBase)
500 #ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP
501 MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
502 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
503 #elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
504 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
505 #endif
506 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
507 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
508 COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
509 COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
510 END_MSG_MAP()
511
512 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
513 {
514 T* pT = static_cast<T*>(this);
515 ATLASSERT(t_bModal == pT->m_bModal);
516 pT->StdPlatformInit();
517 pT->StdShidInit();
518 return bHandled = FALSE;
519 }
520 };
521
522 ///////////////////////////////////////////////////////////////////////////////
523 // CStdDialogImpl - implementation of standard PPC/SmartPhone dialog
524
525 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
526 class ATL_NO_VTABLE CStdDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal>
527 {};
528
529 ///////////////////////////////////////////////////////////////////////////////
530 // CStdIndirectDialogImpl - implementation of standard indirect PPC/SmartPhone dialog
531
532 #if defined __ATLDLGS_H__
533
534 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true>
535 class ATL_NO_VTABLE CStdIndirectDialogImpl :
536 public CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl<T, t_shidiFlags, t_bModal> >
537 {
538 public:
539 typedef CIndirectDialogImpl< T, CMemDlgTemplate, CStdDialogImpl<T, t_shidiFlags, t_bModal> > _baseClass;
540 typedef CStdDialogImpl<T, t_shidiFlags, t_bModal> _baseStd;
541
542 void CheckStyle()
543 {
544 // Mobile devices don't support DLGTEMPLATEEX
545 ATLASSERT(!m_Template.IsTemplateEx());
546
547 // Standard dialogs need only DS_CENTER
548 DWORD &dwStyle = m_Template.GetTemplatePtr()->style;
549 if (dwStyle & DS_CENTER)
550 if(t_bModal)
551 {
552 ATLASSERT((dwStyle & WS_CHILD) != WS_CHILD);
553 dwStyle |= WS_POPUP;
554 }
555 else
556 {
557 if((dwStyle & WS_CHILD) != WS_CHILD)
558 dwStyle |= WS_POPUP;
559 }
560 }
561
562 INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
563 {
564 ATLASSERT(t_bModal);
565
566 if (!m_Template.IsValid())
567 CreateTemplate();
568
569 CheckStyle();
570
571 return _baseClass::DoModal(hWndParent, dwInitParam);
572 }
573
574 HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
575 {
576 ATLASSERT(!t_bModal);
577
578 if (!m_Template.IsValid())
579 CreateTemplate();
580
581 CheckStyle();
582
583 return _baseClass::Create(hWndParent, dwInitParam);
584 }
585
586 BEGIN_MSG_MAP(CStdIndirectDialogImpl)
587 CHAIN_MSG_MAP(_baseStd)
588 END_MSG_MAP()
589
590 };
591
592 #endif // defined __ATLDLGS_H__
593
594 #ifndef _ATL_NO_HOSTING
595
596 ///////////////////////////////////////////////////////////////////////////////
597 // CStdAxDialogImpl - implementation of standard PPC/SmartPhone AxDialog
598
599 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
600 class ATL_NO_VTABLE CStdAxDialogImpl : public CStdDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl< T > >
601 {};
602 #endif // _ATL_NO_HOSTING
603
604 ///////////////////////////////////////////////////////////////////////////////
605 // CStdSimpleDialog - standard PPC/SmartPhone simple dialog with SHIDIF_xxx flags
606
607 template <WORD t_wDlgTemplateID, UINT t_shidiFlags = WTL_STD_SHIDIF>
608 class CStdSimpleDialog :
609 public ATL::CSimpleDialog<t_wDlgTemplateID, FALSE>,
610 public CStdDialogBase<CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>, t_shidiFlags>
611 {
612 public:
613 typedef CStdDialogBase<CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>, t_shidiFlags> baseClass;
614
615 #ifdef WIN32_PLATFORM_PSPC
616 BOOL GetClientRect(LPRECT lpRect)
617 {
618 return baseClass::GetClientRect(lpRect);
619 }
620
621 BOOL SetWindowText(LPCTSTR lpszString)
622 {
623 return baseClass::SetWindowText(lpszString);
624 }
625 #endif
626
627 BEGIN_MSG_MAP(CStdSimpleDialog)
628 #ifdef WIN32_PLATFORM_PSPC // Pocket PC title and SIP
629 MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
630 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
631 #elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
632 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
633 #endif
634 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
635 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
636 COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
637 COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd)
638 END_MSG_MAP()
639
640 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
641 {
642 StdPlatformInit();
643 StdShidInit();
644 return bHandled = FALSE;
645 }
646 };
647
648 ///////////////////////////////////////////////////////////////////////////////
649 // CStdDialogResizeImplBase - Base implementation of orientation resizing standard PPC/SmartPhone dialog
650
651 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true, class TBase = ATL::CDialogImpl<T> >
652 class ATL_NO_VTABLE CStdDialogResizeImplBase :
653 public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>,
654 public CDialogResize<T>
655 {
656 public:
657 // Note: BEGIN_DLGRESIZE_MAP is required in the derived class.
658
659 BEGIN_MSG_MAP(CStdResizeDialogImplBase)
660 #ifdef WIN32_PLATFORM_PSPC // Pocket PC title
661 MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
662 #elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
663 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
664 #endif
665 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
666 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
667 COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
668 COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
669 CHAIN_MSG_MAP(CDialogResize< T >)
670 END_MSG_MAP()
671
672 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
673 {
674 T* pT = static_cast<T*>(this);
675 ATLASSERT(t_bModal == pT->m_bModal);
676 pT->StdPlatformInit();
677 pT->DlgResize_Init(FALSE);
678 pT->StdShidInit();
679 return bHandled = FALSE;
680 }
681 };
682
683 ///////////////////////////////////////////////////////////////////////////////
684 // CStdDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone dialog
685
686 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
687 class ATL_NO_VTABLE CStdDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal>
688 {};
689
690 #ifndef _ATL_NO_HOSTING
691
692 ///////////////////////////////////////////////////////////////////////////////
693 // CStdAxDialogResizeImpl - implementation of orientation resizing standard PPC/SmartPhone AxDialog
694
695 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
696 class ATL_NO_VTABLE CStdAxDialogResizeImpl : public CStdDialogResizeImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl<T> >
697 {};
698 #endif // _ATL_NO_HOSTING
699
700 ///////////////////////////////////////////////////////////////////////////////
701 // CStdSimpleDialogResizeImpl - implementation of standard resizing simple dialog with SHIDIF_xxx flags
702
703 // Usage:
704 // class CMyDlg : public CStdSimpleDialogResize<CMyDlg,
705 // IDD_MYDLG, SHIDIF_DONEBUTTON | SHIDIF_FULLSCREENNOMENUBAR>
706 // {
707 // public:
708 // BEGIN_DLGRESIZE_MAP(CMyDlg)
709 // ...
710 // END_DLGRESIZE_MAP()
711 // };
712
713 template <class T, WORD t_wDlgTemplateID, UINT t_shidiFlags = WTL_STD_SHIDIF>
714 class ATL_NO_VTABLE CStdSimpleDialogResizeImpl :
715 public CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>,
716 public CDialogResize< T >
717 {
718 public:
719 typedef CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>::baseClass baseClass;
720
721 BEGIN_MSG_MAP(CStdSimpleDialogResizeImpl)
722 #ifdef WIN32_PLATFORM_PSPC // Pocket PC title
723 MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
724 #elif defined(WIN32_PLATFORM_WFSP) // SmartPhone VK_TBACK key
725 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
726 #endif
727 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
728 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
729 COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd)
730 COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
731 CHAIN_MSG_MAP(CDialogResize< T >)
732 END_MSG_MAP()
733
734 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
735 {
736 T* pT = static_cast<T*>(this);
737 pT->StdPlatformInit();
738 pT->DlgResize_Init(FALSE);
739 pT->StdShidInit();
740 return bHandled = FALSE;
741 }
742 };
743
744 #if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC)
745
746 ///////////////////////////////////////////////////////////////////////////////
747 // CStdOrientedDialogBase - Oriented PPC standard dialog base class
748
749 template <class T>
750 class CStdOrientedDialogBase
751 {
752 public:
753 // Operation
754 BOOL SetOrientation(DRA::DisplayMode mode)
755 {
756 T* pT = static_cast<T*>(this);
757 ATLASSERT(pT->IsWindow());
758 ATLASSERT(mode == DRA::GetDisplayMode());
759
760 // Derived dialog must enumerate TWO dialog templates with the same control ids and types ie:
761 // enum { IDD = IDD_MYDLG, IDD_LANDSCAPE = IDD_MYDLG_L };
762 UINT iResource = (mode == DRA::Landscape)? T::IDD_LANDSCAPE : T::IDD;
763
764 BOOL bRes = DRA::RelayoutDialog(ModuleHelper::GetResourceInstance(), pT->m_hWnd, MAKEINTRESOURCE(iResource));
765 pT->OnOrientation(mode);
766 return bRes;
767 }
768
769 // Override
770 void OnOrientation(DRA::DisplayMode /*mode*/)
771 {}
772
773 // Message handlers
774 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
775 {
776 T* pT = static_cast<T*>(this);
777 ATLASSERT(pT->IsWindow());
778 if (wParam == SETTINGCHANGE_RESET)
779 {
780 pT->SetOrientation(DRA::GetDisplayMode());
781 pT->StdPlatformInit();
782 pT->StdShidInit();
783 }
784 else if (wParam == SPI_SETSIPINFO)
785 {
786 pT->DoSipInfo();
787 return TRUE;
788 }
789 return bHandled = FALSE;
790 }
791 };
792
793 ///////////////////////////////////////////////////////////////////////////////
794 // CStdOrientedDialogImplBase - Oriented PPC standard dialog base implementation
795
796 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true, class TBase = ATL::CDialogImpl<T> >
797 class ATL_NO_VTABLE CStdOrientedDialogImplBase :
798 public CStdDialogImplBase< T, t_shidiFlags, t_bModal, TBase>,
799 public CStdOrientedDialogBase<T>
800 {
801 public:
802 BEGIN_MSG_MAP(CStdOrientedDialogImpl)
803 MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
804 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
805 MESSAGE_HANDLER(WM_SETTINGCHANGE, CStdOrientedDialogBase<T>::OnSettingChange)
806 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
807 COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
808 COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
809 END_MSG_MAP()
810
811 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
812 {
813 T* pT = static_cast<T*>(this);
814 #ifdef _DEBUG
815 ATLASSERT(t_bModal == pT->m_bModal);
816 #endif
817 if (DRA::GetDisplayMode() == DRA::Landscape)
818 pT->SetOrientation(DRA::Landscape);
819 pT->StdPlatformInit();
820 pT->StdShidInit();
821 return bHandled = FALSE;
822 }
823 };
824
825 ///////////////////////////////////////////////////////////////////////////////
826 // CStdOrientedDialogImpl - Oriented PPC standard dialog implementation
827
828 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
829 class ATL_NO_VTABLE CStdOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal>
830 {};
831
832 #ifndef _ATL_NO_HOSTING
833 ///////////////////////////////////////////////////////////////////////////////
834 // CStdAxOrientedDialogImpl - Oriented PPC standard AxDialog implementation
835
836 template <class T, UINT t_shidiFlags = WTL_STD_SHIDIF, bool t_bModal = true >
837 class ATL_NO_VTABLE CStdAxOrientedDialogImpl : public CStdOrientedDialogImplBase< T, t_shidiFlags, t_bModal, ATL::CAxDialogImpl<T> >
838 {};
839 #endif // _ATL_NO_HOSTING
840
841 ///////////////////////////////////////////////////////////////////////////////
842 // CStdSimpleOrientedDialog - Standard simple orientable dialog
843
844 template <WORD t_wDlgTemplateID, WORD t_wDlgLandscapeID, UINT t_shidiFlags = WTL_STD_SHIDIF>
845 class CStdSimpleOrientedDialog :
846 public CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>,
847 public CStdOrientedDialogBase<CStdSimpleOrientedDialog<t_wDlgTemplateID, t_wDlgLandscapeID, t_shidiFlags> >
848 {
849 public:
850 typedef CStdSimpleDialog<t_wDlgTemplateID, t_shidiFlags>::baseClass baseClass;
851 typedef CStdOrientedDialogBase<CStdSimpleOrientedDialog<t_wDlgTemplateID, t_wDlgLandscapeID, t_shidiFlags> > baseOriented;
852
853 enum {IDD = t_wDlgTemplateID, IDD_LANDSCAPE = t_wDlgLandscapeID};
854
855 BEGIN_MSG_MAP(CStdSimpleDialog)
856 MESSAGE_HANDLER(WM_PAINT, OnPaintTitle)
857 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
858 MESSAGE_HANDLER(WM_SETTINGCHANGE, baseOriented::OnSettingChange)
859 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
860 COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, baseClass::OnCloseCmd)
861 COMMAND_RANGE_HANDLER(ID_MENU_OK, ID_MENU_CANCEL, OnMenuClose)
862 END_MSG_MAP()
863
864 LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
865 {
866 if (DRA::GetDisplayMode() == DRA::Landscape)
867 SetOrientation(DRA::Landscape);
868 StdPlatformInit();
869 StdShidInit();
870 return bHandled = FALSE;
871 }
872 };
873
874 #endif // _WTL_CE_DRA
875
876
877 #endif // _WTL_CE_NO_DIALOGS
878
879
880 // --- PPC/SmartPhone application window and helpers ---
881
882 #ifndef _WTL_CE_NO_APPWINDOW
883
884 ///////////////////////////////////////////////////////////////////////////////
885 // CAppInfoBase - Helper for application state save/restore to registry
886
887 class CAppInfoBase
888 {
889 public:
890 CRegKeyEx m_Key;
891
892 CAppInfoBase(ATL::_U_STRINGorID sAppKey)
893 {
894 m_Key.Create(HKEY_CURRENT_USER, sAppKey.m_lpstr);
895 ATLASSERT(m_Key.m_hKey);
896 }
897
898 template <class V>
899 LONG Save(V& val, ATL::_U_STRINGorID sName)
900 {
901 return m_Key.SetBinaryValue(sName.m_lpstr, &val, sizeof(V));
902 }
903
904 template <class V>
905 LONG Save(int nb, V& val0, ATL::_U_STRINGorID sName)
906 {
907 return m_Key.SetBinaryValue(sName.m_lpstr, &val0, nb * sizeof(V));
908 }
909
910 template <class V>
911 LONG Restore(V& val, ATL::_U_STRINGorID sName)
912 {
913 ULONG bufSize = sizeof(V);
914 return m_Key.QueryBinaryValue(sName.m_lpstr, &val, &bufSize);
915 }
916
917 template <class V>
918 LONG Restore(int nb, V& val0, ATL::_U_STRINGorID sName)
919 {
920 ULONG bufSize = nb * sizeof(V);
921 return m_Key.QueryBinaryValue(sName.m_lpstr, &val0, &bufSize);
922 }
923
924 #if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
925 LONG Save(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName)
926 {
927 return m_Key.SetStringValue(sName.m_lpstr, sval);
928 }
929
930 LONG Restore(_CSTRING_NS::CString& sval, ATL::_U_STRINGorID sName)
931 {
932 DWORD size = MAX_PATH;
933 LONG res = m_Key.QueryStringValue(sName.m_lpstr, sval.GetBuffer(size), &size);
934 sval.ReleaseBuffer();
935 return res;
936 }
937 #else
938 #pragma message("Warning: CAppInfoBase compiles without CString support. Do not use CString in Save or Restore.")
939 #endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)
940
941 LONG Save(LPCTSTR sval, ATL::_U_STRINGorID sName)
942 {
943 return m_Key.SetStringValue(sName.m_lpstr, sval);
944 }
945
946 LONG Restore(LPTSTR sval, ATL::_U_STRINGorID sName, DWORD *plength)
947 {
948 return m_Key.QueryStringValue(sName.m_lpstr, sval, plength);
949 }
950
951 LONG Delete(ATL::_U_STRINGorID sName)
952 {
953 return m_Key.DeleteValue(sName.m_lpstr);
954 }
955 };
956
957
958 ///////////////////////////////////////////////////////////////////////////////
959 // CAppInfoT - CAppInfoBase constructed from a class with T::GetAppKey()
960
961 // Macro for declaring AppKey
962 #define DECLARE_APPKEY(uAppKey) \
963 static LPCTSTR GetAppKey() \
964 { \
965 static LPCTSTR sAppKey = ATL::_U_STRINGorID(uAppKey).m_lpstr; \
966 return sAppKey; \
967 }
968
969 template <class T>
970 class CAppInfoT : public CAppInfoBase
971 {
972 public:
973 CAppInfoT() : CAppInfoBase(T::GetAppKey()){}
974 };
975
976
977 ///////////////////////////////////////////////////////////////////////////////
978 // CAppWindowBase - Base class for PPC/SmartPhone "well-behaved" application window or dialog
979
980 // Macros for declaring frame WNDCLASS and AppKey
981 #define DECLARE_APP_FRAME_CLASS(WndClassName, uCommonResourceID, uAppKey) \
982 DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
983 DECLARE_APPKEY(uAppKey)
984
985 #define DECLARE_APP_FRAME_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd, uAppKey) \
986 DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
987 DECLARE_APPKEY(uAppKey)
988
989 template <class T>
990 class CAppWindowBase
991 {
992 public:
993 typedef class CAppInfoT< T > CAppInfo;
994
995 #ifndef WIN32_PLATFORM_WFSP
996 SHACTIVATEINFO m_sai; // NoOp on SmartPhones
997 #endif // WIN32_PLATFORM_WFSP
998
999 bool m_bHibernate;
1000
1001 CAppWindowBase< T >() : m_bHibernate(false)
1002 {
1003 #ifndef WIN32_PLATFORM_WFSP
1004 SHACTIVATEINFO sai = { sizeof(SHACTIVATEINFO) };
1005 m_sai = sai;
1006 #endif // WIN32_PLATFORM_WFSP
1007 };
1008
1009 // Same as WTL 7.1 AppWizard generated ActivatePreviousInstance + SendMessage WM_COPYDATA
1010 static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine, bool bDialog)
1011 {
1012 // requires T does DECLARE_APP_FRAME_CLASS, DECLARE_APP_FRAME_CLASS_EX or DECLARE_APP_DLG_CLASS
1013 CFrameWndClassInfo& classInfo = T::GetWndClassInfo();
1014
1015 ATLVERIFY(::LoadString(hInstance, classInfo.m_uCommonResourceID, classInfo.m_szAutoName, sizeof(classInfo.m_szAutoName)/sizeof(classInfo.m_szAutoName[0])) != 0);
1016
1017 classInfo.m_wc.lpszClassName = classInfo.m_szAutoName;
1018
1019 const TCHAR* pszClass = classInfo.m_wc.lpszClassName;
1020
1021 if(NULL == pszClass || '\0' == *pszClass)
1022 {
1023 return E_FAIL;
1024 }
1025
1026 const DWORD dRetryInterval = 100;
1027 const int iMaxRetries = 25;
1028
1029 for(int i = 0; i < iMaxRetries; ++i)
1030 {
1031 HANDLE hMutex = CreateMutex(NULL, FALSE, pszClass);
1032
1033 DWORD dw = GetLastError();
1034
1035 if(NULL == hMutex)
1036 {
1037 HRESULT hr;
1038
1039 switch(dw)
1040 {
1041 case ERROR_INVALID_HANDLE:
1042 // A non-mutext object with this name already exists.
1043 hr = E_INVALIDARG;
1044 break;
1045 default:
1046 // This should never happen...
1047 hr = E_FAIL;
1048 }
1049
1050 return hr;
1051 }
1052
1053 // If the mutex already exists, then there should be another instance running
1054 if(dw == ERROR_ALREADY_EXISTS)
1055 {
1056 CloseHandle(hMutex);
1057
1058 HWND hwnd = NULL;
1059 if (bDialog)
1060 hwnd = FindWindow(NULL, pszClass);
1061 else
1062 hwnd = FindWindow(pszClass, NULL);
1063
1064 if(hwnd == NULL)
1065 {
1066 Sleep(dRetryInterval);
1067 continue;
1068 }
1069 else
1070 {
1071 // Transmit our params to previous instance
1072 if (lpstrCmdLine && *lpstrCmdLine)
1073 {
1074 COPYDATASTRUCT cd = { NULL, sizeof(TCHAR) * (wcslen(lpstrCmdLine) + 1), (PVOID)lpstrCmdLine };
1075 ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cd);
1076 }
1077 // Set the previous instance as the foreground window
1078 if(0 != SetForegroundWindow(reinterpret_cast<HWND>(reinterpret_cast<ULONG>(hwnd) | 0x1)))
1079 return S_FALSE;
1080 }
1081 }
1082 else
1083 {
1084 return S_OK;
1085 }
1086 }
1087 return S_OK;
1088 }
1089
1090 // Operations overriden in derived class
1091 bool AppHibernate(bool /*bHibernate*/)
1092 {
1093 return false;
1094 }
1095
1096 bool AppNewInstance(LPCTSTR /*lpstrCmdLine*/)
1097 {
1098 return false;
1099 }
1100
1101 void AppSave()
1102 {
1103 }
1104
1105 #ifdef WIN32_PLATFORM_WFSP
1106 void AppBackKey()
1107 {
1108 ::SHNavigateBack();
1109 }
1110 #endif
1111
1112 // Message map and handlers
1113 BEGIN_MSG_MAP(CAppWindowBase)
1114 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
1115 #ifdef WIN32_PLATFORM_WFSP
1116 MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
1117 #else
1118 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
1119 #endif // WIN32_PLATFORM_WFSP
1120 MESSAGE_HANDLER(WM_HIBERNATE, OnHibernate)
1121 MESSAGE_HANDLER(WM_COPYDATA, OnNewInstance)
1122 MESSAGE_HANDLER(WM_CLOSE, OnClose)
1123 END_MSG_MAP()
1124
1125 LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1126 {
1127 T* pT = static_cast<T*>(this);
1128 if (m_bHibernate)
1129 m_bHibernate = pT->AppHibernate(false);
1130 #ifndef WIN32_PLATFORM_WFSP
1131 ::SHHandleWMActivate(pT->m_hWnd, wParam, lParam, &m_sai, 0);
1132 #else
1133 wParam;
1134 lParam;
1135 #endif // WIN32_PLATFORM_WFSP
1136 return bHandled = FALSE;
1137 }
1138
1139 #ifdef WIN32_PLATFORM_WFSP
1140 // SmartPhone VK_TBACK key standard management
1141 LRESULT OnHotKey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
1142 {
1143 T* pT = static_cast<T*>(this);
1144 const UINT uModif = (UINT)LOWORD(lParam);
1145 const UINT uVirtKey = (UINT)HIWORD(lParam);
1146 if(uVirtKey == VK_TBACK)
1147 if (AtlIsEditFocus())
1148 ::SHSendBackToFocusWindow(uMsg, wParam, lParam);
1149 else if (uModif & MOD_KEYUP)
1150 pT->AppBackKey();
1151 return 1;
1152 }
1153
1154 #else // !WIN32_PLATFORM_WFSP
1155 // PPC SIP handling
1156 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
1157 {
1158 T* pT = static_cast<T*>(this);
1159 bHandled = FALSE;
1160 return ::SHHandleWMSettingChange(pT->m_hWnd, wParam, lParam, &m_sai);
1161 }
1162 #endif // !WIN32_PLATFORM_WFSP
1163
1164 LRESULT OnHibernate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1165 {
1166 T* pT = static_cast<T*>(this);
1167 return m_bHibernate = pT->AppHibernate(true);
1168 }
1169
1170 LRESULT OnNewInstance(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
1171 {
1172 T* pT = static_cast<T*>(this);
1173 PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam;
1174 return pT->AppNewInstance((LPCTSTR)pcds->lpData);
1175 }
1176
1177 LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
1178 {
1179 T* pT = static_cast<T*>(this);
1180 pT->AppSave();
1181 bHandled = FALSE;
1182 return 1;
1183 }
1184 };
1185
1186
1187 ///////////////////////////////////////////////////////////////////////////////
1188 // CAppWindow - PPC/SmartPhone "well-behaved" application window class
1189
1190 template <class T>
1191 class CAppWindow : public CAppWindowBase< T >
1192 {
1193 public:
1194 // Same as WTL 7.1 AppWizard generated Run + lpstrCmdLine in CreateEx
1195 static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL)
1196 {
1197 CMessageLoop theLoop;
1198 _Module.AddMessageLoop(&theLoop);
1199
1200 T wndMain;
1201
1202 if(wndMain.CreateEx(NULL, NULL, 0, 0, lpstrCmdLine) == NULL)
1203 {
1204 ATLTRACE2(atlTraceUI, 0, _T("Main window creation failed!\n"));
1205 return 0;
1206 }
1207
1208 wndMain.ShowWindow(nCmdShow);
1209
1210 int nRet = theLoop.Run();
1211
1212 _Module.RemoveMessageLoop();
1213 return nRet;
1214 }
1215
1216 static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine)
1217 {
1218 return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, false);
1219 }
1220 };
1221
1222
1223 #ifndef _WTL_CE_NO_DIALOGS
1224
1225 ///////////////////////////////////////////////////////////////////////////////
1226 // CAppDialog - PPC/SmartPhone "well-behaved" dialog application class
1227
1228 // Macro for declaring dialog WNDCLASS and AppKey
1229 #define DECLARE_APP_DLG_CLASS(WndClassName, uCommonResourceID, uAppKey) \
1230 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
1231 { \
1232 static WTL::CFrameWndClassInfo wc = \
1233 { \
1234 { 0, (WNDPROC)StartDialogProc, \
1235 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
1236 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
1237 }; \
1238 return wc; \
1239 }; \
1240 DECLARE_APPKEY(uAppKey)
1241
1242 template <class T>
1243 class CAppDialog : public CAppWindowBase< T >
1244 {
1245 public:
1246 static int AppRun(LPTSTR lpstrCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL)
1247 {
1248 CMessageLoop theLoop;
1249 _Module.AddMessageLoop(&theLoop);
1250
1251 T dlgMain;
1252
1253 if(dlgMain.Create(NULL, (LPARAM)lpstrCmdLine) == NULL)
1254 {
1255 ATLTRACE2(atlTraceUI, 0, _T("Main dialog creation failed!\n"));
1256 return 0;
1257 }
1258
1259 dlgMain.ShowWindow(nCmdShow);
1260
1261 int nRet = theLoop.Run();
1262
1263 _Module.RemoveMessageLoop();
1264 return nRet;
1265 }
1266
1267 static HRESULT ActivatePreviousInstance(HINSTANCE hInstance, LPCTSTR lpstrCmdLine)
1268 {
1269 return CAppWindowBase< T >::ActivatePreviousInstance(hInstance, lpstrCmdLine, true);
1270 };
1271 };
1272
1273 // PPC/SmartPhone standard application dialogs
1274
1275 #ifdef WIN32_PLATFORM_WFSP
1276 #define WTL_APP_SHIDIF WTL_SP_SHIDIF
1277 #else
1278 #define WTL_APP_SHIDIF WTL_STD_SHIDIF
1279 #endif
1280
1281 ///////////////////////////////////////////////////////////////////////////////
1282 // CAppStdDialogImplBase - Base implementation of standard application dialogs
1283
1284 template <class T, class TImplBase, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1285 class ATL_NO_VTABLE CAppStdDialogImplBase :
1286 public TImplBase,
1287 public CAppDialog< T >
1288 {
1289 public:
1290 WTL_DLG_NOTITLE;
1291
1292 void StdCloseDialog(int nVal)
1293 {
1294 T* pT = static_cast<T*>(this);
1295 if (nVal != IDCANCEL)
1296 pT->AppSave();
1297 if (t_bModal == false)
1298 {
1299 pT->DestroyWindow();
1300 ::PostQuitMessage(nVal);
1301 }
1302 else
1303 ::EndDialog(pT->m_hWnd, nVal);
1304 }
1305
1306 BEGIN_MSG_MAP(CAppStdDialogImplBase)
1307 MESSAGE_HANDLER(WM_CLOSE, OnSystemClose)
1308 CHAIN_MSG_MAP(TImplBase)
1309 CHAIN_MSG_MAP(CAppDialog< T >)
1310 END_MSG_MAP()
1311
1312 LRESULT OnSystemClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
1313 {
1314 T* pT = static_cast<T*>(this);
1315 pT->StdCloseDialog(IDCANCEL);
1316 return 0;
1317 }
1318 };
1319
1320 ///////////////////////////////////////////////////////////////////////////////
1321 // CAppStdDialogImpl - Implementation of standard application dialog
1322
1323 template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1324 class ATL_NO_VTABLE CAppStdDialogImpl :
1325 public CAppStdDialogImplBase<T, CStdDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
1326 {};
1327
1328 ///////////////////////////////////////////////////////////////////////////////
1329 // CAppStdDialogResizeImpl - implementation of orientation resizing standard application dialog
1330
1331 template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1332 class ATL_NO_VTABLE CAppStdDialogResizeImpl :
1333 public CAppStdDialogImplBase<T, CStdDialogResizeImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
1334 {};
1335
1336 #ifndef _ATL_NO_HOSTING
1337 ///////////////////////////////////////////////////////////////////////////////
1338 // CAppStdAxDialogImpl - Implementation of standard application AxDialog
1339
1340 template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1341 class ATL_NO_VTABLE CAppStdAxDialogImpl :
1342 public CAppStdDialogImplBase<T, CStdAxDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
1343 {};
1344
1345 ///////////////////////////////////////////////////////////////////////////////
1346 // CAppStdAxDialogResizeImpl - implementation of orientation resizing standard application AxDialog
1347
1348 template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1349 class ATL_NO_VTABLE CAppStdAxDialogResizeImpl :
1350 public CAppStdDialogImplBase<T, CStdAxDialogResizeImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
1351 {};
1352 #endif // _ATL_NO_HOSTING
1353
1354 #if defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC)
1355 ///////////////////////////////////////////////////////////////////////////////
1356 // CAppStdOrientedDialogImpl - implementation of oriented PPC standard application dialog
1357
1358 template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1359 class ATL_NO_VTABLE CAppStdOrientedDialogImpl :
1360 public CAppStdDialogImplBase<T, CStdOrientedDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
1361 {};
1362
1363 #ifndef _ATL_NO_HOSTING
1364 ///////////////////////////////////////////////////////////////////////////////
1365 // CAppStdAxOrientedDialogImpl - implementation of oriented PPC standard application AxDialog
1366
1367 template <class T, UINT t_shidiFlags = WTL_APP_SHIDIF, bool t_bModal = false>
1368 class ATL_NO_VTABLE CAppStdAxOrientedDialogImpl :
1369 public CAppStdDialogImplBase<T, CStdAxOrientedDialogImpl<T, t_shidiFlags, t_bModal>, t_shidiFlags, t_bModal>
1370 {};
1371 #endif // _ATL_NO_HOSTING
1372
1373 #endif // defined(_WTL_CE_DRA) && defined(WIN32_PLATFORM_PSPC)
1374
1375 #endif // _WTL_CE_NO_DIALOGS
1376
1377 #endif // _WTL_CE_NO_APPWINDOW
1378
1379
1380 // --- Full screen support ---
1381
1382 #ifndef _WTL_CE_NO_FULLSCREEN
1383
1384 ///////////////////////////////////////////////////////////////////////////////
1385 // CFullScreenFrame - full screen frame implementation
1386
1387 template <class T, bool t_bHasSip = true>
1388 class CFullScreenFrame
1389 {
1390 public:
1391 bool m_bFullScreen;
1392
1393 CFullScreenFrame() : m_bFullScreen(false)
1394 { }
1395
1396 // Operation
1397 void SetFullScreen(bool bFull)
1398 {
1399 m_bFullScreen = bFull;
1400 ShowTaskBar(!bFull, false);
1401 ShowMenuBar(!bFull);
1402 }
1403
1404 // Manage TaskBar for modal dialogs and property sheets
1405 template <class D>
1406 int FSDoModal(D& dlg)
1407 {
1408 T* pT = static_cast<T*>(this);
1409 pT; // avoid level 4 warning
1410 ATLASSERT(pT->IsWindow());
1411 if (m_bFullScreen) // Show taskbar if hidden
1412 ShowTaskBar(true, false);
1413 int iRet = dlg.DoModal();
1414 if (m_bFullScreen) // Hide taskbar if restored
1415 ShowTaskBar(false);
1416 return iRet;
1417 }
1418
1419 // Implementation
1420 void ShowMenuBar(bool bShow)
1421 {
1422 T* pT = static_cast<T*>(this);
1423 ATLASSERT(pT->IsWindow());
1424 ATL::CWindow MenuBar = pT->m_hWndCECommandBar;
1425 ATLASSERT(MenuBar.IsWindow());
1426 MenuBar.ShowWindow(bShow ? SW_SHOWNORMAL : SW_HIDE);
1427 pT->SizeToMenuBar();
1428 }
1429
1430 void ShowTaskBar(bool bShow, bool bRepaint = true)
1431 {
1432 T* pT = static_cast<T*>(this);
1433 ATLASSERT(pT->IsWindow());
1434 RECT rect = { 0 };
1435 SystemParametersInfo(SPI_GETWORKAREA, NULL, &rect, FALSE);
1436 if (!bShow)
1437 rect.top = 0;
1438
1439 #ifdef WIN32_PLATFORM_PSPC // Pocket PC code
1440 UINT uShow = t_bHasSip ? SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON : SHFS_SHOWTASKBAR | SHFS_HIDESIPBUTTON;
1441 SHFullScreen(pT->m_hWnd, bShow ? uShow : SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON);
1442 #elif _WIN32_WCE > 0x500 // Smartphone 2005 code
1443 SHFullScreen(pT->m_hWnd, bShow ? SHFS_SHOWTASKBAR : SHFS_HIDETASKBAR);
1444 #else // Smartphone 2003
1445 HWND hTaskBar = FindWindow(_T("tray"), NULL);
1446 ATLASSERT(::IsWindow(hTaskBar));
1447 ::ShowWindow(hTaskBar, bShow ? SW_SHOW : SW_HIDE);
1448 #endif // WIN32_PLATFORM_PSPC
1449
1450 pT->MoveWindow(&rect, bRepaint);
1451 }
1452
1453 // Message map and handler
1454 BEGIN_MSG_MAP(CFullScreenFrame)
1455 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
1456 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
1457 END_MSG_MAP()
1458
1459 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1460 {
1461 #ifndef SETTINGCHANGE_RESET // not defined for PPC 2002
1462 #define SETTINGCHANGE_RESET SPI_SETWORKAREA
1463 #endif
1464 if (m_bFullScreen && (wParam == SETTINGCHANGE_RESET))
1465 SetFullScreen(m_bFullScreen);
1466 return bHandled = FALSE;
1467 }
1468
1469 LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1470 {
1471 if (m_bFullScreen)
1472 {
1473 ShowTaskBar(!wParam);
1474 ShowMenuBar(!wParam);
1475 }
1476 return bHandled = FALSE;
1477 }
1478 };
1479
1480 #endif // _WTL_CE_NO_FULLSCREEN
1481
1482
1483 // --- WinCE zoom support ---
1484
1485 #ifndef _WTL_CE_NO_ZOOMSCROLL
1486
1487 ///////////////////////////////////////////////////////////////////////////////
1488 // CZoomScrollImpl - WinCE zooming implementation on top of CScrollImpl
1489
1490 template <class T>
1491 class CZoomScrollImpl: public CScrollImpl< T >
1492 {
1493 public:
1494 // Data members
1495 _WTYPES_NS::CSize m_sizeTrue;
1496 double m_fzoom;
1497
1498 // Creation
1499 CZoomScrollImpl() : m_sizeTrue(0), m_fzoom(1.)
1500 { }
1501
1502 // Zoom operations and access
1503 void SetZoomScrollSize(_WTYPES_NS::CSize sizeTrue, double fzoom = 1., BOOL bRedraw = TRUE)
1504 {
1505 ATLASSERT(fzoom > 0.);
1506 m_sizeTrue = sizeTrue;
1507 m_fzoom = fzoom;
1508
1509 CScrollImpl< T >::SetScrollSize(sizeTrue / fzoom, bRedraw);
1510 }
1511
1512 void SetZoomScrollSize(int cx, int cy, double fzoom=1., BOOL bRedraw = TRUE)
1513 {
1514 SetZoomScrollSize(_WTYPES_NS::CSize(cx, cy), fzoom, bRedraw);
1515 }
1516
1517 void SetZoom(double fzoom, BOOL bRedraw = TRUE)
1518 {
1519 _WTYPES_NS::CPoint ptCenter = WndtoTrue(m_sizeClient / 2);
1520 _WTYPES_NS::CSize sizePage = GetScrollPage();
1521 _WTYPES_NS::CSize sizeLine = GetScrollLine();
1522
1523 SetZoomScrollSize(GetScrollSize(), fzoom, bRedraw);
1524
1525 SetScrollLine(sizeLine);
1526 SetScrollPage(sizePage);
1527 _WTYPES_NS::CPoint ptOffset = ptCenter - (m_sizeClient / 2) * fzoom;
1528 SetScrollOffset(ptOffset, bRedraw);
1529 }
1530
1531 double GetZoom()
1532 {
1533 return m_fzoom;
1534 }
1535
1536 // CScrollImpl overrides
1537 void SetScrollOffset(int x, int y, BOOL bRedraw = TRUE)
1538 {
1539 CScrollImpl< T >::SetScrollOffset((int)(x / m_fzoom), (int)(y / m_fzoom), bRedraw);
1540 }
1541
1542 void SetScrollOffset(POINT ptOffset, BOOL bRedraw = TRUE)
1543 {
1544 SetScrollOffset(ptOffset.x, ptOffset.y, bRedraw);
1545 }
1546
1547 void GetScrollOffset(POINT& ptOffset)
1548 {
1549 ptOffset.x = (LONG)(m_ptOffset.x * m_fzoom);
1550 ptOffset.y = (LONG)(m_ptOffset.y * m_fzoom);
1551 }
1552
1553 void SetScrollSize(int cx, int cy, BOOL bRedraw = TRUE)
1554 {
1555 SetZoomScrollSize(cx, cy, GetZoom(), bRedraw);
1556 }
1557
1558 void SetScrollSize(SIZE sizeTrue, BOOL bRedraw = TRUE)
1559 {
1560 SetZoomScrollSize(sizeTrue, GetZoom(), bRedraw);
1561 }
1562
1563 void GetScrollSize(SIZE& sizeTrue) const
1564 {
1565 sizeTrue = m_sizeTrue;
1566 }
1567
1568 void SetScrollPage(int cxPage, int cyPage)
1569 {
1570 SetScrollPage(_WTYPES_NS::CSize(cxPage, cyPage));
1571 }
1572
1573 void SetScrollPage(SIZE sizePage)
1574 {
1575 CScrollImpl< T >::SetScrollPage(sizePage / m_fzoom);
1576 }
1577
1578 void GetScrollPage(SIZE& sizePage) const
1579 {
1580 sizePage = m_sizePage * m_fzoom;
1581 }
1582
1583 void SetScrollLine(int cxLine, int cyLine)
1584 {
1585 SetScrollLine(_WTYPES_NS::CSize(cxLine, cyLine));
1586 }
1587
1588 void SetScrollLine(SIZE sizeLine)
1589 {
1590 CScrollImpl< T >::SetScrollLine(sizeLine / m_fzoom);
1591 }
1592
1593 void GetScrollLine(SIZE& sizeLine) const
1594 {
1595 sizeLine = m_sizeLine * m_fzoom;
1596 }
1597
1598 // Data access complements
1599 _WTYPES_NS::CSize GetScrollSize()
1600 {
1601 return m_sizeTrue;
1602 }
1603
1604 _WTYPES_NS::CSize GetScrollPage()
1605 {
1606 return m_sizePage * m_fzoom;
1607 }
1608
1609 _WTYPES_NS::CSize GetScrollLine()
1610 {
1611 return m_sizeLine * m_fzoom;
1612 }
1613
1614 _WTYPES_NS::CPoint GetScrollOffset()
1615 {
1616 return (_WTYPES_NS::CSize)m_ptOffset * m_fzoom;
1617 }
1618
1619 // Helper coordinate functions
1620 _WTYPES_NS::CPoint WndtoTrue(CPoint ptW)
1621 {
1622 return (_WTYPES_NS::CSize)ptW * GetZoom() + GetScrollOffset();
1623 }
1624
1625 void WndtoTrue(LPPOINT aptW, int nPts) // in place coord transformation
1626 {
1627 for (int i = 0 ; i < nPts ; i++)
1628 aptW[i] = WndtoTrue(aptW[i]);
1629 }
1630
1631 void WndtoTrue(LPRECT prectW) // in place coord transformation
1632 {
1633 WndtoTrue((LPPOINT)prectW, 2);
1634 }
1635
1636 _WTYPES_NS::CPoint TruetoWnd(CPoint ptT)
1637 {
1638 return (ptT - GetScrollOffset()) / GetZoom();
1639 }
1640
1641 void TruetoWnd(LPPOINT aptT, int nPts) // in place coord transformation
1642 {
1643 for (int i = 0 ; i < nPts ; i++)
1644 aptT[i] = TruetoWnd(aptT[i]);
1645 }
1646
1647 void TruetoWnd(LPRECT prectT) // in place coord transformation
1648 {
1649 TruetoWnd((LPPOINT)prectT, 2);
1650 }
1651
1652 // Drawing operations : assume adequate setting of data members
1653 BOOL Draw(HBITMAP hbm, HDC hdestDC, DWORD dwROP = SRCCOPY)
1654 {
1655 CDC memDC = CreateCompatibleDC(hdestDC);
1656 CBitmapHandle bmpOld = memDC.SelectBitmap(hbm);
1657 BOOL bRes = Draw(memDC, hdestDC, dwROP);
1658 memDC.SelectBitmap(bmpOld);
1659 return bRes;
1660 }
1661
1662 BOOL Draw(HDC hsourceDC, HDC hdestDC, DWORD dwROP = SRCCOPY)
1663 {
1664 CDCHandle destDC = hdestDC;
1665 destDC.SetViewportOrg(0,0);
1666 _WTYPES_NS::CPoint ptOffset = GetScrollOffset();
1667 _WTYPES_NS::CSize sizeZClient = m_sizeClient * GetZoom();
1668 return destDC.StretchBlt(0, 0, m_sizeClient.cx, m_sizeClient.cy, hsourceDC, ptOffset.x, ptOffset.y, sizeZClient.cx, sizeZClient.cy, dwROP);
1669 }
1670
1671 #ifdef _IMAGING_H
1672 BOOL Draw(IImage* pIImage, HDC hdestDC)
1673 {
1674 CDCHandle destDC = hdestDC;
1675 destDC.SetViewportOrg(0,0);
1676 return SUCCEEDED(pIImage->Draw(destDC, _WTYPES_NS::CRect(-_WTYPES_NS::CPoint(m_ptOffset), m_sizeAll), NULL));
1677 }
1678 #endif
1679
1680 // Message map and handlers
1681 BEGIN_MSG_MAP(CZoomScrollImpl< T >)
1682 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
1683 CHAIN_MSG_MAP(CScrollImpl< T >)
1684 END_MSG_MAP()
1685
1686 LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1687 {
1688 T* pT = static_cast<T*>(this);
1689 ATLASSERT(::IsWindow(pT->m_hWnd));
1690 if ((GetScrollExtendedStyle() & SCRL_ERASEBACKGROUND))
1691 {
1692 _WTYPES_NS::CRect rect;
1693 pT->GetClientRect(rect);
1694 _WTYPES_NS::CSize sizeClient=rect.Size();
1695
1696 if (m_sizeAll.cx < sizeClient.cx || m_sizeAll.cy < sizeClient.cy)
1697 {
1698 CDCHandle hdc = (HDC)wParam;
1699 HBRUSH hbr = GetSysColorBrush((int)T::GetWndClassInfo().m_wc.hbrBackground - 1);
1700
1701 if (m_sizeAll.cx < sizeClient.cx)
1702 {
1703 _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(m_sizeAll.cx, 0), sizeClient);
1704 hdc.FillRect(rectBG, hbr);
1705 }
1706
1707 if (m_sizeAll.cy < sizeClient.cy)
1708 {
1709 _WTYPES_NS::CRect rectBG(_WTYPES_NS::CPoint(0, m_sizeAll.cy), sizeClient);
1710 hdc.FillRect(rectBG, hbr);
1711 }
1712 }
1713 }
1714 else
1715 {
1716 bHandled = FALSE;
1717 }
1718
1719 return 1;
1720 }
1721 };
1722
1723 #endif // _WTL_CE_NO_ZOOMSCROLL
1724
1725 #ifndef _WTL_CE_NO_CONTROLS
1726
1727 // --- PPC bottom TabView control ---
1728
1729 #if defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC)
1730
1731 ///////////////////////////////////////////////////////////////////////////////
1732 // CBottomTabViewImpl
1733
1734 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
1735 class ATL_NO_VTABLE CBottomTabViewImpl : public CTabViewImpl<T, TBase, TWinTraits>
1736 {
1737 public:
1738 DECLARE_WND_CLASS_EX(NULL, 0, COLOR_APPWORKSPACE)
1739
1740 // Implementation overrideables
1741 bool CreateTabControl()
1742 {
1743 m_tab.Create(m_hWnd, rcDefault, NULL, WS_CHILD | TCS_BOTTOM, 0, m_nTabID);
1744
1745 ATLASSERT(m_tab.m_hWnd != NULL);
1746 if(m_tab.m_hWnd == NULL)
1747 return false;
1748
1749 m_tab.SendMessage(CCM_SETVERSION, COMCTL32_VERSION);
1750 m_tab.SetItemExtra(sizeof(TABVIEWPAGE));
1751
1752 T* pT = static_cast<T*>(this);
1753 m_cyTabHeight = pT->CalcTabHeight();
1754
1755 return true;
1756 }
1757
1758 int CalcTabHeight()
1759 {
1760 int nCount = m_tab.GetItemCount();
1761 TCITEMEXTRA tcix = { 0 };
1762 tcix.tciheader.mask = TCIF_TEXT;
1763 tcix.tciheader.pszText = _T("NS");
1764 int nIndex = m_tab.InsertItem(nCount, tcix);
1765
1766 RECT rect = { 0 };
1767 SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
1768 RECT rcWnd = rect;
1769
1770 m_tab.AdjustRect(FALSE, &rect);
1771 rcWnd.top = rect.bottom;
1772 ::AdjustWindowRectEx(&rcWnd, m_tab.GetStyle(), FALSE, m_tab.GetExStyle());
1773 m_tab.DeleteItem(nIndex);
1774
1775 return rcWnd.bottom - rcWnd.top;
1776 }
1777
1778 void UpdateLayout()
1779 {
1780 RECT rect = { 0 };
1781 GetClientRect(&rect);
1782
1783 if(m_tab.IsWindow() && ((m_tab.GetStyle() & WS_VISIBLE) != 0))
1784 m_tab.SetWindowPos(NULL, 0, rect.bottom - m_cyTabHeight, rect.right - rect.left, m_cyTabHeight, SWP_NOZORDER /*| SWP_SHOWWINDOW*/);
1785
1786 if(m_nActivePage != -1)
1787 ::SetWindowPos(GetPageHWND(m_nActivePage), NULL, 0, 0, rect.right - rect.left, rect.bottom - m_cyTabHeight, SWP_NOZORDER);
1788 }
1789
1790 };
1791
1792 class CBottomTabView : public CBottomTabViewImpl<CBottomTabView>
1793 {
1794 public:
1795 DECLARE_WND_CLASS_EX(_T("WTL_BottomTabView"), 0, COLOR_APPWORKSPACE)
1796 };
1797
1798 #endif // defined(__ATLCTRLX_H__) && defined(WIN32_PLATFORM_PSPC)
1799
1800
1801 // --- PPC/SmartPhone controls ---
1802
1803 ////////////////////////////////////////////////////////////////////////////////
1804 // These are wrapper classes for the Pocket PC 2002/2003 and SmartPhone 2003 controls
1805 // To implement a window based on a control, use following:
1806 // Example: Implementing a window based on a Html control
1807 //
1808 // class CMyHtml : CWindowImpl<CMyHtml, CHtmlCtrl>
1809 // {
1810 // public:
1811 // BEGIN_MSG_MAP(CMyHtml)
1812 // // put your message handler entries here
1813 // END_MSG_MAP()
1814 // };
1815 ///////////////////////////////////////////////////////////////////////////////
1816
1817 ///////////////////////////////////////////////////////////////////////////////
1818 // CHtmlCtrl
1819
1820 template <class TBase>
1821 class CHtmlCtrlT : public TBase
1822 {
1823 public:
1824 // Constructors
1825 CHtmlCtrlT(HWND hWnd = NULL) : TBase(hWnd)
1826 { }
1827
1828 CHtmlCtrlT< TBase >& operator =(HWND hWnd)
1829 {
1830 m_hWnd = hWnd;
1831 return *this;
1832 }
1833
1834 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1835 DWORD dwStyle = 0, DWORD dwExStyle = 0,
1836 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
1837 {
1838 HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
1839 ATLASSERT(hWnd != NULL); // Did you remember to call InitHTMLControl(hInstance) ??
1840 return hWnd;
1841 }
1842
1843 // Attributes
1844 static LPCTSTR GetWndClassName()
1845 {
1846 return WC_HTML;
1847 }
1848
1849 #if (_WIN32_WCE >= 400)
1850 void AddStyle(LPCWSTR pszStyle)
1851 {
1852 ATLASSERT(::IsWindow(m_hWnd));
1853 ::SendMessage(m_hWnd, DTM_ADDSTYLE, 0, (LPARAM)pszStyle);
1854 }
1855 #endif // (_WIN32_WCE >= 400)
1856
1857 void AddText(BOOL bPlainText, LPCSTR pszText)
1858 {
1859 ATLASSERT(::IsWindow(m_hWnd));
1860 ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)bPlainText, (LPARAM)pszText);
1861 }
1862
1863 void AddHTML(LPCSTR pszHTML)
1864 {
1865 ATLASSERT(::IsWindow(m_hWnd));
1866 ::SendMessage(m_hWnd, DTM_ADDTEXT, (WPARAM)FALSE, (LPARAM)pszHTML);
1867 }
1868
1869 void AddText(BOOL bPlainText, LPCWSTR pszText)
1870 {
1871 ATLASSERT(::IsWindow(m_hWnd));
1872 ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)bPlainText, (LPARAM)pszText);
1873 }
1874
1875 void AddHTML(LPCWSTR pszHTML)
1876 {
1877 ATLASSERT(::IsWindow(m_hWnd));
1878 ::SendMessage(m_hWnd, DTM_ADDTEXTW, (WPARAM)FALSE, (LPARAM)pszHTML);
1879 }
1880
1881 void Anchor(LPCSTR pszAnchor)
1882 {
1883 ATLASSERT(::IsWindow(m_hWnd));
1884 ::SendMessage(m_hWnd, DTM_ANCHOR, 0, (LPARAM)pszAnchor);
1885 }
1886
1887 void Anchor(LPCWSTR pszAnchor)
1888 {
1889 ATLASSERT(::IsWindow(m_hWnd));
1890 ::SendMessage(m_hWnd, DTM_ANCHORW, 0, (LPARAM)pszAnchor);
1891 }
1892
1893 #if (_WIN32_WCE >= 420)
1894 void GetBrowserDispatch(IDispatch** ppDispatch)
1895 {
1896 ATLASSERT(::IsWindow(m_hWnd));
1897 ATLASSERT(ppDispatch);
1898 ATLASSERT(*ppDispatch==NULL);
1899 ::SendMessage(m_hWnd, DTM_BROWSERDISPATCH, 0, (LPARAM)ppDispatch);
1900 }
1901 void GetDocumentDispatch(IDispatch** ppDispatch)
1902 {
1903 ATLASSERT(::IsWindow(m_hWnd));
1904 ATLASSERT(ppDispatch);
1905 ATLASSERT(*ppDispatch==NULL);
1906 ::SendMessage(m_hWnd, DTM_DOCUMENTDISPATCH , 0, (LPARAM)ppDispatch);
1907 }
1908 #endif // (_WIN32_WCE >= 420)
1909
1910 void Clear()
1911 {
1912 ATLASSERT(::IsWindow(m_hWnd));
1913 ::SendMessage(m_hWnd, DTM_CLEAR, 0, 0L);
1914 }
1915
1916 void EnableClearType(BOOL bEnable = TRUE)
1917 {
1918 ATLASSERT(::IsWindow(m_hWnd));
1919 ::SendMessage(m_hWnd, DTM_ENABLECLEARTYPE, 0, (LPARAM)bEnable);
1920 }
1921
1922 void EnableContextMenu(BOOL bEnable = TRUE)
1923 {
1924 ATLASSERT(::IsWindow(m_hWnd));
1925 ::SendMessage(m_hWnd, DTM_ENABLECONTEXTMENU, 0, (LPARAM)bEnable);
1926 }
1927
1928 void EnableScripting(BOOL bEnable = TRUE)
1929 {
1930 ATLASSERT(::IsWindow(m_hWnd));
1931 ::SendMessage(m_hWnd, DTM_ENABLESCRIPTING, 0, (LPARAM)bEnable);
1932 }
1933
1934 void EnableShrink(BOOL bEnable = TRUE)
1935 {
1936 ATLASSERT(::IsWindow(m_hWnd));
1937 ::SendMessage(m_hWnd, DTM_ENABLESHRINK, 0, (LPARAM)bEnable);
1938 }
1939
1940 void EndOfSource()
1941 {
1942 ATLASSERT(::IsWindow(m_hWnd));
1943 ::SendMessage(m_hWnd, DTM_ENDOFSOURCE, 0, 0L);
1944 }
1945
1946 void ImageFail(DWORD dwCookie)
1947 {
1948 ATLASSERT(::IsWindow(m_hWnd));
1949 ::SendMessage(m_hWnd, DTM_IMAGEFAIL, 0, (LPARAM)dwCookie);
1950 }
1951
1952 int GetLayoutHeight() const
1953 {
1954 ATLASSERT(::IsWindow(m_hWnd));
1955 return (int)::SendMessage(m_hWnd, DTM_LAYOUTHEIGHT, 0, 0L);
1956 }
1957
1958 int GetLayoutWidth() const
1959 {
1960 ATLASSERT(::IsWindow(m_hWnd));
1961 return (int)::SendMessage(m_hWnd, DTM_LAYOUTWIDTH, 0, 0L);
1962 }
1963
1964 void Navigate(LPCTSTR pstrURL, UINT uFlags = 0)
1965 {
1966 ATLASSERT(::IsWindow(m_hWnd));
1967 ATLASSERT(pstrURL);
1968 ::SendMessage(m_hWnd, DTM_NAVIGATE, (WPARAM)uFlags, (LPARAM)pstrURL);
1969 }
1970
1971 void SelectAll()
1972 {
1973 ATLASSERT(::IsWindow(m_hWnd));
1974 ::SendMessage(m_hWnd, DTM_SELECTALL, 0, 0L);
1975 }
1976
1977 void SetImage(INLINEIMAGEINFO* pImageInfo)
1978 {
1979 ATLASSERT(::IsWindow(m_hWnd));
1980 ATLASSERT(pImageInfo);
1981 ::SendMessage(m_hWnd, DTM_SETIMAGE, 0, (LPARAM)pImageInfo);
1982 }
1983
1984 void ZoomLevel(int iLevel)
1985 {
1986 ATLASSERT(::IsWindow(m_hWnd));
1987 ::SendMessage(m_hWnd, DTM_ZOOMLEVEL, 0, (LPARAM)iLevel);
1988 }
1989
1990 #if (_WIN32_WCE >= 400)
1991 void Stop()
1992 {
1993 ATLASSERT(::IsWindow(m_hWnd));
1994 ::SendMessage(m_hWnd, DTM_STOP, 0, 0L);
1995 }
1996 #endif // (_WIN32_WCE >= 400)
1997
1998 void GetScriptDispatch(IDispatch** ppDispatch)
1999 {
2000 ATLASSERT(::IsWindow(m_hWnd));
2001 ATLASSERT(ppDispatch);
2002 ATLASSERT(*ppDispatch==NULL);
2003 ::SendMessage(m_hWnd, DTM_SCRIPTDISPATCH, 0, (LPARAM)ppDispatch);
2004 }
2005 };
2006
2007 typedef CHtmlCtrlT<ATL::CWindow> CHtmlCtrl;
2008
2009
2010 #ifdef WIN32_PLATFORM_PSPC
2011
2012 ///////////////////////////////////////////////////////////////////////////////
2013 // CRichInkCtrl
2014
2015 template <class TBase>
2016 class CRichInkCtrlT : public TBase
2017 {
2018 public:
2019 // Constructors
2020 CRichInkCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2021 { }
2022
2023 CRichInkCtrlT< TBase >& operator =(HWND hWnd)
2024 {
2025 m_hWnd = hWnd;
2026 return *this;
2027 }
2028
2029 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2030 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2031 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2032 {
2033 HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2034 ATLASSERT(hWnd != NULL); // Did you remember to call InitRichInkDLL() ??
2035 return hWnd;
2036 }
2037
2038 // Attributes
2039 static LPCTSTR GetWndClassName()
2040 {
2041 return WC_RICHINK;
2042 }
2043
2044 BOOL CanPaste(UINT uFormat = 0) const
2045 {
2046 ATLASSERT(::IsWindow(m_hWnd));
2047 return (BOOL)::SendMessage(m_hWnd, EM_CANPASTE, (WPARAM)uFormat, 0L);
2048 }
2049
2050 BOOL CanRedo() const
2051 {
2052 ATLASSERT(::IsWindow(m_hWnd));
2053 return (BOOL)::SendMessage(m_hWnd, EM_CANREDO, 0, 0L);
2054 }
2055
2056 BOOL CanUndo() const
2057 {
2058 ATLASSERT(::IsWindow(m_hWnd));
2059 return (BOOL)::SendMessage(m_hWnd, EM_CANUNDO, 0, 0L);
2060 }
2061
2062 void ClearAll(BOOL bRepaint = TRUE) const
2063 {
2064 ATLASSERT(::IsWindow(m_hWnd));
2065 ::SendMessage(m_hWnd, EM_CLEARALL, (WPARAM)bRepaint, 0L);
2066 }
2067
2068 BOOL GetModify() const
2069 {
2070 ATLASSERT(::IsWindow(m_hWnd));
2071 return (BOOL)::SendMessage(m_hWnd, EM_GETMODIFY, 0, 0L);
2072 }
2073
2074 UINT GetPageStyle() const
2075 {
2076 ATLASSERT(::IsWindow(m_hWnd));
2077 return (UINT)::SendMessage(m_hWnd, EM_GETPAGESTYLE, 0, 0L);
2078 }
2079
2080 UINT GetPenMode() const
2081 {
2082 ATLASSERT(::IsWindow(m_hWnd));
2083 return (UINT)::SendMessage(m_hWnd, EM_GETPENMODE, 0, 0L);
2084 }
2085
2086 UINT GetViewStyle() const
2087 {
2088 ATLASSERT(::IsWindow(m_hWnd));
2089 return (UINT)::SendMessage(m_hWnd, EM_GETVIEW, 0, 0L);
2090 }
2091
2092 UINT GetWrapMode() const
2093 {
2094 ATLASSERT(::IsWindow(m_hWnd));
2095 return (UINT)::SendMessage(m_hWnd, EM_GETWRAPMODE, 0, 0L);
2096 }
2097
2098 UINT GetZoomPercent() const
2099 {
2100 ATLASSERT(::IsWindow(m_hWnd));
2101 return (UINT)::SendMessage(m_hWnd, EM_GETZOOMPERCENT, 0, 0L);
2102 }
2103
2104 void InsertLinks(LPWSTR lpString, int cchLength = -1)
2105 {
2106 ATLASSERT(::IsWindow(m_hWnd));
2107 if(cchLength == -1)
2108 cchLength = lstrlen(lpString);
2109 ::SendMessage(m_hWnd, EM_INSERTLINKS, (WPARAM)cchLength, (LPARAM)lpString);
2110 }
2111
2112 void RedoEvent()
2113 {
2114 ATLASSERT(::IsWindow(m_hWnd));
2115 ::SendMessage(m_hWnd, EM_REDOEVENT, 0, 0L);
2116 }
2117
2118 UINT SetInkLayer(UINT uLayer)
2119 {
2120 ATLASSERT(::IsWindow(m_hWnd));
2121 return (UINT)::SendMessage(m_hWnd, EM_SETINKLAYER, (WPARAM)uLayer, 0L);
2122 }
2123
2124 void SetPageStyle(UINT uStyle)
2125 {
2126 ATLASSERT(::IsWindow(m_hWnd));
2127 ::SendMessage(m_hWnd, EM_SETPAGESTYLE, (WPARAM)uStyle, 0L);
2128 }
2129
2130 void SetPenMode(UINT uMode)
2131 {
2132 ATLASSERT(::IsWindow(m_hWnd));
2133 ::SendMessage(m_hWnd, EM_SETPENMODE, (WPARAM)uMode, 0L);
2134 }
2135
2136 void SetViewStyle(UINT uStyle)
2137 {
2138 ATLASSERT(::IsWindow(m_hWnd));
2139 ::SendMessage(m_hWnd, EM_SETVIEW, (WPARAM)uStyle, 0L);
2140 }
2141
2142 void SetViewAttributes(VIEWATTRIBUTES* pAttribs)
2143 {
2144 ATLASSERT(::IsWindow(m_hWnd));
2145 ATLASSERT(pAttribs);
2146 ::SendMessage(m_hWnd, EM_SETVIEWATTRIBUTES, 0, (LPARAM)pAttribs);
2147 }
2148
2149 void SetWrapMode(UINT uMode)
2150 {
2151 ATLASSERT(::IsWindow(m_hWnd));
2152 ::SendMessage(m_hWnd, EM_SETWRAPMODE, (WPARAM)uMode, 0L);
2153 }
2154
2155 void SetZoomPercent(UINT uPercent)
2156 {
2157 ATLASSERT(::IsWindow(m_hWnd));
2158 ::SendMessage(m_hWnd, EM_SETZOOMPERCENT, (WPARAM)uPercent, 0L);
2159 }
2160
2161 LONG StreamIn(UINT uFormat, EDITSTREAM& es)
2162 {
2163 ATLASSERT(::IsWindow(m_hWnd));
2164 return (LONG)::SendMessage(m_hWnd, EM_STREAMIN, (WPARAM)uFormat, (LPARAM)&es);
2165 }
2166
2167 LONG StreamOut(UINT uFormat, EDITSTREAM& es)
2168 {
2169 ATLASSERT(::IsWindow(m_hWnd));
2170 return (LONG)::SendMessage(m_hWnd, EM_STREAMOUT, (WPARAM)uFormat, (LPARAM)&es);
2171 }
2172
2173 void UndoEvent()
2174 {
2175 ATLASSERT(::IsWindow(m_hWnd));
2176 ::SendMessage(m_hWnd, EM_UNDOEVENT, 0, 0L);
2177 }
2178
2179 void Undo()
2180 {
2181 UndoEvent();
2182 }
2183
2184 // Standard EM_xxx messages
2185 DWORD GetSel() const
2186 {
2187 ATLASSERT(::IsWindow(m_hWnd));
2188 ATLASSERT(GetViewStyle() != VT_DRAWINGVIEW);
2189 return (DWORD)::SendMessage(m_hWnd, EM_GETSEL, 0, 0L);
2190 }
2191
2192 void GetSel(int& nStartChar, int& nEndChar) const
2193 {
2194 ATLASSERT(::IsWindow(m_hWnd));
2195 ATLASSERT(GetViewStyle() != VT_DRAWINGVIEW);
2196 ::SendMessage(m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
2197 }
2198
2199 void SetSel(int nStartChar, int nEndChar)
2200 {
2201 ATLASSERT(::IsWindow(m_hWnd));
2202 ATLASSERT(GetViewStyle() != VT_DRAWINGVIEW);
2203 ::SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar);
2204 }
2205
2206 void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
2207 {
2208 ATLASSERT(::IsWindow(m_hWnd));
2209 ATLASSERT(GetViewStyle() != VT_DRAWINGVIEW);
2210 ::SendMessage(m_hWnd, EM_REPLACESEL, (WPARAM)bCanUndo, (LPARAM)lpszNewText);
2211 }
2212
2213 void SetModify(BOOL bModified = TRUE)
2214 {
2215 ATLASSERT(::IsWindow(m_hWnd));
2216 ::SendMessage(m_hWnd, EM_SETMODIFY, (WPARAM)bModified, 0L);
2217 }
2218
2219 int GetTextLength() const
2220 {
2221 ATLASSERT(::IsWindow(m_hWnd));
2222 return (int)::SendMessage(m_hWnd, WM_GETTEXTLENGTH, 0, 0L);
2223 }
2224
2225 // Clipboard operations
2226 void Clear()
2227 {
2228 ATLASSERT(::IsWindow(m_hWnd));
2229 ::SendMessage(m_hWnd, WM_CLEAR, 0, 0L);
2230 }
2231
2232 void Copy()
2233 {
2234 ATLASSERT(::IsWindow(m_hWnd));
2235 ::SendMessage(m_hWnd, WM_COPY, 0, 0L);
2236 }
2237
2238 void Cut()
2239 {
2240 ATLASSERT(::IsWindow(m_hWnd));
2241 ::SendMessage(m_hWnd, WM_CUT, 0, 0L);
2242 }
2243
2244 void Paste()
2245 {
2246 ATLASSERT(::IsWindow(m_hWnd));
2247 ::SendMessage(m_hWnd, WM_PASTE, 0, 0L);
2248 }
2249 };
2250
2251 typedef CRichInkCtrlT<ATL::CWindow> CRichInkCtrl;
2252
2253
2254 ///////////////////////////////////////////////////////////////////////////////
2255 // CInkXCtrl
2256
2257 template <class TBase>
2258 class CInkXCtrlT : public TBase
2259 {
2260 public:
2261 // Constructors
2262 CInkXCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2263 { }
2264
2265 CInkXCtrlT< TBase >& operator =(HWND hWnd)
2266 {
2267 m_hWnd = hWnd;
2268 return *this;
2269 }
2270
2271 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2272 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2273 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2274 {
2275 HWND hWnd = TBase::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2276 ATLASSERT(hWnd != NULL); // Did you remember to call InitInkX() ??
2277 return hWnd;
2278 }
2279
2280 // Attributes
2281 static LPCTSTR GetWndClassName()
2282 {
2283 return WC_INKX;
2284 }
2285
2286 static UINT GetHotRecordingMessage()
2287 {
2288 return ::RegisterWindowMessage(szHotRecording);
2289 }
2290
2291 void ClearAll()
2292 {
2293 ATLASSERT(::IsWindow(m_hWnd));
2294 ::SendMessage(m_hWnd, IM_CLEARALL, 0, 0L);
2295 }
2296
2297 int GetData(BYTE* lpBuffer, INT cbBuffer) const
2298 {
2299 ATLASSERT(::IsWindow(m_hWnd));
2300 ATLASSERT(lpBuffer);
2301 return (int)::SendMessage(m_hWnd, IM_GETDATA, (WPARAM)cbBuffer, (LPARAM)lpBuffer);
2302 }
2303
2304 int GetDataLen() const
2305 {
2306 ATLASSERT(::IsWindow(m_hWnd));
2307 return (int)::SendMessage(m_hWnd, IM_GETDATALEN, 0, 0L);
2308 }
2309
2310 CRichInkCtrl GetRichInk() const
2311 {
2312 ATLASSERT(::IsWindow(m_hWnd));
2313 return (HWND)::SendMessage(m_hWnd, IM_GETRICHINK, 0, 0L);
2314 }
2315
2316 BOOL IsRecording() const
2317 {
2318 ATLASSERT(::IsWindow(m_hWnd));
2319 return (BOOL)::SendMessage(m_hWnd, IM_RECORDING, 0, 0L);
2320 }
2321
2322 void ReInit()
2323 {
2324 ATLASSERT(::IsWindow(m_hWnd));
2325 ::SendMessage(m_hWnd, IM_REINIT, 0, 0L);
2326 }
2327
2328 void SetData(const BYTE* lpInkData, INT cbInkData)
2329 {
2330 ATLASSERT(::IsWindow(m_hWnd));
2331 ATLASSERT(lpInkData);
2332 ::SendMessage(m_hWnd, IM_SETDATA, (WPARAM)cbInkData, (LPARAM)lpInkData);
2333 }
2334
2335 void VoicePlay()
2336 {
2337 ATLASSERT(::IsWindow(m_hWnd));
2338 ::SendMessage(m_hWnd, IM_VOICE_PLAY, 0, 0L);
2339 }
2340
2341 BOOL IsVoicePlaying() const
2342 {
2343 ATLASSERT(::IsWindow(m_hWnd));
2344 return (BOOL)::SendMessage(m_hWnd, IM_VOICE_PLAYING, 0, 0L);
2345 }
2346
2347 BOOL VoiceRecord()
2348 {
2349 ATLASSERT(::IsWindow(m_hWnd));
2350 return (BOOL)::SendMessage(m_hWnd, IM_VOICE_RECORD, 0, 0L);
2351 }
2352
2353 void VoiceStop()
2354 {
2355 ATLASSERT(::IsWindow(m_hWnd));
2356 ::SendMessage(m_hWnd, IM_VOICE_STOP, 0, 0L);
2357 }
2358
2359 void ShowVoiceBar(BOOL bShow = TRUE)
2360 {
2361 ATLASSERT(::IsWindow(m_hWnd));
2362 ::SendMessage(m_hWnd, IM_VOICEBAR, (WPARAM)bShow, 0L);
2363 }
2364 };
2365
2366 typedef CInkXCtrlT<ATL::CWindow> CInkXCtrl;
2367
2368 #endif // WIN32_PLATFORM_PSPC
2369
2370
2371 ///////////////////////////////////////////////////////////////////////////////
2372 // CVoiceRecorderCtrl
2373
2374 template <class TBase>
2375 class CVoiceRecorderCtrlT : public TBase
2376 {
2377 public:
2378 // Constructors
2379 CVoiceRecorderCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2380 { }
2381
2382 CVoiceRecorderCtrlT< TBase >& operator =(HWND hWnd)
2383 {
2384 m_hWnd = hWnd;
2385 return *this;
2386 }
2387
2388 HWND Create(HWND hWndParent, const POINT pt, LPTSTR pstrFileName, UINT nID, DWORD dwStyle = 0)
2389 {
2390 ATLASSERT(pstrFileName != NULL);
2391 CM_VOICE_RECORDER cmvr = { 0 };
2392 cmvr.cb = sizeof(CM_VOICE_RECORDER);
2393 cmvr.dwStyle = dwStyle;
2394 cmvr.xPos = pt.x;
2395 cmvr.yPos = pt.y;
2396 cmvr.hwndParent = hWndParent;
2397 cmvr.id = nID;
2398 cmvr.lpszRecordFileName = pstrFileName;
2399 m_hWnd = VoiceRecorder_Create(&cmvr);
2400 return m_hWnd;
2401 }
2402
2403 HWND Create(LPCM_VOICE_RECORDER pAttribs)
2404 {
2405 ATLASSERT(pAttribs);
2406 m_hWnd = VoiceRecorder_Create(pAttribs);
2407 return m_hWnd;
2408 }
2409
2410 // Attributes
2411 void Record()
2412 {
2413 ATLASSERT(::IsWindow(m_hWnd));
2414 ::SendMessage(m_hWnd, VRM_RECORD, 0, 0L);
2415 }
2416
2417 void Play()
2418 {
2419 ATLASSERT(::IsWindow(m_hWnd));
2420 ::SendMessage(m_hWnd, VRM_PLAY, 0, 0L);
2421 }
2422
2423 void Stop()
2424 {
2425 ATLASSERT(::IsWindow(m_hWnd));
2426 ::SendMessage(m_hWnd, VRM_STOP, 0, 0L);
2427 }
2428
2429 void Cancel()
2430 {
2431 ATLASSERT(::IsWindow(m_hWnd));
2432 ::SendMessage(m_hWnd, VRM_CANCEL, 0, 0L);
2433 }
2434
2435 void Done()
2436 {
2437 ATLASSERT(::IsWindow(m_hWnd));
2438 ::SendMessage(m_hWnd, VRM_OK, 0, 0L);
2439 }
2440 };
2441
2442 typedef CVoiceRecorderCtrlT<ATL::CWindow> CVoiceRecorderCtrl;
2443
2444
2445 #ifdef WIN32_PLATFORM_PSPC
2446
2447 ///////////////////////////////////////////////////////////////////////////////
2448 // CDocListCtrl
2449
2450 template <class TBase>
2451 class CDocListCtrlT : public TBase
2452 {
2453 public:
2454 // Attributes
2455 DOCLISTCREATE m_dlc;
2456 TCHAR m_szPath[MAX_PATH];
2457
2458 // Constructors
2459 CDocListCtrlT(HWND hWnd = NULL) : TBase(hWnd)
2460 { }
2461
2462 CDocListCtrlT< TBase >& operator =(HWND hWnd)
2463 {
2464 m_hWnd = hWnd;
2465 return *this;
2466 }
2467
2468 HWND Create(HWND hWndParent, WORD wId, LPCTSTR pszFolder = NULL, LPCTSTR pstrFilter = NULL,
2469 WORD wFilterIndex = 0, DWORD dwFlags = DLF_SHOWEXTENSION)
2470 {
2471 ATLASSERT(pstrFilter != NULL); // It seems to need a filter badly!!
2472 ::ZeroMemory(&m_dlc, sizeof(DOCLISTCREATE));
2473 ::ZeroMemory(m_szPath, sizeof(m_szPath));
2474 if(pszFolder != NULL)
2475 SecureHelper::strncpy_x(m_szPath, MAX_PATH, pszFolder, MAX_PATH - 1);
2476 m_dlc.dwStructSize = sizeof(DOCLISTCREATE);
2477 m_dlc.hwndParent = hWndParent;
2478 m_dlc.pszFolder = m_szPath;
2479 m_dlc.pstrFilter = pstrFilter;
2480 m_dlc.wFilterIndex = wFilterIndex;
2481 m_dlc.wId = wId;
2482 m_dlc.dwFlags = dwFlags;
2483 m_hWnd = DocList_Create(&m_dlc);
2484 return m_hWnd;
2485 }
2486
2487 HWND Create(DOCLISTCREATE* pDlc)
2488 {
2489 m_dlc = *pDlc;
2490 m_hWnd = DocList_Create(&m_dlc);
2491 return m_hWnd;
2492 }
2493
2494 // Attributes
2495 void DeleteSel()
2496 {
2497 ATLASSERT(::IsWindow(m_hWnd));
2498 ::SendMessage(m_hWnd, DLM_DELETESEL, 0, 0L);
2499 }
2500
2501 void DisableUpdates()
2502 {
2503 ATLASSERT(::IsWindow(m_hWnd));
2504 ::SendMessage(m_hWnd, DLM_DISABLEUPDATES, 0, 0L);
2505 }
2506
2507 void EnableUpdates()
2508 {
2509 ATLASSERT(::IsWindow(m_hWnd));
2510 ::SendMessage(m_hWnd, DLM_ENABLEUPDATES, 0, 0L);
2511 }
2512
2513 int GetFilterIndex() const
2514 {
2515 ATLASSERT(::IsWindow(m_hWnd));
2516 return (int)::SendMessage(m_hWnd, DLM_GETFILTERINDEX, 0, 0L);
2517 }
2518
2519 int GetItemCount() const
2520 {
2521 ATLASSERT(::IsWindow(m_hWnd));
2522 return (int)::SendMessage(m_hWnd, DLM_GETITEMCOUNT, 0, 0L);
2523 }
2524
2525 int GetNextItem(int iIndex, DWORD dwRelation = LVNI_ALL) const
2526 {
2527 ATLASSERT(::IsWindow(m_hWnd));
2528 return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)dwRelation);
2529 }
2530
2531 int GetFirstItem(DWORD dwRelation = LVNI_ALL) const
2532 {
2533 ATLASSERT(::IsWindow(m_hWnd));
2534 return (int)::SendMessage(m_hWnd, DLM_GETNEXTITEM, (WPARAM)-1, (LPARAM)dwRelation);
2535 }
2536
2537 BOOL GetNextWave(int* pIndex) const
2538 {
2539 ATLASSERT(::IsWindow(m_hWnd));
2540 ATLASSERT(pIndex);
2541 return (BOOL)::SendMessage(m_hWnd, DLM_GETNEXTWAVE, 0, (LPARAM)pIndex);
2542 }
2543
2544 BOOL GetPrevWave(int* pIndex) const
2545 {
2546 ATLASSERT(::IsWindow(m_hWnd));
2547 ATLASSERT(pIndex);
2548 return (BOOL)::SendMessage(m_hWnd, DLM_GETPREVWAVE, 0, (LPARAM)pIndex);
2549 }
2550
2551 int GetSelCount() const
2552 {
2553 ATLASSERT(::IsWindow(m_hWnd));
2554 return (int)::SendMessage(m_hWnd, DLM_GETSELCOUNT, 0, 0L);
2555 }
2556
2557 BOOL GetSelPathName(LPTSTR pstrPath, int cchMax) const
2558 {
2559 ATLASSERT(::IsWindow(m_hWnd));
2560 ATLASSERT(pstrPath);
2561 return (BOOL)::SendMessage(m_hWnd, DLM_GETSELPATHNAME, (WPARAM)cchMax, (LPARAM)pstrPath);
2562 }
2563
2564 void ReceiveIR(LPCTSTR pstrPath) const
2565 {
2566 ATLASSERT(::IsWindow(m_hWnd));
2567 ATLASSERT(pstrPath);
2568 ::SendMessage(m_hWnd, DLM_RECEIVEIR, 0, (LPARAM)pstrPath);
2569 }
2570
2571 void Refresh()
2572 {
2573 ATLASSERT(::IsWindow(m_hWnd));
2574 ::SendMessage(m_hWnd, DLM_REFRESH, 0, 0L);
2575 }
2576
2577 BOOL RenameMoveSelectedItems()
2578 {
2579 ATLASSERT(::IsWindow(m_hWnd));
2580 return (BOOL)::SendMessage(m_hWnd, DLM_RENAMEMOVE, 0, 0L);
2581 }
2582
2583 int SelectAll()
2584 {
2585 ATLASSERT(::IsWindow(m_hWnd));
2586 return (int)::SendMessage(m_hWnd, DLM_SELECTALL, 0, 0L);
2587 }
2588
2589 HRESULT SelectItem(LPCTSTR pstrPath, BOOL bVisible = TRUE)
2590 {
2591 ATLASSERT(::IsWindow(m_hWnd));
2592 ATLASSERT(pstrPath);
2593 return (HRESULT)::SendMessage(m_hWnd, DLM_SELECTITEM, (WPARAM)bVisible, (LPARAM)pstrPath);
2594 }
2595
2596 void SendEMail(LPCTSTR pstrAttachment)
2597 {
2598 ATLASSERT(::IsWindow(m_hWnd));
2599 ::SendMessage(m_hWnd, DLM_SENDEMAIL, 0, (LPARAM)pstrAttachment);
2600 }
2601
2602 void SendIR(LPCTSTR pstrPath)
2603 {
2604 ATLASSERT(::IsWindow(m_hWnd));
2605 ::SendMessage(m_hWnd, DLM_SENDIR, 0, (LPARAM)pstrPath);
2606 }
2607
2608 HRESULT SetFilterIndex(int iIndex)
2609 {
2610 ATLASSERT(::IsWindow(m_hWnd));
2611 return (HRESULT)::SendMessage(m_hWnd, DLM_SETFILTERINDEX, (WPARAM)iIndex, 0L);
2612 }
2613
2614 void SetFolder(LPCTSTR pstrPath)
2615 {
2616 ATLASSERT(::IsWindow(m_hWnd));
2617 ATLASSERT(pstrPath);
2618 ::SendMessage(m_hWnd, DLM_SETFOLDER, 0, (LPARAM)pstrPath);
2619 }
2620
2621 BOOL SetItemState(int iIndex, const LVITEM* pItem)
2622 {
2623 ATLASSERT(::IsWindow(m_hWnd));
2624 ATLASSERT(pItem);
2625 return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)pItem);
2626 }
2627
2628 BOOL SetItemState(int iIndex, UINT uState, UINT uMask)
2629 {
2630 ATLASSERT(::IsWindow(m_hWnd));
2631 LVITEM lvi = { 0 };
2632 lvi.stateMask = uMask;
2633 lvi.state = uState;
2634 return (BOOL)::SendMessage(m_hWnd, DLM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)&lvi);
2635 }
2636
2637 void SetOneItem(int iIndex, LPCVOID pPA)
2638 {
2639 ATLASSERT(::IsWindow(m_hWnd));
2640 ::SendMessage(m_hWnd, DLM_SETONEITEM, (WPARAM)iIndex, (LPARAM)pPA);
2641 }
2642
2643 void SetSelect(int iIndex)
2644 {
2645 ATLASSERT(::IsWindow(m_hWnd));
2646 ::SendMessage(m_hWnd, DLM_SETSELECT, (WPARAM)iIndex, 0L);
2647 }
2648
2649 void SetSelPathName(LPCTSTR pstrPath)
2650 {
2651 ATLASSERT(::IsWindow(m_hWnd));
2652 ATLASSERT(pstrPath);
2653 ::SendMessage(m_hWnd, DLM_SETSELPATHNAME, 0, (LPARAM)pstrPath);
2654 }
2655
2656 BOOL SetSortOrder()
2657 {
2658 ATLASSERT(::IsWindow(m_hWnd));
2659 return (BOOL)::SendMessage(m_hWnd, DLM_SETSORTORDER, 0, 0L);
2660 }
2661
2662 HRESULT Update()
2663 {
2664 ATLASSERT(::IsWindow(m_hWnd));
2665 return (HRESULT)::SendMessage(m_hWnd, DLM_UPDATE, 0, 0L);
2666 }
2667
2668 BOOL ValidateFolder()
2669 {
2670 ATLASSERT(::IsWindow(m_hWnd));
2671 return (BOOL)::SendMessage(m_hWnd, DLM_VALIDATEFOLDER, 0, 0L);
2672 }
2673
2674 // Functions
2675 BOOL GetFirstSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath)
2676 {
2677 ATLASSERT(::IsWindow(m_hWnd));
2678 return DocList_GetFirstSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath);
2679 }
2680
2681 BOOL GetNextSelectedWaveFile(int* pIndex, LPTSTR szPath, const size_t cchPath)
2682 {
2683 ATLASSERT(::IsWindow(m_hWnd));
2684 return DocList_GetNextSelectedWaveFile(m_hWnd, pIndex, szPath, cchPath);
2685 }
2686 };
2687
2688 typedef CDocListCtrlT<ATL::CWindow> CDocListCtrl;
2689
2690 #endif // WIN32_PLATFORM_PSPC
2691
2692
2693 ///////////////////////////////////////////////////////////////////////////////
2694 // CCapEdit
2695
2696 template <class TBase>
2697 class CCapEditT : public TBase
2698 {
2699 public:
2700 // Constructors
2701 CCapEditT(HWND hWnd = NULL) : TBase(hWnd)
2702 { }
2703
2704 CCapEditT< TBase >& operator =(HWND hWnd)
2705 {
2706 m_hWnd = hWnd;
2707 return *this;
2708 }
2709
2710 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2711 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2712 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2713 {
2714 HWND hWnd = /*TBase*/CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2715 ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ??
2716 return hWnd;
2717 }
2718
2719 // Attributes
2720 static LPCTSTR GetWndClassName()
2721 {
2722 return WC_CAPEDIT;
2723 }
2724 };
2725
2726 typedef CCapEditT<WTL::CEdit> CCapEdit;
2727
2728 ///////////////////////////////////////////////////////////////////////////////
2729 // CTTStatic
2730
2731 #ifndef WIN32_PLATFORM_WFSP // Tooltips not supported on SmartPhone
2732
2733 template <class TBase>
2734 class CTTStaticT : public TBase
2735 {
2736 public:
2737 // Constructors
2738 CTTStaticT(HWND hWnd = NULL) : TBase(hWnd)
2739 { }
2740
2741 CTTStaticT< TBase >& operator =(HWND hWnd)
2742 {
2743 m_hWnd = hWnd;
2744 return *this;
2745 }
2746
2747 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2748 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2749 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2750 {
2751 HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2752 ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ??
2753 return hWnd;
2754 }
2755
2756 // Attributes
2757 static LPCTSTR GetWndClassName()
2758 {
2759 return WC_TSTATIC;
2760 }
2761
2762 // Operations
2763 BOOL SetToolTipText(LPCTSTR pstrTipText)
2764 {
2765 ATLASSERT(::IsWindow(m_hWnd));
2766 ATLASSERT(pstrTipText);
2767 ATLASSERT(lstrlen(pstrTipText) <= 253);
2768 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
2769 int cchLen = lstrlen(pstrTipText) + 3;
2770 LPTSTR pstr = buff.Allocate(cchLen);
2771 if(pstr == NULL)
2772 return FALSE;
2773 SecureHelper::strcpy_x(pstr, cchLen, _T("~~"));
2774 SecureHelper::strcat_x(pstr, cchLen, pstrTipText);
2775 return SetWindowText(pstr);
2776 }
2777 };
2778
2779 typedef CTTStaticT<WTL::CStatic> CTTStatic;
2780
2781
2782 ///////////////////////////////////////////////////////////////////////////////
2783 // CTTButton
2784
2785 template <class TBase>
2786 class CTTButtonT : public TBase
2787 {
2788 public:
2789 // Constructors
2790 CTTButtonT(HWND hWnd = NULL) : TBase(hWnd)
2791 { }
2792
2793 CTTButtonT< TBase >& operator =(HWND hWnd)
2794 {
2795 m_hWnd = hWnd;
2796 return *this;
2797 }
2798
2799 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
2800 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2801 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2802 {
2803 HWND hWnd = TBase::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
2804 ATLASSERT(hWnd != NULL); // Did you remember to call SHInitExtraControls() ??
2805 return hWnd;
2806 }
2807
2808 // Attributes
2809 static LPCTSTR GetWndClassName()
2810 {
2811 return WC_TBUTTON;
2812 }
2813
2814 // Operations
2815 BOOL SetToolTipText(LPCTSTR pstrTipText)
2816 {
2817 ATLASSERT(::IsWindow(m_hWnd));
2818 ATLASSERT(pstrTipText);
2819 ATLASSERT(lstrlen(pstrTipText) <= 253);
2820 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
2821 int cchLen = lstrlen(pstrTipText) + 3;
2822 LPTSTR pstr = buff.Allocate(cchLen);
2823 if(pstr == NULL)
2824 return FALSE;
2825 SecureHelper::strcpy_x(pstr, cchLen, _T("~~"));
2826 SecureHelper::strcat_x(pstr, cchLen, pstrTipText);
2827 return SetWindowText(pstr);
2828 }
2829 };
2830
2831 typedef CTTButtonT<WTL::CButton> CTTButton;
2832
2833 #endif // !WIN32_PLATFORM_WFSP
2834
2835
2836 // --- SmartPhone specific controls ---
2837
2838 #ifdef WIN32_PLATFORM_WFSP
2839
2840 ///////////////////////////////////////////////////////////////////////////////
2841 // CSpinCtrlT - CSpinCtrl : SmartPhone adapted UpDown control
2842
2843 template <class TBase>
2844 class CSpinCtrlT : public CUpDownCtrlT< TBase >
2845 {
2846 public:
2847 // Constructors
2848 CSpinCtrlT(HWND hWnd = NULL) : CUpDownCtrlT< TBase >(hWnd)
2849 { }
2850
2851 CSpinCtrlT< TBase >& operator =(HWND hWnd)
2852 {
2853 m_hWnd = hWnd;
2854 return *this;
2855 }
2856
2857 HWND Create(HWND hWndParent, HWND hBuddy, DWORD dwStyle, int nID, LPCTSTR szExpandedName = NULL)
2858 {
2859 ATLASSERT(::IsWindow(hWndParent));
2860 CUpDownCtrlT< TBase >::Create(hWndParent, NULL, szExpandedName, dwStyle, 0, nID, NULL);
2861 ATLASSERT(m_hWnd != NULL); // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)?
2862 if (hBuddy != NULL)
2863 {
2864 ATLASSERT(::IsWindow(hBuddy));
2865 SetBuddy(hBuddy);
2866 }
2867 return m_hWnd;
2868 }
2869 };
2870
2871 typedef CSpinCtrlT<ATL::CWindow> CSpinCtrl;
2872
2873
2874 ///////////////////////////////////////////////////////////////////////////////
2875 // CSpinned - SmartPhone association of control and Spin
2876
2877 template <class TBase, bool t_bExpandOnly>
2878 class CSpinned : public TBase
2879 {
2880 public:
2881 CSpinCtrl m_SpinCtrl;
2882 DWORD m_dwSpinnedStyle;
2883
2884 // Constructors
2885 CSpinned(HWND hWnd = NULL) : TBase(hWnd)
2886 {
2887 m_dwSpinnedStyle = WS_VISIBLE | UDS_ALIGNRIGHT | UDS_EXPANDABLE;
2888
2889 if (t_bExpandOnly == true)
2890 m_dwSpinnedStyle |= UDS_NOSCROLL;
2891 else
2892 m_dwSpinnedStyle |= UDS_HORZ | UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_WRAP;
2893
2894 if (hWnd != NULL)
2895 AttachOrCreateSpinCtrl();
2896 }
2897
2898 CSpinned<TBase, t_bExpandOnly>& operator =(HWND hWnd)
2899 {
2900 Attach(hWnd);
2901 return *this;
2902 }
2903
2904 void Attach(HWND hWnd)
2905 {
2906 ATLASSERT(!IsWindow());
2907 TBase* pT = static_cast<TBase*>(this);
2908 pT->m_hWnd = hWnd;
2909 if (hWnd != NULL)
2910 AttachOrCreateSpinCtrl();
2911 }
2912
2913 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szExpandedName = NULL,
2914 DWORD dwStyle = 0, DWORD dwExStyle = 0,
2915 ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
2916 {
2917
2918 TBase* pT = static_cast<TBase*>(this);
2919 TBase::Create(hWndParent, rect, NULL, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
2920 ATLASSERT(pT->m_hWnd != NULL);
2921
2922 m_SpinCtrl.Create(hWndParent, pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + (int)MenuOrID.m_hMenu, szExpandedName);
2923
2924 ATLASSERT(m_SpinCtrl.m_hWnd != NULL); // Did you remember to call AtlInitCommonControls(ICC_UPDOWN_CLASS)?
2925
2926 return pT->m_hWnd;
2927 }
2928
2929 // Attributes
2930 CSpinCtrl& GetSpinCtrl()
2931 {
2932 return m_SpinCtrl;
2933 }
2934
2935 // Implementation
2936 // Attach our existing SpinCtrl or create one
2937 bool AttachOrCreateSpinCtrl()
2938 {
2939 TBase* pT = static_cast<TBase*>(this);
2940
2941 HWND hSpin = ::GetDlgItem(pT->GetParent(), ATL_IDW_SPIN_ID + pT->GetDlgCtrlID());
2942
2943 if (hSpin != NULL)
2944 {
2945 m_SpinCtrl.Attach(hSpin);
2946 #ifdef DEBUG
2947 TCHAR sClassName[16] = { 0 };
2948 ::GetClassName(hSpin, sClassName, 16);
2949 ATLASSERT(!_tcscmp(sClassName, UPDOWN_CLASS));
2950 ATLASSERT(m_SpinCtrl.GetBuddy().m_hWnd == pT->m_hWnd);
2951 #endif // DEBUG
2952 }
2953 else
2954 {
2955 m_SpinCtrl.Create(pT->GetParent(), pT->m_hWnd, m_dwSpinnedStyle, ATL_IDW_SPIN_ID + pT->GetDlgCtrlID());
2956 }
2957
2958 return m_SpinCtrl.m_hWnd != NULL;
2959 }
2960 };
2961
2962
2963 ///////////////////////////////////////////////////////////////////////////////
2964 // CSpinListBox - SmartPhone spinned ListBox control
2965 // CExpandListBox - SmartPhone expandable ListBox control
2966 // CExpandEdit - SmartPhone expandable Edit control
2967 // CExpandCapEdit - SmartPhone expandable CapEdit control
2968
2969 typedef CSpinned<CListBox, false> CSpinListBox;
2970 typedef CSpinned<CListBox, true> CExpandListBox;
2971 typedef CSpinned<CEdit, true> CExpandEdit;
2972 typedef CSpinned<CCapEdit, true> CExpandCapEdit;
2973
2974 #endif // WIN32_PLATFORM_WFSP
2975
2976 #endif // _WTL_CE_NO_CONTROLS
2977
2978 }; // namespace WTL
2979
2980 #endif // __ATLWINCE_H__
+0
-522
src/third_party/wtl/Include/atlwinx.h less more
0 // Windows Template Library - WTL version 9.10
1 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2 //
3 // This file is a part of the Windows Template Library.
4 // The use and distribution terms for this software are covered by the
5 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
6 // which can be found in the file MS-PL.txt at the root folder.
7
8 #ifndef __ATLWINX_H__
9 #define __ATLWINX_H__
10
11 #pragma once
12
13 #ifndef __ATLAPP_H__
14 #error atlwinx.h requires atlapp.h to be included first
15 #endif
16
17 #if (_ATL_VER >= 0x0700)
18 #include <atlwin.h>
19 #endif // (_ATL_VER >= 0x0700)
20
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // Classes in this file:
24 //
25 // _U_RECT
26 // _U_MENUorID
27 // _U_STRINGorID
28
29
30 ///////////////////////////////////////////////////////////////////////////////
31 // Command Chaining Macros
32
33 #define CHAIN_COMMANDS(theChainClass) \
34 if(uMsg == WM_COMMAND) \
35 CHAIN_MSG_MAP(theChainClass)
36
37 #define CHAIN_COMMANDS_ALT(theChainClass, msgMapID) \
38 if(uMsg == WM_COMMAND) \
39 CHAIN_MSG_MAP_ALT(theChainClass, msgMapID)
40
41 #define CHAIN_COMMANDS_MEMBER(theChainMember) \
42 if(uMsg == WM_COMMAND) \
43 CHAIN_MSG_MAP_MEMBER(theChainMember)
44
45 #define CHAIN_COMMANDS_ALT_MEMBER(theChainMember, msgMapID) \
46 if(uMsg == WM_COMMAND) \
47 CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID)
48
49
50 ///////////////////////////////////////////////////////////////////////////////
51 // Macros for parent message map to selectively reflect control messages
52
53 // NOTE: ReflectNotifications is a member of ATL's CWindowImplRoot
54 // (and overridden in 2 cases - CContainedWindowT and CAxHostWindow)
55 // Since we can't modify ATL, we'll provide the needed additions
56 // in a separate function (that is not a member of CWindowImplRoot)
57
58 namespace WTL
59 {
60
61 inline LRESULT WtlReflectNotificationsFiltered(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled,
62 UINT uMsgFilter = WM_NULL, UINT_PTR idFromFilter = 0, HWND hWndChildFilter = NULL)
63 {
64 if((uMsgFilter != WM_NULL) && (uMsgFilter != uMsg))
65 {
66 // The notification message doesn't match the filter.
67 bHandled = FALSE;
68 return 1;
69 }
70
71 HWND hWndChild = NULL;
72 UINT_PTR idFrom = 0;
73
74 switch(uMsg)
75 {
76 case WM_COMMAND:
77 if(lParam != NULL) // not from a menu
78 {
79 hWndChild = (HWND)lParam;
80 idFrom = (UINT_PTR)LOWORD(wParam);
81 }
82 break;
83 case WM_NOTIFY:
84 hWndChild = ((LPNMHDR)lParam)->hwndFrom;
85 idFrom = ((LPNMHDR)lParam)->idFrom;
86 break;
87 #ifndef _WIN32_WCE
88 case WM_PARENTNOTIFY:
89 switch(LOWORD(wParam))
90 {
91 case WM_CREATE:
92 case WM_DESTROY:
93 hWndChild = (HWND)lParam;
94 idFrom = (UINT_PTR)HIWORD(wParam);
95 break;
96 default:
97 hWndChild = ::GetDlgItem(hWndParent, HIWORD(wParam));
98 idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild);
99 break;
100 }
101 break;
102 #endif // !_WIN32_WCE
103 case WM_DRAWITEM:
104 if(wParam) // not from a menu
105 {
106 hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
107 idFrom = (UINT_PTR)wParam;
108 }
109 break;
110 case WM_MEASUREITEM:
111 if(wParam) // not from a menu
112 {
113 hWndChild = ::GetDlgItem(hWndParent, ((LPMEASUREITEMSTRUCT)lParam)->CtlID);
114 idFrom = (UINT_PTR)wParam;
115 }
116 break;
117 case WM_COMPAREITEM:
118 if(wParam) // not from a menu
119 {
120 hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem;
121 idFrom = (UINT_PTR)wParam;
122 }
123 break;
124 case WM_DELETEITEM:
125 if(wParam) // not from a menu
126 {
127 hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem;
128 idFrom = (UINT_PTR)wParam;
129 }
130 break;
131 case WM_VKEYTOITEM:
132 case WM_CHARTOITEM:
133 case WM_HSCROLL:
134 case WM_VSCROLL:
135 hWndChild = (HWND)lParam;
136 idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild);
137 break;
138 case WM_CTLCOLORBTN:
139 case WM_CTLCOLORDLG:
140 case WM_CTLCOLOREDIT:
141 case WM_CTLCOLORLISTBOX:
142 case WM_CTLCOLORMSGBOX:
143 case WM_CTLCOLORSCROLLBAR:
144 case WM_CTLCOLORSTATIC:
145 hWndChild = (HWND)lParam;
146 idFrom = (UINT_PTR)::GetDlgCtrlID(hWndChild);
147 break;
148 default:
149 break;
150 }
151
152 if((hWndChild == NULL) ||
153 ((hWndChildFilter != NULL) && (hWndChildFilter != hWndChild)))
154 {
155 // Either hWndChild isn't valid, or
156 // hWndChild doesn't match the filter.
157 bHandled = FALSE;
158 return 1;
159 }
160
161 if((idFromFilter != 0) && (idFromFilter != idFrom))
162 {
163 // The dialog control id doesn't match the filter.
164 bHandled = FALSE;
165 return 1;
166 }
167
168 ATLASSERT(::IsWindow(hWndChild));
169 LRESULT lResult = ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
170 if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC))
171 {
172 // Try to prevent problems with WM_CTLCOLOR* messages when
173 // the message wasn't really handled
174 bHandled = FALSE;
175 }
176
177 return lResult;
178 }
179
180 }; // namespace WTL
181
182 // Try to prevent problems with WM_CTLCOLOR* messages when
183 // the message wasn't really handled
184 #define REFLECT_NOTIFICATIONS_EX() \
185 { \
186 bHandled = TRUE; \
187 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
188 if((lResult == 0) && (uMsg >= WM_CTLCOLORMSGBOX) && (uMsg <= WM_CTLCOLORSTATIC)) \
189 bHandled = FALSE; \
190 if(bHandled) \
191 return TRUE; \
192 }
193
194 #define REFLECT_NOTIFICATIONS_MSG_FILTERED(uMsgFilter) \
195 { \
196 bHandled = TRUE; \
197 lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, NULL); \
198 if(bHandled) \
199 return TRUE; \
200 }
201
202 #define REFLECT_NOTIFICATIONS_ID_FILTERED(idFromFilter) \
203 { \
204 bHandled = TRUE; \
205 lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, idFromFilter, NULL); \
206 if(bHandled) \
207 return TRUE; \
208 }
209
210 #define REFLECT_NOTIFICATIONS_HWND_FILTERED(hWndChildFilter) \
211 { \
212 bHandled = TRUE; \
213 lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, WM_NULL, 0, hWndChildFilter); \
214 if(bHandled) \
215 return TRUE; \
216 }
217
218 #define REFLECT_NOTIFICATIONS_MSG_ID_FILTERED(uMsgFilter, idFromFilter) \
219 { \
220 bHandled = TRUE; \
221 lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, idFromFilter, NULL); \
222 if(bHandled) \
223 return TRUE; \
224 }
225
226 #define REFLECT_NOTIFICATIONS_MSG_HWND_FILTERED(uMsgFilter, hWndChildFilter) \
227 { \
228 bHandled = TRUE; \
229 lResult = WTL::WtlReflectNotificationsFiltered(m_hWnd, uMsg, wParam, lParam, bHandled, uMsgFilter, 0, hWndChildFilter); \
230 if(bHandled) \
231 return TRUE; \
232 }
233
234 #define REFLECT_COMMAND(id, code) \
235 if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
236 { \
237 bHandled = TRUE; \
238 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
239 if(bHandled) \
240 return TRUE; \
241 }
242
243 #define REFLECT_COMMAND_ID(id) \
244 if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
245 { \
246 bHandled = TRUE; \
247 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
248 if(bHandled) \
249 return TRUE; \
250 }
251
252 #define REFLECT_COMMAND_CODE(code) \
253 if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \
254 { \
255 bHandled = TRUE; \
256 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
257 if(bHandled) \
258 return TRUE; \
259 }
260
261 #define REFLECT_COMMAND_RANGE(idFirst, idLast) \
262 if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
263 { \
264 bHandled = TRUE; \
265 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
266 if(bHandled) \
267 return TRUE; \
268 }
269
270 #define REFLECT_COMMAND_RANGE_CODE(idFirst, idLast, code) \
271 if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
272 { \
273 bHandled = TRUE; \
274 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
275 if(bHandled) \
276 return TRUE; \
277 }
278
279 #define REFLECT_NOTIFY(id, cd) \
280 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
281 { \
282 bHandled = TRUE; \
283 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
284 if(bHandled) \
285 return TRUE; \
286 }
287
288 #define REFLECT_NOTIFY_ID(id) \
289 if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
290 { \
291 bHandled = TRUE; \
292 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
293 if(bHandled) \
294 return TRUE; \
295 }
296
297 #define REFLECT_NOTIFY_CODE(cd) \
298 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
299 { \
300 bHandled = TRUE; \
301 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
302 if(bHandled) \
303 return TRUE; \
304 }
305
306 #define REFLECT_NOTIFY_RANGE(idFirst, idLast) \
307 if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
308 { \
309 bHandled = TRUE; \
310 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
311 if(bHandled) \
312 return TRUE; \
313 }
314
315 #define REFLECT_NOTIFY_RANGE_CODE(idFirst, idLast, cd) \
316 if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
317 { \
318 bHandled = TRUE; \
319 lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
320 if(bHandled) \
321 return TRUE; \
322 }
323
324
325 ///////////////////////////////////////////////////////////////////////////////
326 // Reflected message handler macros for message maps (for ATL 3.0)
327
328 #if (_ATL_VER < 0x0700)
329
330 #define REFLECTED_COMMAND_HANDLER(id, code, func) \
331 if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
332 { \
333 bHandled = TRUE; \
334 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
335 if(bHandled) \
336 return TRUE; \
337 }
338
339 #define REFLECTED_COMMAND_ID_HANDLER(id, func) \
340 if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
341 { \
342 bHandled = TRUE; \
343 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
344 if(bHandled) \
345 return TRUE; \
346 }
347
348 #define REFLECTED_COMMAND_CODE_HANDLER(code, func) \
349 if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
350 { \
351 bHandled = TRUE; \
352 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
353 if(bHandled) \
354 return TRUE; \
355 }
356
357 #define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
358 if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
359 { \
360 bHandled = TRUE; \
361 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
362 if(bHandled) \
363 return TRUE; \
364 }
365
366 #define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \
367 if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
368 { \
369 bHandled = TRUE; \
370 lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
371 if(bHandled) \
372 return TRUE; \
373 }
374
375 #define REFLECTED_NOTIFY_HANDLER(id, cd, func) \
376 if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
377 { \
378 bHandled = TRUE; \
379 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
380 if(bHandled) \
381 return TRUE; \
382 }
383
384 #define REFLECTED_NOTIFY_ID_HANDLER(id, func) \
385 if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
386 { \
387 bHandled = TRUE; \
388 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
389 if(bHandled) \
390 return TRUE; \
391 }
392
393 #define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \
394 if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
395 { \
396 bHandled = TRUE; \
397 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
398 if(bHandled) \
399 return TRUE; \
400 }
401
402 #define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
403 if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
404 { \
405 bHandled = TRUE; \
406 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
407 if(bHandled) \
408 return TRUE; \
409 }
410
411 #define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \
412 if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
413 { \
414 bHandled = TRUE; \
415 lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
416 if(bHandled) \
417 return TRUE; \
418 }
419
420 #endif // (_ATL_VER < 0x0700)
421
422
423 ///////////////////////////////////////////////////////////////////////////////
424 // Dual argument helper classes (for ATL 3.0)
425
426 #if (_ATL_VER < 0x0700)
427
428 namespace ATL
429 {
430
431 class _U_RECT
432 {
433 public:
434 _U_RECT(LPRECT lpRect) : m_lpRect(lpRect)
435 { }
436 _U_RECT(RECT& rc) : m_lpRect(&rc)
437 { }
438 LPRECT m_lpRect;
439 };
440
441 class _U_MENUorID
442 {
443 public:
444 _U_MENUorID(HMENU hMenu) : m_hMenu(hMenu)
445 { }
446 _U_MENUorID(UINT nID) : m_hMenu((HMENU)LongToHandle(nID))
447 { }
448 HMENU m_hMenu;
449 };
450
451 class _U_STRINGorID
452 {
453 public:
454 _U_STRINGorID(LPCTSTR lpString) : m_lpstr(lpString)
455 { }
456 _U_STRINGorID(UINT nID) : m_lpstr(MAKEINTRESOURCE(nID))
457 { }
458 LPCTSTR m_lpstr;
459 };
460
461 }; // namespace ATL
462
463 #endif // (_ATL_VER < 0x0700)
464
465
466 namespace WTL
467 {
468
469 ///////////////////////////////////////////////////////////////////////////////
470 // Forward notifications support for message maps (for ATL 3.0)
471
472 #if (_ATL_VER < 0x0700)
473
474 // forward notifications support
475 #define FORWARD_NOTIFICATIONS() \
476 { \
477 bHandled = TRUE; \
478 lResult = WTL::Atl3ForwardNotifications(m_hWnd, uMsg, wParam, lParam, bHandled); \
479 if(bHandled) \
480 return TRUE; \
481 }
482
483 static LRESULT Atl3ForwardNotifications(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
484 {
485 LRESULT lResult = 0;
486 switch(uMsg)
487 {
488 case WM_COMMAND:
489 case WM_NOTIFY:
490 #ifndef _WIN32_WCE
491 case WM_PARENTNOTIFY:
492 #endif // !_WIN32_WCE
493 case WM_DRAWITEM:
494 case WM_MEASUREITEM:
495 case WM_COMPAREITEM:
496 case WM_DELETEITEM:
497 case WM_VKEYTOITEM:
498 case WM_CHARTOITEM:
499 case WM_HSCROLL:
500 case WM_VSCROLL:
501 case WM_CTLCOLORBTN:
502 case WM_CTLCOLORDLG:
503 case WM_CTLCOLOREDIT:
504 case WM_CTLCOLORLISTBOX:
505 case WM_CTLCOLORMSGBOX:
506 case WM_CTLCOLORSCROLLBAR:
507 case WM_CTLCOLORSTATIC:
508 lResult = ::SendMessage(::GetParent(hWnd), uMsg, wParam, lParam);
509 break;
510 default:
511 bHandled = FALSE;
512 break;
513 }
514 return lResult;
515 }
516
517 #endif // (_ATL_VER < 0x0700)
518
519 }; // namespace WTL
520
521 #endif // __ATLWINX_H__
+0
-22
src/third_party/wtl/LICENSE less more
0 Microsoft Public License (MS-PL)
1
2 This license governs use of the accompanying software. If you use the software, you
3 accept this license. If you do not accept the license, do not use the software.
4
5 1. Definitions
6 The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
7 same meaning here as under U.S. copyright law.
8 A "contribution" is the original software, or any additions or changes to the software.
9 A "contributor" is any person that distributes its contribution under this license.
10 "Licensed patents" are a contributor's patent claims that read directly on its contribution.
11
12 2. Grant of Rights
13 (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
14 (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
15
16 3. Conditions and Limitations
17 (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
18 (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
19 (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
20 (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
21 (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
+0
-22
src/third_party/wtl/MS-PL.txt less more
0 Microsoft Public License (MS-PL)
1
2 This license governs use of the accompanying software. If you use the software, you
3 accept this license. If you do not accept the license, do not use the software.
4
5 1. Definitions
6 The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
7 same meaning here as under U.S. copyright law.
8 A "contribution" is the original software, or any additions or changes to the software.
9 A "contributor" is any person that distributes its contribution under this license.
10 "Licensed patents" are a contributor's patent claims that read directly on its contribution.
11
12 2. Grant of Rights
13 (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
14 (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
15
16 3. Conditions and Limitations
17 (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
18 (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
19 (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
20 (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
21 (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
+0
-11
src/third_party/wtl/README.mozc less more
0 URL: http://sourceforge.net/projects/wtl/files/WTL%209.1/WTL%209.1.5321%20Final/
1 Version: WTL version 9.1.5321
2 License: Ms-PL
3 License File: LICENSE
4
5 Local Modifications:
6 Removed following non-essential directories, to save space.
7 - AppWiz/
8 - AppWizCE/
9 - AppWizMobile/
10 - Samples/
+0
-3653
src/third_party/wtl/ReadMe.html less more
0 <html>
1
2 <head>
3 <meta http-equiv="Content-Language" content="en-us">
4 <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
5 <title>Windows Template Library</title>
6 <style type="text/css">
7 html, body {
8 width: 800px;
9 }
10 .style1 {
11 font-family: Arial;
12 font-weight: bold;
13 font-size: x-small;
14 }
15 .style2 {
16 font-family: Courier;
17 font-size: small;
18 }
19 .style3 {
20 text-align: right;
21 }
22 </style>
23 </head>
24
25 <body>
26
27 <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber3">
28 <tr>
29 <td class="style3">
30 <p style="text-align: left"><font face="Arial"><b>Windows Template Library - WTL Version 9.1</b></font><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
31 (build 5321 final) 2015-11-17</font></td>
32 </tr>
33 <tr>
34 <td><hr></td>
35 </tr>
36 <tr>
37 <td><font face="Arial" size="2">Copyright &#169; 2015 Microsoft Corporation, WTL Team. All rights reserved.</font></td>
38 </tr>
39 <tr>
40 <td>&nbsp;</td>
41 </tr>
42 <tr>
43 <td><font face="Arial" size="2">This file is a part of the Windows Template
44 Library.<br>
45 The use and distribution terms for this software are covered by the<br>
46 Microsoft Public License (<a target="_blank" href="http://opensource.org/licenses/MS-PL">http://opensource.org/licenses/MS-PL</a>)<br>
47 which can be found in the file MS-PL.txt at the root folder.<br></font></td>
48 </tr>
49 <tr>
50 <td><hr></td>
51 </tr>
52 </table>
53
54 <p style=margin:0in>&nbsp;</p>
55
56 <p style=margin:0in>&nbsp;</p>
57
58 <p style=margin:0in><font face="Arial" size="2">Welcome to the Windows Template Library, version
59 9.1. This document contains the following topics:</font></p>
60 <p style=margin:0in>&nbsp;</p>
61 <ul style="margin-top:0in;margin-bottom:0in">
62 <li><font face="Arial" size="2"><a href="#Introduction">Introduction</a></font></li>
63 <li><font face="Arial" size="2"><a href="#Features and Installation">Features
64 and Installation</a></font></li>
65 <li><font face="Arial" size="2"><a href="#Packing List">Packing List</a></font></li>
66 <li><font face="Arial" size="2"><a href="#Class Overview">Class Overview</a></font></li>
67 <li><font face="Arial" size="2"><a href="#ATL/WTL AppWizard">ATL/WTL AppWizard</a></font></li>
68 <li><a href="#Support for Windows CE"><font face="Arial" size="2">S</font></a><font face="Arial" size="2"><a href="#Support for Windows CE">upport
69 for Windows CE</a></font></li>
70 <li><font face="Arial" size="2">
71 <a href="#Support for Visual C++ Express">Support for Visual C++
72 Express</a></font></li>
73 <li><font face="Arial" size="2"><a href="#Notes">Notes</a></font></li>
74 <li><font face="Arial" size="2"><a href="#Changes Between WTL 9.1 and 9.0">Changes Between WTL
75 9.1 and 9.0</a></font></li>
76 <li><font face="Arial" size="2"><a href="#Changes Between WTL 9.0 and 8.0">Changes Between WTL
77 9.0 and 8.0</a></font></li>
78 <li><font face="Arial" size="2"><a href="#Changes Between WTL 8.0 and 7.5">Changes Between WTL
79 8.0 and 7.5</a></font></li>
80 <li><font face="Arial" size="2"><a href="#Changes Between WTL 7.5 and 7.1">Changes Between WTL 7.5 and 7.1</a></font></li>
81 <li><font face="Arial" size="2"><a href="#Changes Between WTL 7.1 and 7.0">Changes Between WTL
82 7.1 and 7.0</a></font></li>
83 <li><font face="Arial" size="2"><a href="#Changes Between WTL 7.0 and 3.1">Changes Between WTL
84 7.0 and 3.1</a></font></li>
85 <li><font face="Arial" size="2"><a href="#Changes Between WTL 3.1 and 3.0">Changes Between WTL 3.1 and 3.0</a></font></li>
86 </ul>
87 <p style=margin:0in>&nbsp;</p>
88 <p style=margin:0in>&nbsp;</p>
89 <p style=margin:0in><font face="Arial">
90 <b><a name="Introduction"></a>Introduction</b></font></p>
91 <p style=margin:0in>&nbsp;</p>
92 <p style=margin:0in><font face="Arial" size="2">Windows Template Library, or WTL, is a set of
93 classes that extend ATL to support more complex user interfaces for either
94 applications or various UI components, while maintaining the big advantage of
95 ATL - small and fast code. WTL classes were designed to be the best and the
96 easiest way to implement rich Win32 based UI for ATL based applications,
97 servers, components, and controls.</font></p>
98 <p style=margin:0in>&nbsp;</p>
99 <p style=margin:0in><font face="Arial" size="2">WTL provides support for implementing
100 many
101 user interface elements, from frame and popup windows, to MDI, standard and
102 common controls, common dialogs, property sheets and pages, GDI objects, UI
103 updating, scrollable windows, splitter windows, command bars, etc. The WTL
104 classes are mostly templated and use minimal instance data and inline functions.
105 They were not designed as a framework, so they do not force a particular
106 application model, and can accommodate any. The classes do not use hooks or
107 thread local storage, so they have no restrictions that those techniques impose.
108 They also have no inter-dependencies and can be freely mixed with straight SDK
109 code. In summary, WTL delivers very small and efficient code, very close in size
110 and speed to SDK programs, while presenting a more logical, object oriented
111 model to a programmer.</font></p>
112 <p style=margin:0in>&nbsp;</p>
113 <p style=margin:0in>&nbsp;</p>
114 <p style=margin:0in><font face="Arial">
115 <b><a name="Features and Installation"></a>Features and Installation</b></font></p>
116 <p style=margin:0in>&nbsp;</p>
117 <p style=margin:0in><font face="Arial" size="2">This is the eigth public release
118 of WTL, after WTL 3.0, 3.1, 7.0, 7.1, 7.5, 8.0, and 9.0. This version is released
119 under the Microsoft Public License, enabling developers from the WTL community to
120 contribute to the library.</font></p>
121 <p style=margin:0in>&nbsp;</p>
122 <p style=margin:0in><font face="Arial" size="2">WTL classes can be used with either VC++ 6.0, VC++ .NET 2002 or 2003, VC++ 2005 or 2008 or 2010 or 2012 or 2013 or 2015,
123 or EVC++ 4.0 or 3.0. AppWizard for Visual Studio is
124 included.</font></p>
125 <p style=margin:0in>&nbsp;</p>
126 <p style=margin:0in><font face="Arial" size="2">The WTL classes are provided in
127 header files located in the include directory. The only header files that must
128 be included is atlapp.h, while others can be used when needed. The name of the
129 file doesn't mean that you have to create an application, just that
130 atlapp.h contains base definitions required for WTL projects.</font></p>
131 <p style=margin:0in>&nbsp;</p>
132 <p style=margin:0in><font face="Arial" size="2">To install WTL, just copy the whole directory
133 structure, or unpack the archive file, to the location of your choice. Please be sure to
134 <b>add the WTL\include
135 directory</b> to the list of include directories in VC++, so that the compiler
136 can find them when you include them in your projects..</font></p>
137 <p style=margin:0in>&nbsp;</p>
138 <p style=margin:0in><font face="Arial" size="2">Setup programs for the AppWizard are provided. After executing the setup script, ATL/WTL AppWizard will appear in the list of AppWizards when you select File.New.Project
139 in VC++ IDE. The file AppWiz\setup.js is the setup script for all supported versions of Visual Studio, while
140 AppWizards for Windows CE have separate scripts for VS2005 and VS2008 SmartDevice projects.</font></p>
141 <p style=margin:0in>&nbsp;</p>
142 <p style=margin:0in><font face="Arial" size="2">To manually install AppWizard
143 for VC++ .NET 2002/2003, copy all WTLAppWiz.* files from AppWiz\Files to VC++ .NET
144 projects directory, %VC7DIR%\Vc7\vcprojects, where %VC7DIR% is the directory
145 where VC++ .NET 2002/2003 is installed. After that,&nbsp;open WTLAppWiz.vsz and modify the
146 like that contains ABSOLUTE_PATH to contain %WTLDIR%\AppWiz\Files, where
147 %WTLDIR% is the directory where WTL files are.</font></p>
148 <p style=margin:0in>&nbsp;</p>
149 <p style=margin:0in><font face="Arial" size="2">Platform support and
150 requirements:</font></p>
151 <p style=margin:0in>&nbsp;</p>
152 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Compiler/IDE/ATL:</font></p>
153 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
154 Visual C++ 6.0&nbsp;&nbsp; (ATL 3.0)</font></p>
155 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
156 Visual C++.NET 2002&nbsp;&nbsp; (ATL 7.0)</font></p>
157 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
158 Visual C++.NET 2003&nbsp;&nbsp; (ATL 7.1)</font></p>
159 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
160 Visual C++ 2005&nbsp;&nbsp; (ATL 8.0)</font></p>
161 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
162 Visual C++ 2008&nbsp;&nbsp; (ATL 9.0)</font></p>
163 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
164 Visual C++ 2010&nbsp;&nbsp; (ATL 10.0)</font></p>
165 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
166 Visual C++ 2012&nbsp;&nbsp; (ATL 11.0)</font></p>
167 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
168 Visual C++ 2013&nbsp;&nbsp; (ATL 12.0)</font></p>
169 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
170 Visual C++ 2015&nbsp;&nbsp; (ATL 14.0)</font></p>
171 <p style=margin:0in>&nbsp;</p>
172 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; SDK
173 (optional):</font></p>
174 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
175 Any Platform SDK from January 2000 release up to the latest Windows SDK</font></p>
176 <p style=margin:0in>&nbsp;</p>
177 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Windows CE
178 development:</font></p>
179 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
180 eMbedded Visual C++ 3.0 - Pocket PC, Pocket PC 2002</font></p>
181 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
182 eMbedded Visual C++ 4.0 - STANDARDSDK_410, Pocket PC 2003, Smartphone 2003,
183 </font></p>
184 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
185 STANDARDSDK_500, Pocket PC 2003 SE, Smartphone 2003 SE</font></p>
186 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
187 Visual C++ 2005 - Pocket PC 2003 SE, Smartphone 2003 SE, STANDARDSDK_500,</font></p>
188 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
189 Windows Mobile 5.0 (Pocket PC and Smartphone),<br>
190 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
191 Windows Mobile 6.0 (Standard and Professional)</font></p>
192 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
193 Visual C++ 2008 - Pocket PC 2003 SE, Smartphone 2003 SE, STANDARDSDK_500,</font></p>
194 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
195 Windows Mobile 5.0 (Pocket PC and Smartphone),<br>
196 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
197 Windows Mobile 6.0 (Standard and Professional)</font></p>
198 <p style=margin:0in>&nbsp;</p>
199 <p style=margin:0in>&nbsp;</p>
200 <p style=margin:0in><font face="Arial">
201 <b><a name="Packing List"></a>Packing List</b></font></p>
202 <p style=margin:0in>&nbsp;</p>
203 <table border="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="497" id="AutoNumber2">
204 <tr>
205 <td width="136"><font face="Arial" size="2">File Name:</font></td>
206 <td width="358"><font face="Arial" size="2">Description:</font></td>
207 </tr>
208 <tr>
209 <td width="494" colspan="2"><hr></td>
210 </tr>
211 <tr>
212 <td width="136"><font face="Arial" size="2">readme.html</font></td>
213 <td width="358"><font face="Arial" size="2">this file</font></td>
214 </tr>
215 <tr>
216 <td width="136"><font face="Arial" size="2">MS-PL.txt</font></td>
217 <td width="358"><font face="Arial" size="2">Microsoft Public License</font></td>
218 </tr>
219 <tr>
220 <td width="494" colspan="2">&nbsp;</td>
221 </tr>
222 <tr>
223 <td width="494" colspan="2"><font face="Arial" size="2">include\</font></td>
224 </tr>
225 <tr>
226 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlapp.h</font></td>
227 <td width="358"><font face="Arial" size="2">message loop, interfaces,
228 general app stuff</font></td>
229 </tr>
230 <tr>
231 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlcrack.h</font></td>
232 <td width="358"><font face="Arial" size="2">message cracker macros</font></td>
233 </tr>
234 <tr>
235 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlctrls.h</font></td>
236 <td width="358"><font face="Arial" size="2">standard and common control
237 classes</font></td>
238 </tr>
239 <tr>
240 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlctrlw.h</font></td>
241 <td width="358"><font face="Arial" size="2">command bar class</font></td>
242 </tr>
243 <tr>
244 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlctrlx.h</font></td>
245 <td width="358"><font face="Arial" size="2">bitmap button, check list view,
246 and other controls</font></td>
247 </tr>
248 <tr>
249 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlddx.h</font></td>
250 <td width="358"><font face="Arial" size="2">data exchange for dialogs and
251 windows</font></td>
252 </tr>
253 <tr>
254 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atldlgs.h</font></td>
255 <td width="358"><font face="Arial" size="2">common dialog classes, property
256 sheet and page classes</font></td>
257 </tr>
258 <tr>
259 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atldwm.h</font></td>
260 <td width="358"><font face="Arial" size="2">DWM support classes</font></td>
261 </tr>
262 <tr>
263 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlfind.h</font></td>
264 <td width="358"><font face="Arial" size="2">Find/Replace support for Edit
265 and RichEdit</font></td>
266 </tr>
267 <tr>
268 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlframe.h</font></td>
269 <td width="358"><font face="Arial" size="2">frame window classes, MDI,
270 update UI classes</font></td>
271 </tr>
272 <tr>
273 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlgdi.h</font></td>
274 <td width="358"><font face="Arial" size="2">DC classes, GDI object classes</font></td>
275 </tr>
276 <tr>
277 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlmisc.h</font></td>
278 <td width="358"><font face="Arial" size="2">WTL ports of CPoint, CRect,
279 CSize, CString, etc.</font></td>
280 </tr>
281 <tr>
282 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlprint.h</font></td>
283 <td width="358"><font face="Arial" size="2">printing and print preview</font></td>
284 </tr>
285 <tr>
286 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlres.h</font></td>
287 <td width="358"><font face="Arial" size="2">standard resource IDs</font></td>
288 </tr>
289 <tr>
290 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlresce.h</font></td>
291 <td width="358"><font face="Arial" size="2">standard resource IDs for
292 Windows CE</font></td>
293 </tr>
294 <tr>
295 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlribbon.h</font></td>
296 <td width="358"><font face="Arial" size="2">RibbonUI support</font></td>
297 </tr>
298 <tr>
299 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlscrl.h</font></td>
300 <td width="358"><font face="Arial" size="2">scrollable windows</font></td>
301 </tr>
302 <tr>
303 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlsplit.h</font></td>
304 <td width="358"><font face="Arial" size="2">splitter windows</font></td>
305 </tr>
306 <tr>
307 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atltheme.h</font></td>
308 <td width="358"><font face="Arial" size="2">Windows XP theme classes</font></td>
309 </tr>
310 <tr>
311 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atluser.h</font></td>
312 <td width="358"><font face="Arial" size="2">menu class, USER object classes</font></td>
313 </tr>
314 <tr>
315 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlwince.h</font></td>
316 <td width="358"><font face="Arial" size="2">specific support for Windows CE
317 Mobile platforms</font></td>
318 </tr>
319 <tr>
320 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; atlwinx.h</font></td>
321 <td width="358"><font face="Arial" size="2">extensions of ATL windowing
322 support</font></td>
323 </tr>
324 <tr>
325 <td width="494" colspan="2">&nbsp;</td>
326 </tr>
327 <tr>
328 <td width="494" colspan="2"><font face="Arial" size="2">Samples\</font></td>
329 </tr>
330 <tr>
331 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Aero\...</font></td>
332 <td width="358"><font face="Arial" size="2">Vista Aero glass showcase</font></td>
333 </tr>
334 <tr>
335 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Alpha\...</font></td>
336 <td width="358"><font face="Arial" size="2">Windows XP 32-bit (alpha)
337 toolbar images</font></td>
338 </tr>
339 <tr>
340 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; BmpView\...</font></td>
341 <td width="358"><font face="Arial" size="2">bitmap file view sample</font></td>
342 </tr>
343 <tr>
344 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; GuidGen\...</font></td>
345 <td width="358"><font face="Arial" size="2">WTL version of the GuidGen
346 sample</font></td>
347 </tr>
348 <tr>
349 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; ImageView\...</font></td>
350 <td width="358"><font face="Arial" size="2">Full-featured PPC frame-view
351 application</font></td>
352 </tr>
353 <tr>
354 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MDIDocVw\...</font></td>
355 <td width="358"><font face="Arial" size="2">WTL version of the MDI sample</font></td>
356 </tr>
357 <tr>
358 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MemDlg\...</font></td>
359 <td width="358"><font face="Arial" size="2">In-memory dialog sample</font></td>
360 </tr>
361 <tr>
362 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MiniPie\...</font></td>
363 <td width="358"><font face="Arial" size="2">port of the SDK sample for
364 Mobile devices</font></td>
365 </tr>
366 <tr>
367 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MTPad\...</font></td>
368 <td width="358"><font face="Arial" size="2">multithreaded notepad sample</font></td>
369 </tr>
370 <tr>
371 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; MTPad7\...</font></td>
372 <td width="358"><font face="Arial" size="2">MTPad with RibbonUI</font></td>
373 </tr>
374 <tr>
375 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; SPControls\...</font></td>
376 <td width="358"><font face="Arial" size="2">Barebone SmartPhone dialog
377 application</font></td>
378 </tr>
379 <tr>
380 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; TabBrowser\...</font></td>
381 <td width="358"><font face="Arial" size="2">Web browser using TabView</font></td>
382 </tr>
383 <tr>
384 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Wizard97Test\...</font></td>
385 <td width="358"><font face="Arial" size="2">Wizard97 showcase
386 sample</font></td>
387 </tr>
388 <tr>
389 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; WTLExplorer\...</font></td>
390 <td width="358"><font face="Arial" size="2">Explorer-like application
391 sample</font></td>
392 </tr>
393 <tr>
394 <td width="494" colspan="2">&nbsp;</td>
395 </tr>
396 <tr>
397 <td width="494" colspan="2"><font face="Arial" size="2">AppWiz\</font></td>
398 </tr>
399 <tr>
400 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup.js</font></td>
401 <td width="358"><font face="Arial" size="2">AppWizard setup program for all versions of
402 Visual Studio</font></td>
403 </tr>
404 <tr>
405 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Files\...</font></td>
406 <td width="358"><font face="Arial" size="2">WTL AppWizard files</font></td>
407 </tr>
408 <tr>
409 <td width="494" colspan="2">&nbsp;</td>
410 </tr>
411 <tr>
412 <td width="494" colspan="2"><font face="Arial" size="2">AppWizCE\</font></td>
413 </tr>
414 <tr>
415 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup80.js</font></td>
416 <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++
417 2005</font></td>
418 </tr>
419 <tr>
420 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup90.js</font></td>
421 <td width="358"><font face="Arial" size="2">AppWizard setup program for VC++
422 2008</font></td>
423 </tr>
424 <tr>
425 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Files\...</font></td>
426 <td width="358"><font face="Arial" size="2">WTL AppWizard CE files</font></td>
427 </tr>
428 <tr>
429 <td width="494" colspan="2">&nbsp;</td>
430 </tr>
431 <tr>
432 <td width="494" colspan="2"><font face="Arial" size="2">AppWizMobile\</font></td>
433 </tr>
434 <tr>
435 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup80.js</font></td>
436 <td width="358"><font face="Arial" size="2">AppWizard Mobile setup program for VC++
437 2005</font></td>
438 </tr>
439 <tr>
440 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; setup90.js</font></td>
441 <td width="358"><font face="Arial" size="2">AppWizard Mobile setup program for VC++
442 2008</font></td>
443 </tr>
444 <tr>
445 <td width="136"><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; Files\...</font></td>
446 <td width="358"><font face="Arial" size="2">WTL AppWizard Mobile files</font></td>
447 </tr>
448 </table>
449 <p style=margin:0in>&nbsp;</p>
450 <p style=margin:0in>&nbsp;</p>
451 <p style=margin:0in><font face="Arial">
452 <b><a name="Class Overview"></a>Class Overview</b></font></p>
453 <p style=margin:0in>&nbsp;</p>
454 <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber4">
455 <tr>
456 <td><font face="Arial" size="2">usage:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
457 </font></td>
458 <td><font face="Arial" size="2"><b>mi base</b></font></td>
459 <td>&nbsp;&nbsp; -</td>
460 <td><font face="Arial" size="2">&nbsp;&nbsp; a base class (multiple
461 inheritance)</font></td>
462 </tr>
463 <tr>
464 <td>&nbsp;</td>
465 <td><font face="Arial" size="2"><b>client</b></font></td>
466 <td>&nbsp;&nbsp; -</td>
467 <td><font face="Arial" size="2">&nbsp;&nbsp; wrapper class for a handle</font></td>
468 </tr>
469 <tr>
470 <td>&nbsp;</td>
471 <td><font face="Arial" size="2"><b>as-is</b></font></td>
472 <td>&nbsp;&nbsp; -</td>
473 <td><font face="Arial" size="2">&nbsp;&nbsp; to be used directly</font></td>
474 </tr>
475 <tr>
476 <td>&nbsp;</td>
477 <td><font face="Arial" size="2"><b>impl</b></font></td>
478 <td>&nbsp;&nbsp; -</td>
479 <td><font face="Arial" size="2">&nbsp;&nbsp; implements a window (has
480 WindowProc) or other support</font></td>
481 </tr>
482 <tr>
483 <td>&nbsp;</td>
484 <td><font face="Arial" size="2"><b>helper</b></font></td>
485 <td>&nbsp;&nbsp; -</td>
486 <td><font face="Arial" size="2">&nbsp;&nbsp; a helper class</font></td>
487 </tr>
488 <tr>
489 <td>&nbsp;</td>
490 <td><font face="Arial" size="2"><b>base</b></font></td>
491 <td>&nbsp;&nbsp; -</td>
492 <td><font face="Arial" size="2">&nbsp;&nbsp; implementation base class</font></td>
493 </tr>
494 </table>
495 <p style=margin:0in>&nbsp;</p>
496 <table border="1" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber1" width="600">
497 <tr>
498 <td width="220"><b><font face="Arial" size="2">class name:</font></b></td>
499 <td width="114"><b><font face="Arial" size="2">usage:</font></b></td>
500 <td width="253"><b><font face="Arial" size="2">description:</font></b></td>
501 </tr>
502 <tr>
503 <td colspan="3" width="593"><font size="2" face="Arial"><br>App/module support</font></td>
504 </tr>
505 <tr>
506 <td width="221"><b><font face="Arial" size="2">CAppModule</font></b></td>
507 <td width="115"><font face="Arial" size="2">as-is</font></td>
508 <td width="255"><font face="Arial" size="2">app support, CComModule derived</font></td>
509 </tr>
510 <tr>
511 <td width="221"><b><font face="Arial" size="2">CServerAppModule</font></b></td>
512 <td width="115"><font face="Arial" size="2">as-is</font></td>
513 <td width="255"><font face="Arial" size="2">module for COM servers</font></td>
514 </tr>
515 <tr>
516 <td width="221"><b><font face="Arial" size="2">CMessageLoop</font></b></td>
517 <td width="115"><font face="Arial" size="2">as-is</font></td>
518 <td width="255"><font face="Arial" size="2">message loop</font></td>
519 </tr>
520 <tr>
521 <td width="221"><b><font face="Arial" size="2">CMessageFilter</font></b></td>
522 <td width="115"><font face="Arial" size="2">mi base</font></td>
523 <td width="255"><font face="Arial" size="2">message filter interface</font></td>
524 </tr>
525 <tr>
526 <td width="221"><b><font face="Arial" size="2">CIdleHandler</font></b></td>
527 <td width="115"><font face="Arial" size="2">mi base</font></td>
528 <td width="255"><font face="Arial" size="2">idle time handler interface</font></td>
529 </tr>
530 <tr>
531 <td colspan="3" width="593"><font face="Arial" size="2"><br>Frame windows</font></td>
532 </tr>
533 <tr>
534 <td width="221"><b><font face="Arial" size="2">CFrameWindowImplBase</font></b></td>
535 <td width="115"><font face="Arial" size="2">base</font></td>
536 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
537 </tr>
538 <tr>
539 <td width="221"><b><font face="Arial" size="2">CFrameWindowImpl</font></b></td>
540 <td width="115"><font face="Arial" size="2">impl</font></td>
541 <td width="255"><font face="Arial" size="2">frame window support</font></td>
542 </tr>
543 <tr>
544 <td width="221"><b><font face="Arial" size="2">COwnerDraw</font></b></td>
545 <td width="115"><font face="Arial" size="2">impl mi base</font></td>
546 <td width="255"><font face="Arial" size="2">owner-draw msg map and handlers</font></td>
547 </tr>
548 <tr>
549 <td width="221"><b><font face="Arial" size="2">CDialogResize</font>
550 </b></td>
551 <td width="115"><font face="Arial" size="2">impl mi base</font></td>
552 <td width="255"><font face="Arial" size="2">support for resizing dialogs</font></td>
553 </tr>
554 <tr>
555 <td width="221"><b><font face="Arial" size="2">CDoubleBufferImpl</font>
556 </b></td>
557 <td width="115"><font face="Arial" size="2">impl mi</font></td>
558 <td width="255"><font face="Arial" size="2">double-buffer painting support</font></td>
559 </tr>
560 <tr>
561 <td width="221"><b><font face="Arial" size="2">CDoubleBufferWindowImpl</font>
562 </b></td>
563 <td width="115"><font face="Arial" size="2">impl</font></td>
564 <td width="255"><font face="Arial" size="2">double-buffer painting window</font></td>
565 </tr>
566 <tr>
567 <td colspan="3" width="593"><font face="Arial" size="2"><br>MDI windows</font></td>
568 </tr>
569 <tr>
570 <td width="221"><b><font face="Arial" size="2">CMDIWindow</font></b></td>
571 <td width="115"><font face="Arial" size="2">client</font></td>
572 <td width="255"><font face="Arial" size="2">MDI methods</font></td>
573 </tr>
574 <tr>
575 <td width="221"><b><font face="Arial" size="2">CMDIFrameWindowImpl</font></b></td>
576 <td width="115"><font face="Arial" size="2">impl</font></td>
577 <td width="255"><font face="Arial" size="2">MDI frame window</font></td>
578 </tr>
579 <tr>
580 <td width="221"><b><font face="Arial" size="2">CMDIChildWindowImpl</font></b></td>
581 <td width="115"><font face="Arial" size="2">impl</font></td>
582 <td width="255"><font face="Arial" size="2">MDI child window</font></td>
583 </tr>
584 <tr>
585 <td colspan="3" width="593"><font face="Arial" size="2"><br>Update UI</font></td>
586 </tr>
587 <tr>
588 <td width="221"><b><font face="Arial" size="2">CUpdateUIBase</font></b></td>
589 <td width="115"><font face="Arial" size="2">base</font></td>
590 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
591 </tr>
592 <tr>
593 <td width="221"><b><font face="Arial" size="2">CUpdateUI</font></b></td>
594 <td width="115"><font face="Arial" size="2">mi base class</font></td>
595 <td width="255"><font face="Arial" size="2">provides support for UI update</font></td>
596 </tr>
597 <tr>
598 <td width="221"><b><font face="Arial" size="2">CDynamicUpdateUI</font></b></td>
599 <td width="115"><font face="Arial" size="2">mi base class</font></td>
600 <td width="255"><font face="Arial" size="2">provides dynamic support for UI update</font></td>
601 </tr>
602 <tr>
603 <td colspan="3" width="593"><font face="Arial" size="2"><br>Standard controls</font></td>
604 </tr>
605 <tr>
606 <td width="221"><b><font face="Arial" size="2">CStatic</font></b></td>
607 <td width="115"><font face="Arial" size="2">client</font></td>
608 <td width="255"><font face="Arial" size="2">static ctrl</font></td>
609 </tr>
610 <tr>
611 <td width="221"><b><font face="Arial" size="2">CButton</font></b></td>
612 <td width="115"><font face="Arial" size="2">client</font></td>
613 <td width="255"><font face="Arial" size="2">button ctrl</font></td>
614 </tr>
615 <tr>
616 <td width="221"><b><font face="Arial" size="2">CListBox</font></b></td>
617 <td width="115"><font face="Arial" size="2">client</font></td>
618 <td width="255"><font face="Arial" size="2">list box ctrl</font></td>
619 </tr>
620 <tr>
621 <td width="221"><b><font face="Arial" size="2">CComboBox</font></b></td>
622 <td width="115"><font face="Arial" size="2">client</font></td>
623 <td width="255"><font face="Arial" size="2">combo box ctrl</font></td>
624 </tr>
625 <tr>
626 <td width="221"><b><font face="Arial" size="2">CEdit</font></b></td>
627 <td width="115"><font face="Arial" size="2">client</font></td>
628 <td width="255"><font face="Arial" size="2">edit ctrl</font></td>
629 </tr>
630 <tr>
631 <td width="221"><b><font face="Arial" size="2">CEditCommands</font></b></td>
632 <td width="115"><font face="Arial" size="2">mi</font></td>
633 <td width="255"><font face="Arial" size="2">standard edit command support</font></td>
634 </tr>
635 <tr>
636 <td width="221"><b><font face="Arial" size="2">CScrollBar</font></b></td>
637 <td width="115"><font face="Arial" size="2">client</font></td>
638 <td width="255"><font face="Arial" size="2">scroll bar ctrl</font></td>
639 </tr>
640 <tr>
641 <td colspan="3" width="593"><font face="Arial" size="2"><br>Common controls</font></td>
642 </tr>
643 <tr>
644 <td width="221"><b><font face="Arial" size="2">CImageList</font></b></td>
645 <td width="115"><font face="Arial" size="2">client</font></td>
646 <td width="255"><font face="Arial" size="2">image list</font></td>
647 </tr>
648 <tr>
649 <td width="221"><b><font face="Arial" size="2">CListViewCtrl</font></b></td>
650 <td width="115"><font face="Arial" size="2">client</font></td>
651 <td width="255"><font face="Arial" size="2">list view ctrl</font></td>
652 </tr>
653 <tr>
654 <td width="221"><b><font face="Arial" size="2">CTreeViewCtrl</font></b></td>
655 <td width="115"><font face="Arial" size="2">client</font></td>
656 <td width="255"><font face="Arial" size="2">tree view ctrl</font></td>
657 </tr>
658 <tr>
659 <td width="221"><b><font face="Arial" size="2">CTreeItem</font></b></td>
660 <td width="115"><font face="Arial" size="2">helper</font></td>
661 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
662 </tr>
663 <tr>
664 <td width="221"><b><font face="Arial" size="2">CTreeViewCtrlEx</font></b></td>
665 <td width="115"><font face="Arial" size="2">client</font></td>
666 <td width="255"><font face="Arial" size="2">uses CTreeItem</font></td>
667 </tr>
668 <tr>
669 <td width="221"><b><font face="Arial" size="2">CHeaderCtrl</font></b></td>
670 <td width="115"><font face="Arial" size="2">client</font></td>
671 <td width="255"><font face="Arial" size="2">header bar ctrl</font></td>
672 </tr>
673 <tr>
674 <td width="221"><b><font face="Arial" size="2">CToolBarCtrl</font></b></td>
675 <td width="115"><font face="Arial" size="2">client</font></td>
676 <td width="255"><font face="Arial" size="2">toolbar ctrl</font></td>
677 </tr>
678 <tr>
679 <td width="221"><b><font face="Arial" size="2">CStatusBarCtrl</font></b></td>
680 <td width="115"><font face="Arial" size="2">client</font></td>
681 <td width="255"><font face="Arial" size="2">status bar ctrl</font></td>
682 </tr>
683 <tr>
684 <td width="221"><b><font face="Arial" size="2">CTabCtrl</font></b></td>
685 <td width="115"><font face="Arial" size="2">client</font></td>
686 <td width="255"><font face="Arial" size="2">tab ctrl</font></td>
687 </tr>
688 <tr>
689 <td width="221"><b><font face="Arial" size="2">CToolTipCtrl</font></b></td>
690 <td width="115"><font face="Arial" size="2">client</font></td>
691 <td width="255"><font face="Arial" size="2">tool tip ctrl</font></td>
692 </tr>
693 <tr>
694 <td width="221"><b><font face="Arial" size="2">CToolInfo</font></b></td>
695 <td width="115"><font face="Arial" size="2">helper</font></td>
696 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
697 </tr>
698 <tr>
699 <td width="221"><b><font face="Arial" size="2">CTrackBarCtrl</font></b></td>
700 <td width="115"><font face="Arial" size="2">client</font></td>
701 <td width="255"><font face="Arial" size="2">trackbar ctrl</font></td>
702 </tr>
703 <tr>
704 <td width="221"><b><font face="Arial" size="2">CUpDownCtrl</font></b></td>
705 <td width="115"><font face="Arial" size="2">client</font></td>
706 <td width="255"><font face="Arial" size="2">up-down ctrl</font></td>
707 </tr>
708 <tr>
709 <td width="221"><b><font face="Arial" size="2">CProgressBarCtrl</font></b></td>
710 <td width="115"><font face="Arial" size="2">client</font></td>
711 <td width="255"><font face="Arial" size="2">progress bar ctrl</font></td>
712 </tr>
713 <tr>
714 <td width="221"><b><font face="Arial" size="2">CHotKeyCtrl</font></b></td>
715 <td width="115"><font face="Arial" size="2">client</font></td>
716 <td width="255"><font face="Arial" size="2">hot key ctrl</font></td>
717 </tr>
718 <tr>
719 <td width="221"><b><font face="Arial" size="2">CAnimateCtrl</font></b></td>
720 <td width="115"><font face="Arial" size="2">client</font></td>
721 <td width="255"><font face="Arial" size="2">animation ctrl</font></td>
722 </tr>
723 <tr>
724 <td width="221"><b><font face="Arial" size="2">CRichEditCtrl</font></b></td>
725 <td width="115"><font face="Arial" size="2">client</font></td>
726 <td width="255"><font face="Arial" size="2">rich edit ctrl</font></td>
727 </tr>
728 <tr>
729 <td width="221"><b><font face="Arial" size="2">CRichEditCommands</font></b></td>
730 <td width="115"><font face="Arial" size="2">mi</font></td>
731 <td width="255"><font face="Arial" size="2">std rich edit commands support</font></td>
732 </tr>
733 <tr>
734 <td width="221"><b><font face="Arial" size="2">CDragListBox</font></b></td>
735 <td width="115"><font face="Arial" size="2">client</font></td>
736 <td width="255"><font face="Arial" size="2">drag list box</font></td>
737 </tr>
738 <tr>
739 <td width="221"><b><font face="Arial" size="2">CDragListNotifyImpl</font></b></td>
740 <td width="115"><font face="Arial" size="2">impl mi class</font></td>
741 <td width="255"><font face="Arial" size="2">support for notifications</font></td>
742 </tr>
743 <tr>
744 <td width="221"><b><font face="Arial" size="2">CReBarCtrl</font></b></td>
745 <td width="115"><font face="Arial" size="2">client</font></td>
746 <td width="255"><font face="Arial" size="2">rebar ctrl</font></td>
747 </tr>
748 <tr>
749 <td width="221"><b><font face="Arial" size="2">CComboBoxEx</font></b></td>
750 <td width="115"><font face="Arial" size="2">client</font></td>
751 <td width="255"><font face="Arial" size="2">extended combo box</font></td>
752 </tr>
753 <tr>
754 <td width="221"><b><font face="Arial" size="2">CDateTimePickerCtrl</font></b></td>
755 <td width="115"><font face="Arial" size="2">client</font></td>
756 <td width="255"><font face="Arial" size="2">date-time ctrl</font></td>
757 </tr>
758 <tr>
759 <td width="221"><b><font face="Arial" size="2">CFlatScrollBarImpl</font></b></td>
760 <td width="115"><font face="Arial" size="2">mi impl</font></td>
761 <td width="255"><font face="Arial" size="2">flat scroll bars support</font></td>
762 </tr>
763 <tr>
764 <td width="221"><b><font face="Arial" size="2">CFlatScrollBar</font></b></td>
765 <td width="115"><font face="Arial" size="2">as-is</font></td>
766 <td width="255"><font face="Arial" size="2">flat scroll bars support</font></td>
767 </tr>
768 <tr>
769 <td width="221"><b><font face="Arial" size="2">CIPAddressCtrl</font></b></td>
770 <td width="115"><font face="Arial" size="2">client</font></td>
771 <td width="255"><font face="Arial" size="2">IP address ctrl</font></td>
772 </tr>
773 <tr>
774 <td width="221"><b><font face="Arial" size="2">CMonthCalendarCtrl</font></b></td>
775 <td width="115"><font face="Arial" size="2">client</font></td>
776 <td width="255"><font face="Arial" size="2">month calendar ctrl</font></td>
777 </tr>
778 <tr>
779 <td width="221"><b><font face="Arial" size="2">CCustomDraw</font></b></td>
780 <td width="115"><font face="Arial" size="2">impl mi class</font></td>
781 <td width="255"><font face="Arial" size="2">custom draw handling support</font></td>
782 </tr>
783 <tr>
784 <td colspan="3" width="593"><font face="Arial" size="2"><br>Windows CE controls</font></td>
785 </tr>
786 <tr>
787 <td width="221"><b><font face="Arial" size="2">CCECommandBarCtrl</font></b></td>
788 <td width="115"><font face="Arial" size="2">client</font></td>
789 <td width="255"><font face="Arial" size="2">command bar ctrl</font></td>
790 </tr>
791 <tr>
792 <td width="221"><b><font face="Arial" size="2">CCECommandBandsCtrl</font></b></td>
793 <td width="115"><font face="Arial" size="2">client</font></td>
794 <td width="255"><font face="Arial" size="2">command bands ctrl</font></td>
795 </tr>
796 <tr>
797 <td colspan="3" width="593"><font face="Arial" size="2"><br>Property sheet &amp; page</font></td>
798 </tr>
799 <tr>
800 <td width="221"><b><font face="Arial" size="2">CPropertySheetWindow</font></b></td>
801 <td width="115"><font face="Arial" size="2">client</font></td>
802 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
803 </tr>
804 <tr>
805 <td width="221"><b><font face="Arial" size="2">CPropertySheetImpl</font></b></td>
806 <td width="115"><font face="Arial" size="2">impl</font></td>
807 <td width="255"><font face="Arial" size="2">property sheet </font></td>
808 </tr>
809 <tr>
810 <td width="221"><b><font face="Arial" size="2">CPropertySheet</font></b></td>
811 <td width="115"><font face="Arial" size="2">as-is</font></td>
812 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
813 </tr>
814 <tr>
815 <td width="221"><b><font face="Arial" size="2">CPropertyPageWindow</font></b></td>
816 <td width="115"><font face="Arial" size="2">client</font></td>
817 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
818 </tr>
819 <tr>
820 <td width="221"><b><font face="Arial" size="2">CPropertyPageImpl</font></b></td>
821 <td width="115"><font face="Arial" size="2">impl</font></td>
822 <td width="255"><font face="Arial" size="2">property page</font></td>
823 </tr>
824 <tr>
825 <td width="221"><b><font face="Arial" size="2">CPropertyPage</font></b></td>
826 <td width="115"><font face="Arial" size="2">as-is</font></td>
827 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
828 </tr>
829 <tr>
830 <td width="221"><b><font face="Arial" size="2">CAxPropertyPageImpl</font></b></td>
831 <td width="115"><font face="Arial" size="2">impl</font></td>
832 <td width="255"><font face="Arial" size="2">property page with ActiveX</font></td>
833 </tr>
834 <tr>
835 <td width="221"><b><font face="Arial" size="2">CAxPropertyPage</font></b></td>
836 <td width="115"><font face="Arial" size="2">as-is</font></td>
837 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
838 </tr>
839 <tr>
840 <td width="221"><b><font face="Arial" size="2">CWizard97SheetWindow</font></b></td>
841 <td width="115"><font face="Arial" size="2">client</font></td>
842 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
843 </tr>
844 <tr>
845 <td width="221"><b><font face="Arial" size="2">CWizard97SheetImpl</font></b></td>
846 <td width="115"><font face="Arial" size="2">impl</font></td>
847 <td width="255"><font face="Arial" size="2">Wizard97 property sheet</font></td>
848 </tr>
849 <tr>
850 <td width="221"><b><font face="Arial" size="2">CWizard97Sheet</font></b></td>
851 <td width="115"><font face="Arial" size="2">as-is</font></td>
852 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
853 </tr>
854 <tr>
855 <td width="221"><b><font face="Arial" size="2">CWizard97PageWindow</font></b></td>
856 <td width="115"><font face="Arial" size="2">client</font></td>
857 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
858 </tr>
859 <tr>
860 <td width="221"><b><font face="Arial" size="2">CWizard97PageImpl</font></b></td>
861 <td width="115"><font face="Arial" size="2">impl</font></td>
862 <td width="255"><font face="Arial" size="2">Wizard97 property page</font></td>
863 </tr>
864 <tr>
865 <td width="221"><b><font face="Arial" size="2">CWizard97ExteriorPageImpl</font></b></td>
866 <td width="115"><font face="Arial" size="2">impl</font></td>
867 <td width="255"><font face="Arial" size="2">Wizard97 exterior page</font></td>
868 </tr>
869 <tr>
870 <td width="221"><b><font face="Arial" size="2">CWizard97InteriorPageImpl</font></b></td>
871 <td width="115"><font face="Arial" size="2">impl</font></td>
872 <td width="255"><font face="Arial" size="2">Wizard97 interior page</font></td>
873 </tr>
874 <tr>
875 <td width="221"><b><font face="Arial" size="2">CAeroWizardFrameWindow</font></b></td>
876 <td width="115"><font face="Arial" size="2">client</font></td>
877 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
878 </tr>
879 <tr>
880 <td width="221"><b><font face="Arial" size="2">CAeroWizardFrameImpl</font></b></td>
881 <td width="115"><font face="Arial" size="2">impl</font></td>
882 <td width="255"><font face="Arial" size="2">Aero Wizard frame</font></td>
883 </tr>
884 <tr>
885 <td width="221"><b><font face="Arial" size="2">CAeroWizardFrame</font></b></td>
886 <td width="115"><font face="Arial" size="2">as-is</font></td>
887 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
888 </tr>
889 <tr>
890 <td width="221"><b><font face="Arial" size="2">CAeroWizardPageWindow</font></b></td>
891 <td width="115"><font face="Arial" size="2">client</font></td>
892 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
893 </tr>
894 <tr>
895 <td width="221"><b><font face="Arial" size="2">CAeroWizardPageImpl</font></b></td>
896 <td width="115"><font face="Arial" size="2">impl</font></td>
897 <td width="255"><font face="Arial" size="2">Aero Wizard page</font></td>
898 </tr>
899 <tr>
900 <td width="221"><b><font face="Arial" size="2">CAeroWizardPage</font></b></td>
901 <td width="115"><font face="Arial" size="2">as-is</font></td>
902 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
903 </tr>
904 <tr>
905 <td width="221"><b><font face="Arial" size="2">CAeroWizardAxPageImpl</font></b></td>
906 <td width="115"><font face="Arial" size="2">impl</font></td>
907 <td width="255"><font face="Arial" size="2">Aero Wizard page with ActiveX</font></td>
908 </tr>
909 <tr>
910 <td width="221"><b><font face="Arial" size="2">CAeroWizardAxPage</font></b></td>
911 <td width="115"><font face="Arial" size="2">as-is</font></td>
912 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
913 </tr>
914 <tr>
915 <td colspan="3" width="593"><font face="Arial" size="2"><br>Common dialogs</font></td>
916 </tr>
917 <tr>
918 <td width="221"><b><font face="Arial" size="2">CFileDialogImpl</font></b></td>
919 <td width="115"><font face="Arial" size="2">impl</font></td>
920 <td width="255"><font face="Arial" size="2">GetOpenFileName/GetSaveFileName</font></td>
921 </tr>
922 <tr>
923 <td width="221"><b><font face="Arial" size="2">CFileDialog</font></b></td>
924 <td width="115"><font face="Arial" size="2">as-is</font></td>
925 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
926 </tr>
927 <tr>
928 <td width="221"><b><font face="Arial" size="2">CMultiFileDialogImpl</font></b></td>
929 <td width="115"><font face="Arial" size="2">impl</font></td>
930 <td width="255"><font face="Arial" size="2">Multi-select GetOpenFileName</font></td>
931 </tr>
932 <tr>
933 <td width="221"><b><font face="Arial" size="2">CMultiFileDialog</font></b></td>
934 <td width="115"><font face="Arial" size="2">as-is</font></td>
935 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
936 </tr>
937 <tr>
938 <td width="221"><b><font face="Arial" size="2">CShellFileDialogImpl</font></b></td>
939 <td width="115"><font face="Arial" size="2">base</font></td>
940 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
941 </tr>
942 <tr>
943 <td width="221"><b><font face="Arial" size="2">CShellFileOpenDialogImpl</font></b></td>
944 <td width="115"><font face="Arial" size="2">impl</font></td>
945 <td width="255"><font face="Arial" size="2">Shell File Open dialog</font></td>
946 </tr>
947 <tr>
948 <td width="221"><b><font face="Arial" size="2">CShellFileOpenDialog</font></b></td>
949 <td width="115"><font face="Arial" size="2">as-is</font></td>
950 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
951 </tr>
952 <tr>
953 <td width="221"><b><font face="Arial" size="2">CShellFileSaveDialogImpl</font></b></td>
954 <td width="115"><font face="Arial" size="2">impl</font></td>
955 <td width="255"><font face="Arial" size="2">Shell File Save dialog</font></td>
956 </tr>
957 <tr>
958 <td width="221"><b><font face="Arial" size="2">CShellFileSaveDialog</font></b></td>
959 <td width="115"><font face="Arial" size="2">as-is</font></td>
960 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
961 </tr>
962 <tr>
963 <td width="221"><b><font face="Arial" size="2">CFolderDialogImpl</font></b></td>
964 <td width="115"><font face="Arial" size="2">impl</font></td>
965 <td width="255"><font face="Arial" size="2">directory picker</font></td>
966 </tr>
967 <tr>
968 <td width="221"><b><font face="Arial" size="2">CFolderDialog</font></b></td>
969 <td width="115"><font face="Arial" size="2">as-is</font></td>
970 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
971 </tr>
972 <tr>
973 <td width="221"><b><font face="Arial" size="2">CFontDialogImpl</font></b></td>
974 <td width="115"><font face="Arial" size="2">impl</font></td>
975 <td width="255"><font face="Arial" size="2">ChooseFont common dialog</font></td>
976 </tr>
977 <tr>
978 <td width="221"><b><font face="Arial" size="2">CFontDialog</font></b></td>
979 <td width="115"><font face="Arial" size="2">as-is</font></td>
980 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
981 </tr>
982 <tr>
983 <td width="221"><b><font face="Arial" size="2">CRichEditFontDialogImpl</font></b></td>
984 <td width="115"><font face="Arial" size="2">impl</font></td>
985 <td width="255"><font face="Arial" size="2">ChooseFont for rich edit</font></td>
986 </tr>
987 <tr>
988 <td width="221"><b><font face="Arial" size="2">CRichEditFontDialog</font></b></td>
989 <td width="115"><font face="Arial" size="2">as-is</font></td>
990 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
991 </tr>
992 <tr>
993 <td width="221"><b><font face="Arial" size="2">CColorDialogImpl</font></b></td>
994 <td width="115"><font face="Arial" size="2">impl</font></td>
995 <td width="255"><font face="Arial" size="2">ChooseColor common dialog</font></td>
996 </tr>
997 <tr>
998 <td width="221"><b><font face="Arial" size="2">CColorDialog</font></b></td>
999 <td width="115"><font face="Arial" size="2">as-is</font></td>
1000 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1001 </tr>
1002 <tr>
1003 <td width="221"><b><font face="Arial" size="2">CPrintDialogImpl</font></b></td>
1004 <td width="115"><font face="Arial" size="2">impl</font></td>
1005 <td width="255"><font face="Arial" size="2">PrintDlg common dialog</font></td>
1006 </tr>
1007 <tr>
1008 <td width="221"><b><font face="Arial" size="2">CPrintDialog</font></b></td>
1009 <td width="115"><font face="Arial" size="2">as-is</font></td>
1010 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1011 </tr>
1012 <tr>
1013 <td width="221"><b><font face="Arial" size="2">CPrintDialogExImpl</font></b></td>
1014 <td width="115"><font face="Arial" size="2">impl</font></td>
1015 <td width="255"><font face="Arial" size="2">new Win2000 print dialog</font></td>
1016 </tr>
1017 <tr>
1018 <td width="221"><b><font face="Arial" size="2">CPrintDialogEx</font></b></td>
1019 <td width="115"><font face="Arial" size="2">as-is</font></td>
1020 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1021 </tr>
1022 <tr>
1023 <td width="221"><b><font face="Arial" size="2">CPageSetupDialogImpl</font></b></td>
1024 <td width="115"><font face="Arial" size="2">impl</font></td>
1025 <td width="255"><font face="Arial" size="2">PageSetupDlg common dialog</font></td>
1026 </tr>
1027 <tr>
1028 <td width="221"><b><font face="Arial" size="2">CPageSetupDialog</font></b></td>
1029 <td width="115"><font face="Arial" size="2">as-is</font></td>
1030 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1031 </tr>
1032 <tr>
1033 <td width="221"><b><font face="Arial" size="2">CFindReplaceDialogImpl</font></b></td>
1034 <td width="115"><font face="Arial" size="2">impl</font></td>
1035 <td width="255"><font face="Arial" size="2">FindText/ReplaceText</font></td>
1036 </tr>
1037 <tr>
1038 <td width="221"><b><font face="Arial" size="2">CFindReplaceDialog</font></b></td>
1039 <td width="115"><font face="Arial" size="2">as-is</font></td>
1040 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1041 </tr>
1042 <tr>
1043 <td colspan="3" width="593"><font face="Arial" size="2"><br>User support</font></td>
1044 </tr>
1045 <tr>
1046 <td width="221"><b><font face="Arial" size="2">CMenu</font></b></td>
1047 <td width="115"><font face="Arial" size="2">client</font></td>
1048 <td width="255"><font face="Arial" size="2">menu support</font></td>
1049 </tr>
1050 <tr>
1051 <td width="221"><b><font face="Arial" size="2">CMenuItemInfo</font></b></td>
1052 <td width="115"><font face="Arial" size="2">as-is</font></td>
1053 <td width="255"><font face="Arial" size="2">MENUITEMINFO wrapper</font></td>
1054 </tr>
1055 <tr>
1056 <td width="221"><b><font face="Arial" size="2">CAccelerator</font></b></td>
1057 <td width="115"><font face="Arial" size="2">client</font></td>
1058 <td width="255"><font face="Arial" size="2">accelerator table</font></td>
1059 </tr>
1060 <tr>
1061 <td width="221"><b><font face="Arial" size="2">CIcon</font></b></td>
1062 <td width="115"><font face="Arial" size="2">client</font></td>
1063 <td width="255"><font face="Arial" size="2">icon object</font></td>
1064 </tr>
1065 <tr>
1066 <td width="221"><b><font face="Arial" size="2">CCursor</font></b></td>
1067 <td width="115"><font face="Arial" size="2">client</font></td>
1068 <td width="255"><font face="Arial" size="2">cursor object</font></td>
1069 </tr>
1070 <tr>
1071 <td width="221"><b><font face="Arial" size="2">CResource</font></b></td>
1072 <td width="115"><font face="Arial" size="2">client</font></td>
1073 <td width="255"><font face="Arial" size="2">generic resource object</font></td>
1074 </tr>
1075 <tr>
1076 <td colspan="3" width="593"><font face="Arial" size="2"><br>GDI support</font></td>
1077 </tr>
1078 <tr>
1079 <td width="221"><b><font face="Arial" size="2">CDC</font></b></td>
1080 <td width="115"><font face="Arial" size="2">client</font></td>
1081 <td width="255"><font face="Arial" size="2">DC support</font></td>
1082 </tr>
1083 <tr>
1084 <td width="221"><b><font face="Arial" size="2">CPaintDC</font></b></td>
1085 <td width="115"><font face="Arial" size="2">client</font></td>
1086 <td width="255"><font face="Arial" size="2">for handling WM_PAINT</font></td>
1087 </tr>
1088 <tr>
1089 <td width="221"><b><font face="Arial" size="2">CClientDC</font></b></td>
1090 <td width="115"><font face="Arial" size="2">client</font></td>
1091 <td width="255"><font face="Arial" size="2">for GetDC</font></td>
1092 </tr>
1093 <tr>
1094 <td width="221"><b><font face="Arial" size="2">CWindowDC</font></b></td>
1095 <td width="115"><font face="Arial" size="2">client</font></td>
1096 <td width="255"><font face="Arial" size="2">for GetWindowDC</font></td>
1097 </tr>
1098 <tr>
1099 <td width="221"><b><font face="Arial" size="2">CMemoryDC</font></b></td>
1100 <td width="115"><font face="Arial" size="2">client</font></td>
1101 <td width="255"><font face="Arial" size="2">in-memory DC</font></td>
1102 </tr>
1103 <tr>
1104 <td width="221"><b><font face="Arial" size="2">CPen</font></b></td>
1105 <td width="115"><font face="Arial" size="2">client</font></td>
1106 <td width="255"><font face="Arial" size="2">GDI pen object</font></td>
1107 </tr>
1108 <tr>
1109 <td width="221"><b><font face="Arial" size="2">CBrush</font></b></td>
1110 <td width="115"><font face="Arial" size="2">client</font></td>
1111 <td width="255"><font face="Arial" size="2">GDI brush object</font></td>
1112 </tr>
1113 <tr>
1114 <td width="221"><b><font face="Arial" size="2">CLogFont</font></b></td>
1115 <td width="115"><font face="Arial" size="2">as-is</font></td>
1116 <td width="255"><font face="Arial" size="2">LOGFONT wrapper</font></td>
1117 </tr>
1118 <tr>
1119 <td width="221"><b><font face="Arial" size="2">CFont</font></b></td>
1120 <td width="115"><font face="Arial" size="2">client</font></td>
1121 <td width="255"><font face="Arial" size="2">GDI font object</font></td>
1122 </tr>
1123 <tr>
1124 <td width="221"><b><font face="Arial" size="2">CBitmap</font></b></td>
1125 <td width="115"><font face="Arial" size="2">client</font></td>
1126 <td width="255"><font face="Arial" size="2">GDI bitmap object</font></td>
1127 </tr>
1128 <tr>
1129 <td width="221"><b><font face="Arial" size="2">CPalette</font></b></td>
1130 <td width="115"><font face="Arial" size="2">client</font></td>
1131 <td width="255"><font face="Arial" size="2">GDI palette object</font></td>
1132 </tr>
1133 <tr>
1134 <td width="221"><b><font face="Arial" size="2">CRgn</font></b></td>
1135 <td width="115"><font face="Arial" size="2">client</font></td>
1136 <td width="255"><font face="Arial" size="2">GDI region object</font></td>
1137 </tr>
1138 <tr>
1139 <td colspan="3" width="593"><font face="Arial" size="2"><br>Enhanced controls</font></td>
1140 </tr>
1141 <tr>
1142 <td width="221"><b><font face="Arial" size="2">CCommandBarCtrlImpl</font></b></td>
1143 <td width="115"><font face="Arial" size="2">impl</font></td>
1144 <td width="255"><font face="Arial" size="2">command bar</font></td>
1145 </tr>
1146 <tr>
1147 <td width="221"><b><font face="Arial" size="2">CCommandBarCtrl</font></b></td>
1148 <td width="115"><font face="Arial" size="2">as-is</font></td>
1149 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1150 </tr>
1151 <tr>
1152 <td width="221"><b><font face="Arial" size="2">CBitmapButtonImpl</font></b></td>
1153 <td width="115"><font face="Arial" size="2">impl</font></td>
1154 <td width="255"><font face="Arial" size="2">bitmap button</font></td>
1155 </tr>
1156 <tr>
1157 <td width="221"><b><font face="Arial" size="2">CBitmapButton</font></b></td>
1158 <td width="115"><font face="Arial" size="2">as-is</font></td>
1159 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1160 </tr>
1161 <tr>
1162 <td width="221"><b><font face="Arial" size="2">CCheckListViewCtrlImpl</font></b></td>
1163 <td width="115"><font face="Arial" size="2">impl</font></td>
1164 <td width="255"><font face="Arial" size="2">check list box</font></td>
1165 </tr>
1166 <tr>
1167 <td width="221"><b><font face="Arial" size="2">CCheckListViewCtrl</font></b></td>
1168 <td width="115"><font face="Arial" size="2">as-is</font></td>
1169 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1170 </tr>
1171 <tr>
1172 <td width="221"><b><font face="Arial" size="2">CHyperLinkImpl</font></b></td>
1173 <td width="115"><font face="Arial" size="2">impl</font></td>
1174 <td width="255"><font face="Arial" size="2">hyper link control</font></td>
1175 </tr>
1176 <tr>
1177 <td width="221"><b><font face="Arial" size="2">CHyperLink</font></b></td>
1178 <td width="115"><font face="Arial" size="2">as-is</font></td>
1179 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1180 </tr>
1181 <tr>
1182 <td width="221"><b><font face="Arial" size="2">CWaitCursor</font></b></td>
1183 <td width="115"><font face="Arial" size="2">as-is</font></td>
1184 <td width="255"><font face="Arial" size="2">wait cursor</font></td>
1185 </tr>
1186 <tr>
1187 <td width="221"><b><font face="Arial" size="2">CCustomWaitCursor</font></b></td>
1188 <td width="115"><font face="Arial" size="2">as-is</font></td>
1189 <td width="255"><font face="Arial" size="2">custom and animated wait cursor</font></td>
1190 </tr>
1191 <tr>
1192 <td width="221"><b><font face="Arial" size="2">CMultiPaneStatusBarCtrlImpl</font></b></td>
1193 <td width="115"><font face="Arial" size="2">impl</font></td>
1194 <td width="255"><font face="Arial" size="2">status bar with multiple panes</font></td>
1195 </tr>
1196 <tr>
1197 <td width="221"><b><font face="Arial" size="2">CMultiPaneStatusBarCtrl</font></b></td>
1198 <td width="115"><font face="Arial" size="2">as-is</font></td>
1199 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1200 </tr>
1201 <tr>
1202 <td width="221"><b><font face="Arial" size="2">CPaneContainerImpl</font></b></td>
1203 <td width="115"><font face="Arial" size="2">impl</font></td>
1204 <td width="255"><font face="Arial" size="2">pane window container</font></td>
1205 </tr>
1206 <tr>
1207 <td width="221"><b><font face="Arial" size="2">CPaneContainer</font></b></td>
1208 <td width="115"><font face="Arial" size="2">as-is</font></td>
1209 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1210 </tr>
1211 <tr>
1212 <td width="221"><b><font face="Arial" size="2">CSortListViewImpl</font></b></td>
1213 <td width="115"><font face="Arial" size="2">impl</font></td>
1214 <td width="255"><font face="Arial" size="2">sorting list view control</font></td>
1215 </tr>
1216 <tr>
1217 <td width="221"><b><font face="Arial" size="2">CSortListViewCtrlImpl</font></b></td>
1218 <td width="115"><font face="Arial" size="2">impl</font></td>
1219 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1220 </tr>
1221 <tr>
1222 <td width="221"><b><font face="Arial" size="2">CSortListViewCtrl</font></b></td>
1223 <td width="115"><font face="Arial" size="2">as-is</font></td>
1224 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1225 </tr>
1226 <tr>
1227 <td width="221"><b><font face="Arial" size="2">CTabViewImpl;</font></b></td>
1228 <td width="115"><font face="Arial" size="2">impl</font></td>
1229 <td width="255"><font face="Arial" size="2">tab view window</font></td>
1230 </tr>
1231 <tr>
1232 <td width="221"><b><font face="Arial" size="2">CTabView</font></b></td>
1233 <td width="115"><font face="Arial" size="2">as-is</font></td>
1234 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1235 </tr>
1236 <tr>
1237 <td colspan="3" width="593"><font face="Arial" size="2"><br>Scrolling window support</font></td>
1238 </tr>
1239 <tr>
1240 <td width="221"><b><font face="Arial" size="2">CScrollImpl</font></b></td>
1241 <td width="115"><font face="Arial" size="2">impl mi</font></td>
1242 <td width="255"><font face="Arial" size="2">scrolling support</font></td>
1243 </tr>
1244 <tr>
1245 <td width="221"><b><font face="Arial" size="2">CScrollWindowImpl</font></b></td>
1246 <td width="115"><font face="Arial" size="2">impl</font></td>
1247 <td width="255"><font face="Arial" size="2">scrollable window</font></td>
1248 </tr>
1249 <tr>
1250 <td width="221"><b><font face="Arial" size="2">CMapScrollImpl</font></b></td>
1251 <td width="115"><font face="Arial" size="2">impl mi</font></td>
1252 <td width="255"><font face="Arial" size="2">scrolling support with map modes</font></td>
1253 </tr>
1254 <tr>
1255 <td width="221"><b><font face="Arial" size="2">CMapScrollWindowImpl</font></b></td>
1256 <td width="115"><font face="Arial" size="2">impl</font></td>
1257 <td width="255"><font face="Arial" size="2">scrollable window with map modes</font></td>
1258 </tr>
1259 <tr>
1260 <td width="221"><b><font face="Arial" size="2">CZoomScrollImpl</font></b></td>
1261 <td width="115"><font face="Arial" size="2">impl mi</font></td>
1262 <td width="255"><font face="Arial" size="2">zooming support</font></td>
1263 </tr>
1264 <tr>
1265 <td width="221"><b><font face="Arial" size="2">CZoomScrollWindowImpl</font></b></td>
1266 <td width="115"><font face="Arial" size="2">impl</font></td>
1267 <td width="255"><font face="Arial" size="2">zooming window</font></td>
1268 </tr>
1269 <tr>
1270 <td width="221"><b><font face="Arial" size="2">CScrollContainerImpl</font></b></td>
1271 <td width="115"><font face="Arial" size="2">impl</font></td>
1272 <td width="255"><font face="Arial" size="2">scroll container window</font></td>
1273 </tr>
1274 <tr>
1275 <td width="221"><b><font face="Arial" size="2">CScrollContainer</font></b></td>
1276 <td width="115"><font face="Arial" size="2">as-is</font></td>
1277 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1278 </tr>
1279 <tr>
1280 <td colspan="3" width="593"><font face="Arial" size="2"><br>Splitter window support</font></td>
1281 </tr>
1282 <tr>
1283 <td width="221"><b><font face="Arial" size="2">CSplitterImpl</font></b></td>
1284 <td width="115"><font face="Arial" size="2">impl mi</font></td>
1285 <td width="255"><font face="Arial" size="2">splitter support</font></td>
1286 </tr>
1287 <tr>
1288 <td width="221"><b><font face="Arial" size="2">CSplitterWindowImpl</font></b></td>
1289 <td width="115"><font face="Arial" size="2">impl</font></td>
1290 <td width="255"><font face="Arial" size="2">splitter window</font></td>
1291 </tr>
1292 <tr>
1293 <td width="221"><b><font face="Arial" size="2">CSplitterWindow</font></b></td>
1294 <td width="115"><font face="Arial" size="2">as-is</font></td>
1295 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1296 </tr>
1297 <tr>
1298 <td colspan="3" width="593"><font face="Arial" size="2"><br>Theming support</font></td>
1299 </tr>
1300 <tr>
1301 <td width="221"><b><font face="Arial" size="2">CTheme</font></b></td>
1302 <td width="115"><font face="Arial" size="2">client</font></td>
1303 <td width="255"><font face="Arial" size="2">Windows XP theme</font></td>
1304 </tr>
1305 <tr>
1306 <td width="221"><b><font face="Arial" size="2">CThemeImpl</font></b></td>
1307 <td width="115"><font face="Arial" size="2">impl</font></td>
1308 <td width="255"><font face="Arial" size="2">theming support for a window</font></td>
1309 </tr>
1310 <tr>
1311 <td colspan="3" width="593"><font face="Arial" size="2"><br>Buffered paint and animation support</font></td>
1312 </tr>
1313 <tr>
1314 <td width="221"><b><font face="Arial" size="2">CBufferedPaint</font></b></td>
1315 <td width="115"><font face="Arial" size="2">as-is</font></td>
1316 <td width="255"><font face="Arial" size="2">buffered paint</font></td>
1317 </tr>
1318 <tr>
1319 <td width="221"><b><font face="Arial" size="2">CBufferedPaintImpl</font></b></td>
1320 <td width="115"><font face="Arial" size="2">impl mi</font></td>
1321 <td width="255"><font face="Arial" size="2">buffered paint support</font></td>
1322 </tr>
1323 <tr>
1324 <td width="221"><b><font face="Arial" size="2">CBufferedPaintWindowImpl</font></b></td>
1325 <td width="115"><font face="Arial" size="2">impl</font></td>
1326 <td width="255"><font face="Arial" size="2">window with buffered paint</font></td>
1327 </tr>
1328 <tr>
1329 <td width="221"><b><font face="Arial" size="2">CBufferedAnimation</font></b></td>
1330 <td width="115"><font face="Arial" size="2">as-is</font></td>
1331 <td width="255"><font face="Arial" size="2">buffered animation</font></td>
1332 </tr>
1333 <tr>
1334 <td width="221"><b><font face="Arial" size="2">CBufferedAnimationImpl</font></b></td>
1335 <td width="115"><font face="Arial" size="2">impl mi</font></td>
1336 <td width="255"><font face="Arial" size="2">buffered animation support</font></td>
1337 </tr>
1338 <tr>
1339 <td width="221"><b><font face="Arial" size="2">CBufferedAnimationWindowImpl</font></b></td>
1340 <td width="115"><font face="Arial" size="2">impl</font></td>
1341 <td width="255"><font face="Arial" size="2">window with buffered animation</font></td>
1342 </tr>
1343 <tr>
1344 <td colspan="3" width="593"><font face="Arial" size="2"><br>Edit and RichEdit Find/Replace support</font></td>
1345 </tr>
1346 <tr>
1347 <td width="221"><b><font face="Arial" size="2">CEditFindReplaceImplBase</font></b></td>
1348 <td width="115"><font face="Arial" size="2">base</font></td>
1349 <td width="255"><font face="Arial" size="2">&nbsp;</td>
1350 </tr>
1351 <tr>
1352 <td width="221"><b><font face="Arial" size="2">CEditFindReplaceImpl</font></b></td>
1353 <td width="115"><font face="Arial" size="2">mi</font></td>
1354 <td width="255"><font face="Arial" size="2">Edit Find/Replace support</font></td>
1355 </tr>
1356 <tr>
1357 <td width="221"><b><font face="Arial" size="2">CRichEditFindReplaceImpl</font></b></td>
1358 <td width="115"><font face="Arial" size="2">mi</font></td>
1359 <td width="255"><font face="Arial" size="2">RichEdit Find/Replace support</font></td>
1360 </tr>
1361 <tr>
1362 <td colspan="3" width="593"><font face="Arial" size="2"><br>Printing support</font></td>
1363 </tr>
1364 <tr>
1365 <td width="221"><b><font face="Arial" size="2">CPrinterInfo</font></b></td>
1366 <td width="115"><font face="Arial" size="2">as-is</font></td>
1367 <td width="255"><font face="Arial" size="2">print info support</font></td>
1368 </tr>
1369 <tr>
1370 <td width="221"><b><font face="Arial" size="2">CPrinter</font></b></td>
1371 <td width="115"><font face="Arial" size="2">client</font></td>
1372 <td width="255"><font face="Arial" size="2">printer handle wrapper</font></td>
1373 </tr>
1374 <tr>
1375 <td width="221"><b><font face="Arial" size="2">CDevMode</font></b></td>
1376 <td width="115"><font face="Arial" size="2">client</font></td>
1377 <td width="255"><font face="Arial" size="2">DEVMODE wrapper</font></td>
1378 </tr>
1379 <tr>
1380 <td width="221"><b><font face="Arial" size="2">CPrinterDC</font></b></td>
1381 <td width="115"><font face="Arial" size="2">client</font></td>
1382 <td width="255"><font face="Arial" size="2">printing DC support</font></td>
1383 </tr>
1384 <tr>
1385 <td width="221"><b><font face="Arial" size="2">CPrintJobInfo</font></b></td>
1386 <td width="115"><font face="Arial" size="2">client</font></td>
1387 <td width="255"><font face="Arial" size="2">print job info</font></td>
1388 </tr>
1389 <tr>
1390 <td width="221"><b><font face="Arial" size="2">CPrintJob</font></b></td>
1391 <td width="115"><font face="Arial" size="2">client</font></td>
1392 <td width="255"><font face="Arial" size="2">print job support</font></td>
1393 </tr>
1394 <tr>
1395 <td width="221"><b><font face="Arial" size="2">CPrintPreview</font></b></td>
1396 <td width="115"><font face="Arial" size="2">mi</font></td>
1397 <td width="255"><font face="Arial" size="2">print preview support</font></td>
1398 </tr>
1399 <tr>
1400 <td width="221"><b><font face="Arial" size="2">CPrintPreviewWindowImpl</font></b></td>
1401 <td width="115"><font face="Arial" size="2">impl</font></td>
1402 <td width="255"><font face="Arial" size="2">print preview window</font></td>
1403 </tr>
1404 <tr>
1405 <td width="221"><b><font face="Arial" size="2">CPrintPreviewWindow</font></b></td>
1406 <td width="115"><font face="Arial" size="2">as-is</font></td>
1407 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1408 </tr>
1409 <tr>
1410 <td width="221"><b><font face="Arial" size="2">CZoomPrintPreviewWindowImpl</font></b></td>
1411 <td width="115"><font face="Arial" size="2">impl</font></td>
1412 <td width="255"><font face="Arial" size="2">zooming print preview window</font></td>
1413 </tr>
1414 <tr>
1415 <td width="221"><b><font face="Arial" size="2">CZoomPrintPreviewWindow</font></b></td>
1416 <td width="115"><font face="Arial" size="2">as-is</font></td>
1417 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1418 </tr>
1419 <tr>
1420 <td colspan="3" width="593"><font face="Arial" size="2"><br>Miscellaneous</font></td>
1421 </tr>
1422 <tr>
1423 <td width="221"><b><font face="Arial" size="2">CSize</font></b></td>
1424 <td width="115"><font face="Arial" size="2">as-is</font></td>
1425 <td width="255"><font face="Arial" size="2">WTL port of MFC's CSize</font></td>
1426 </tr>
1427 <tr>
1428 <td width="221"><b><font face="Arial" size="2">CPoint</font></b></td>
1429 <td width="115"><font face="Arial" size="2">as-is</font></td>
1430 <td width="255"><font face="Arial" size="2">WTL port of MFC's CPoint</font></td>
1431 </tr>
1432 <tr>
1433 <td width="221"><b><font face="Arial" size="2">CRect</font></b></td>
1434 <td width="115"><font face="Arial" size="2">as-is</font></td>
1435 <td width="255"><font face="Arial" size="2">WTL port of MFC's CRect</font></td>
1436 </tr>
1437 <tr>
1438 <td width="221"><b><font face="Arial" size="2">CString</font></b></td>
1439 <td width="115"><font face="Arial" size="2">as-is</font></td>
1440 <td width="255"><font face="Arial" size="2">WTL port of MFC's CString</font></td>
1441 </tr>
1442 <tr>
1443 <td width="221"><b><font face="Arial" size="2">CWinDataExchange</font></b></td>
1444 <td width="115"><font face="Arial" size="2">mi</font></td>
1445 <td width="255"><font face="Arial" size="2">data exchange for controls</font></td>
1446 </tr>
1447 <tr>
1448 <td width="221"><b><font face="Arial" size="2">CRecentDocumentList</font></b></td>
1449 <td width="115"><font face="Arial" size="2">mi or as-is</font></td>
1450 <td width="255"><font face="Arial" size="2">support for MRU list</font></td>
1451 </tr>
1452 <tr>
1453 <td width="221"><b><font face="Arial" size="2">CFindFile</font></b></td>
1454 <td width="115"><font face="Arial" size="2">as-is</font></td>
1455 <td width="255"><font face="Arial" size="2">file search support</font></td>
1456 </tr>
1457 <tr>
1458 <td colspan="3" width="593"><font face="Arial" size="2"><br>In-memory dialog</font></td>
1459 </tr>
1460 <tr>
1461 <td width="221"><b><font face="Arial" size="2">CDialogBaseUnits</font></b></td>
1462 <td width="115"><font face="Arial" size="2">helper</font></td>
1463 <td width="255"><font face="Arial" size="2">dialog units helper</font></td>
1464 </tr>
1465 <tr>
1466 <td width="221"><b><font face="Arial" size="2">CMemDlgTemplate</font></b></td>
1467 <td width="115"><font face="Arial" size="2">as-is</font></td>
1468 <td width="255"><font face="Arial" size="2">In-memory dialog template</font></td>
1469 </tr>
1470 <tr>
1471 <td width="221"><b><font face="Arial" size="2">CIndirectDialogImpl</font></b></td>
1472 <td width="115"><font face="Arial" size="2">impl</font></td>
1473 <td width="255"><font face="Arial" size="2">In-memory dialog class</font></td>
1474 </tr>
1475 <tr>
1476 <td colspan="3" width="593"><font face="Arial" size="2"><br>Task dialog</font></td>
1477 </tr>
1478 <tr>
1479 <td width="221"><b><font face="Arial" size="2">CTaskDialogImpl</font></b></td>
1480 <td width="115"><font face="Arial" size="2">impl</font></td>
1481 <td width="255"><font face="Arial" size="2">Task Dialog in Vista</font></td>
1482 </tr>
1483 <tr>
1484 <td width="221"><b><font face="Arial" size="2">CTaskDialog</font></b></td>
1485 <td width="115"><font face="Arial" size="2">as-is</font></td>
1486 <td width="255"><font face="Arial" size="2">&nbsp;</font></td>
1487 </tr>
1488 <tr>
1489 <td colspan="3" width="593"><font face="Arial" size="2"><br>DWM classes</font></td>
1490 </tr>
1491 <tr>
1492 <td width="221"><b><font face="Arial" size="2">CDwm</font></b></td>
1493 <td width="115"><font face="Arial" size="2">client</font></td>
1494 <td width="255"><font face="Arial" size="2">DWM handle warapper</font></td>
1495 </tr>
1496 <tr>
1497 <td width="221"><b><font face="Arial" size="2">CDwmImpl</font></b></td>
1498 <td width="115"><font face="Arial" size="2">impl base</font></td>
1499 <td width="255"><font face="Arial" size="2">DWM support</font></td>
1500 </tr>
1501 <tr>
1502 <td width="221"><b><font face="Arial" size="2">CDwmWindow</font></b></td>
1503 <td width="115"><font face="Arial" size="2">impl</font></td>
1504 <td width="255"><font face="Arial" size="2">DWM window support</font></td>
1505 </tr>
1506 <tr>
1507 <td width="221"><b><font face="Arial" size="2">CDwmThumbnail</font></b></td>
1508 <td width="115"><font face="Arial" size="2">client</font></td>
1509 <td width="255"><font face="Arial" size="2">DWM thumbnail wrapper</font></td>
1510 </tr>
1511 <tr>
1512 <td width="221"><b><font face="Arial" size="2">CAeroControlImpl</font></b></td>
1513 <td width="115"><font face="Arial" size="2">impl</font></td>
1514 <td width="255"><font face="Arial" size="2">support for Aero controls</font></td>
1515 </tr>
1516 <tr>
1517 <td colspan="3" width="593"><font face="Arial" size="2"><br>Ribbon classes</font></td>
1518 </tr>
1519 <tr>
1520 <td width="221"><b><font face="Arial" size="2">CRibbonUpdateUI</font></b></td>
1521 <td width="115"><font face="Arial" size="2">mi base</font></td>
1522 <td width="255"><font face="Arial" size="2">automatic mapping of ribbon UI elements</font></td>
1523 </tr>
1524 <tr>
1525 <td width="221"><b><font face="Arial" size="2">RibbonUI::CtrlImpl</font></b></td>
1526 <td width="115"><font face="Arial" size="2">base impl</font></td>
1527 <td width="255"><font face="Arial" size="2">base class for all ribbon controls</font></td>
1528 </tr>
1529 <tr>
1530 <td width="221"><b><font face="Arial" size="2">RibbonUI::CommandCtrlImpl</font></b></td>
1531 <td width="115"><font face="Arial" size="2">base impl</font></td>
1532 <td width="255"><font face="Arial" size="2">base class for ribbon controls</font></td>
1533 </tr>
1534 <tr>
1535 <td width="221"><b><font face="Arial" size="2">RibbonUI::CollectionImplBase</font></b></td>
1536 <td width="115"><font face="Arial" size="2">base</font></td>
1537 <td width="255"><font face="Arial" size="2">base class for all RibbonUI collections</font></td>
1538 </tr>
1539 <tr>
1540 <td width="221"><b><font face="Arial" size="2">RibbonUI::CollectionImpl</font></b></td>
1541 <td width="115"><font face="Arial" size="2">impl</font></td>
1542 <td width="255"><font face="Arial" size="2">RibbonUI collections</font></td>
1543 </tr>
1544 <tr>
1545 <td width="221"><b><font face="Arial" size="2">RibbonUI::CollectionCtrlImpl</font></b></td>
1546 <td width="115"><font face="Arial" size="2">impl</font></td>
1547 <td width="255"><font face="Arial" size="2">specializable class for ribbon collection controls</font></td>
1548 </tr>
1549 <tr>
1550 <td width="221"><b><font face="Arial" size="2">RibbonUI::ToolbarGalleryCtrlImpl</font></b></td>
1551 <td width="115"><font face="Arial" size="2">base impl</font></td>
1552 <td width="255"><font face="Arial" size="2">base class for ribbon toolbar gallery controls</font></td>
1553 </tr>
1554 <tr>
1555 <td width="221"><b><font face="Arial" size="2">RibbonUI::CRibbonImpl</font></b></td>
1556 <td width="115"><font face="Arial" size="2">impl</font></td>
1557 <td width="255"><font face="Arial" size="2">Ribbon implementation class</font></td>
1558 </tr>
1559 <tr>
1560 <td width="221"><b><font face="Arial" size="2">CRibbonFrameWindowImplBase</font></b></td>
1561 <td width="115"><font face="Arial" size="2">base</font></td>
1562 <td width="255"><font face="Arial" size="2">base frame class for Ribbon</font></td>
1563 </tr>
1564 <tr>
1565 <td width="221"><b><font face="Arial" size="2">CRibbonFrameWindowImpl</font></b></td>
1566 <td width="115"><font face="Arial" size="2">impl</font></td>
1567 <td width="255"><font face="Arial" size="2">Ribbon frame window class</font></td>
1568 </tr>
1569 <tr>
1570 <td width="221"><b><font face="Arial" size="2">CRibbonMDIFrameWindowImpl</font></b></td>
1571 <td width="115"><font face="Arial" size="2">impl</font></td>
1572 <td width="255"><font face="Arial" size="2">Ribbon MDI frame window class</font></td>
1573 </tr>
1574 <tr>
1575 <td width="221"><b><font face="Arial" size="2">CRibbonPersist</font></b></td>
1576 <td width="115"><font face="Arial" size="2">as-is</font></td>
1577 <td width="255"><font face="Arial" size="2">Ribbon persistance support</font></td>
1578 </tr>
1579 <tr>
1580 <td colspan="3" width="593"><font face="Arial" size="2"><br>Windows CE support</font></td>
1581 </tr>
1582 <tr>
1583 <td width="221"><b><font face="Arial" size="2">CStdDialogBase</font></b></td>
1584 <td width="115"><font face="Arial" size="2">base</font></td>
1585 <td width="255"><font face="Arial" size="2">standard dialog base class</font></td>
1586 </tr>
1587 <tr>
1588 <td width="221"><b><font face="Arial" size="2">CStdDialogImpl</font></b></td>
1589 <td width="115"><font face="Arial" size="2">impl</font></td>
1590 <td width="255"><font face="Arial" size="2">standard dialog implementation</font></td>
1591 </tr>
1592 <tr>
1593 <td width="221"><b><font face="Arial" size="2">CStdSimpleDialog</font></b></td>
1594 <td width="115"><font face="Arial" size="2">as-is</font></td>
1595 <td width="255"><font face="Arial" size="2">standard simple dialog</font></td>
1596 </tr>
1597 <tr>
1598 <td width="221"><b><font face="Arial" size="2">CStdDialogResizeBase</font></b></td>
1599 <td width="115"><font face="Arial" size="2">base</font></td>
1600 <td width="255"><font face="Arial" size="2">orientation aware standard dialog base class</font></td>
1601 </tr>
1602 <tr>
1603 <td width="221"><b><font face="Arial" size="2">CStdDialogResizeImpl</font></b></td>
1604 <td width="115"><font face="Arial" size="2">impl</font></td>
1605 <td width="255"><font face="Arial" size="2">orientation aware standard dialog implementation</font></td>
1606 </tr>
1607 <tr>
1608 <td width="221"><b><font face="Arial" size="2">CStdSimpleDialogResizeImpl</font></b></td>
1609 <td width="115"><font face="Arial" size="2">impl</font></td>
1610 <td width="255"><font face="Arial" size="2">standard resizing simple dialog implementation</font></td>
1611 </tr>
1612 <tr>
1613 <td width="221"><b><font face="Arial" size="2">CStdOrientedDialogBase</font></b></td>
1614 <td width="115"><font face="Arial" size="2">base</font></td>
1615 <td width="255"><font face="Arial" size="2">oriented dialog base class</font></td>
1616 </tr>
1617 <tr>
1618 <td width="221"><b><font face="Arial" size="2">CStdOrientedDialogImpl</font></b></td>
1619 <td width="115"><font face="Arial" size="2">impl</font></td>
1620 <td width="255"><font face="Arial" size="2">oriented dialog implementation</font></td>
1621 </tr>
1622 <tr>
1623 <td width="221"><b><font face="Arial" size="2">CStdSimpleOrientedDialog</font></b></td>
1624 <td width="115"><font face="Arial" size="2">as-is</font></td>
1625 <td width="255"><font face="Arial" size="2">standard simple oriented dialog</font></td>
1626 </tr>
1627 <tr>
1628 <td width="221"><b><font face="Arial" size="2">CAppInfoBase</font></b></td>
1629 <td width="115"><font face="Arial" size="2">base</font></td>
1630 <td width="255"><font face="Arial" size="2">application state save/restore to registry</font></td>
1631 </tr>
1632 <tr>
1633 <td width="221"><b><font face="Arial" size="2">CAppInfoT</font></b></td>
1634 <td width="115"><font face="Arial" size="2">impl</font></td>
1635 <td width="255"><font face="Arial" size="2">CAppInfoBase constructed from a CAppWindow&lt;T&gt;</font></td>
1636 </tr>
1637 <tr>
1638 <td width="221"><b><font face="Arial" size="2">CAppWindow&lt;&gt;</font></b></td>
1639 <td width="115"><font face="Arial" size="2">mi</font></td>
1640 <td width="255"><font face="Arial" size="2">PPC/SmartPhone well-behaved application window class</font></td>
1641 </tr>
1642 <tr>
1643 <td width="221"><b><font face="Arial" size="2">CAppDialog</font></b></td>
1644 <td width="115"><font face="Arial" size="2">mi</font></td>
1645 <td width="255"><font face="Arial" size="2">PPC/SmartPhone well-behaved application non-modal dialog class</font></td>
1646 </tr>
1647 <tr>
1648 <td width="221"><b><font face="Arial" size="2">CAppStdDialogImpl</font></b></td>
1649 <td width="115"><font face="Arial" size="2">impl</font></td>
1650 <td width="255"><font face="Arial" size="2">PPC/SmartPhone implementation of non-modal standard dialog application</font></td>
1651 </tr>
1652 <tr>
1653 <td width="221"><b><font face="Arial" size="2">CFullScreenFrame</font></b></td>
1654 <td width="115"><font face="Arial" size="2">impl</font></td>
1655 <td width="255"><font face="Arial" size="2">Full screen frame class</font></td>
1656 </tr>
1657 <tr>
1658 <td width="221"><b><font face="Arial" size="2">CZoomScrollImpl</font></b></td>
1659 <td width="115"><font face="Arial" size="2">mi</font></td>
1660 <td width="255"><font face="Arial" size="2">WinCE zooming implementation</font></td>
1661 </tr>
1662 <tr>
1663 <td width="221"><b><font face="Arial" size="2">CHtmlCtrl</font></b></td>
1664 <td width="115"><font face="Arial" size="2">client</font></td>
1665 <td width="255"><font face="Arial" size="2">HTML control</font></td>
1666 </tr>
1667 <tr>
1668 <td width="221"><b><font face="Arial" size="2">CRichInkCtrl</font></b></td>
1669 <td width="115"><font face="Arial" size="2">client</font></td>
1670 <td width="255"><font face="Arial" size="2">RichInk control</font></td>
1671 </tr>
1672 <tr>
1673 <td width="221"><b><font face="Arial" size="2">CInkXCtrl</font></b></td>
1674 <td width="115"><font face="Arial" size="2">client</font></td>
1675 <td width="255"><font face="Arial" size="2">InkX control</font></td>
1676 </tr>
1677 <tr>
1678 <td width="221"><b><font face="Arial" size="2">CVoiceRecorderCtrl</font></b></td>
1679 <td width="115"><font face="Arial" size="2">client</font></td>
1680 <td width="255"><font face="Arial" size="2">VoiceRecorder control</font></td>
1681 </tr>
1682 <tr>
1683 <td width="221"><b><font face="Arial" size="2">CDocListCtrl</font></b></td>
1684 <td width="115"><font face="Arial" size="2">client</font></td>
1685 <td width="255"><font face="Arial" size="2">DocList control</font></td>
1686 </tr>
1687 <tr>
1688 <td width="221"><b><font face="Arial" size="2">CCapEdit</font></b></td>
1689 <td width="115"><font face="Arial" size="2">client</font></td>
1690 <td width="255"><font face="Arial" size="2">CapEdit control</font></td>
1691 </tr>
1692 <tr>
1693 <td width="221"><b><font face="Arial" size="2">CTTStatic</font></b></td>
1694 <td width="115"><font face="Arial" size="2">client</font></td>
1695 <td width="255"><font face="Arial" size="2">TT Static control</font></td>
1696 </tr>
1697 <tr>
1698 <td width="221"><b><font face="Arial" size="2">CTTButton</font></b></td>
1699 <td width="115"><font face="Arial" size="2">client</font></td>
1700 <td width="255"><font face="Arial" size="2">TT Button control</font></td>
1701 </tr>
1702 <tr>
1703 <td width="221"><b><font face="Arial" size="2">CSpinCtrl</font></b></td>
1704 <td width="115"><font face="Arial" size="2">client</font></td>
1705 <td width="255"><font face="Arial" size="2">Spin control</font></td>
1706 </tr>
1707 <tr>
1708 <td width="221"><b><font face="Arial" size="2">CSpinListBox</font></b></td>
1709 <td width="115"><font face="Arial" size="2">client</font></td>
1710 <td width="255"><font face="Arial" size="2">Spin List Box control</font></td>
1711 </tr>
1712 <tr>
1713 <td width="221"><b><font face="Arial" size="2">CExpandListBox</font></b></td>
1714 <td width="115"><font face="Arial" size="2">client</font></td>
1715 <td width="255"><font face="Arial" size="2">Expand List Box control</font></td>
1716 </tr>
1717 <tr>
1718 <td width="221"><b><font face="Arial" size="2">CExpandEdit</font></b></td>
1719 <td width="115"><font face="Arial" size="2">client</font></td>
1720 <td width="255"><font face="Arial" size="2">Expand Edit control</font></td>
1721 </tr>
1722 <tr>
1723 <td width="221"><b><font face="Arial" size="2">CExpandCapEdit</font></b></td>
1724 <td width="115"><font face="Arial" size="2">client</font></td>
1725 <td width="255"><font face="Arial" size="2">Expand CapEdit control</font></td>
1726 </tr>
1727 </table>
1728 <p style=margin:0in>&nbsp;</p>
1729 <p style=margin:0in>&nbsp;</p>
1730 <p style=margin:0in><font face="Arial">
1731 <b><a name="ATL/WTL AppWizard"></a>ATL/WTL AppWizard</b></font></p>
1732 <p style=margin:0in>&nbsp;</p>
1733 <p style=margin:0in><font face="Arial" size="2">ATL/WTL AppWizard generates starting code for a
1734 WTL application. It has options to create code for different application types and features.</font></p>
1735 <p style=margin:0in>&nbsp;</p>
1736 <p style=margin:0in><font face="Arial" size="2">You can choose the following options:</font></p>
1737 <ul style='margin-top:0in;margin-bottom:0in'>
1738 <li><font face="Arial" size="2">Application type (SDI, multi thread SDI, MDI,
1739 TabView, Explorer, dialog based)</font></li>
1740 <li><font face="Arial" size="2">Support for hosting ActiveX controls</font></li>
1741 <li><font face="Arial" size="2">COM server support</font></li>
1742 <li><font face="Arial" size="2">Class implementation in .CPP files</font></li>
1743 <li><font face="Arial" size="2">Common Control manifest</font></li>
1744 <li><font face="Arial" size="2">Unicode character set</font></li>
1745 <li><font face="Arial" size="2">Toolbar, rebar, command bar, status bar</font></li>
1746 <li><font face="Arial" size="2">View window, and it's type (generic, dialog
1747 based form, or a list box, edit, list view, tree view, rich edit based, HTML
1748 page, scroll window)</font></li>
1749 <li><font face="Arial" size="2">For dialog based apps or a form based view
1750 window - support for hosting ActiveX controls in the dialog</font></li>
1751 </ul>
1752 <p style=margin:0in>&nbsp;</p>
1753 <p style=margin:0in><font face="Arial" size="2">ATL/WTL AppWizard supports VC++
1754 .NET 2002 and 2003, VC++ 2005, 2008, 2010, 2012, 2013, and 2015.</font></p>
1755 <p style=margin:0in>&nbsp;</p>
1756 <p style=margin:0in>&nbsp;</p>
1757 <p style=margin:0in><b><font face="Arial">
1758 <a name="Support for Windows CE"></a>Support for
1759 Windows CE</font></b></p>
1760 <p style=margin:0in>&nbsp;</p>
1761 <p style=margin:0in><font face="Arial" size="2">WTL fully supports building
1762 projects for the Windows CE platforms. The initial support for Windows CE was implemented primarily for
1763 eMbedded Visual C++ 4.0 with Pocket PC 2003 and
1764 SmartPhone 2003 SDKs. However, it can be used with other versions and
1765 configurations. For instance, Standard SDK 4.1 or 5.0 is supported as well. Considerable effort was made to provide the best Windows CE support,
1766 however, there might be some limitations because different platforms provide different
1767 programming support. SmartDevice projects with Visual Studio 2005 and 2008 are also
1768 supported, and it also includes an AppWizard for VS2005 and VS2008.</font></p>
1769 <p style=margin:0in>&nbsp;</p>
1770 <p style=margin:0in><font face="Arial" size="2">The support for Windows CE was
1771 not designed to port projects for the desktop version of Windows as-is to the
1772 Windows CE platforms, but to allow use of the same library, WTL, for both
1773 desktop Windows and Windows CE. Applications for Windows CE are often designed
1774 in a different way, and they use different platform services. WTL depends on the
1775 version of ATL provided with each Windows CE platform, and supports controls and
1776 services that are appropriate and supported for each Windows CE platform.</font></p>
1777 <p style=margin:0in>&nbsp;</p>
1778 <p style=margin:0in>&nbsp;</p>
1779 <p style=margin:0in><b><font face="Arial">
1780 <a name="Support for Visual C++ Express"></a>Support for
1781 Visual C++ Express</font></b></p>
1782 <p style=margin:0in>&nbsp;</p>
1783 <p style=margin:0in><font face="Arial" size="2">Note: Visual Studio Express is not the only or the best free development environment any more - <b>Visual Studio Community</b> provides a complete release of Visual Studio for free.</font></p>
1784 <p style=margin:0in>&nbsp;</p>
1785 <p style=margin:0in><font face="Arial" size="2">WTL supports using Visual C++ Express Edition to build projects. Since Visual C++ Express ships without ATL, you have to use a version of ATL that ships with Windows Driver Kit 7.1.0 or Platform SDK (Windows Server 2003 R2 Platform SDK).</font></p>
1786 <p style=margin:0in>&nbsp;</p>
1787 <p style=margin:0in><font face="Arial" size="2">Windows Driver Kit 7.1.0 contains ATL version 8, while Platform SDK has ATL version 3. We recomend ATL from Windows Driver Kit since it is newer and better version. However, you can still use ATL from Platform SDK since WTL still fully supports ATL3.</font></p>
1788 <p style=margin:0in>&nbsp;</p>
1789 <p style=margin:0in><font face="Arial" size="2">The WTL App Wizard can be installed by running AppWiz\setup.js program. The App Wizard generates code in the stdafx.h file that allows use of ATL. That code is used if _WTL_SUPPORT_EXTERNAL_ATL is defined, so you can comment the line in stdafx.h that defines _WTL_SUPPORT_EXTERNAL_ATL to use the project with different versions of Visual C++ or ATL.</font></p>
1790 <p style=margin:0in>&nbsp;</p>
1791 <p style=margin:0in><font face="Arial" size="2">Note that Release builds might generate some warnings, since ATL3 from Platform SDK is an old version of ATL which doesn't quite match the newer compiler and CRT files. You can ignore those warnings, as they do not indicate any real problems with the code.</font></p>
1792 <p style=margin:0in>&nbsp;</p>
1793 <p style=margin:0in><font face="Arial" size="2">Supported VC++ versions:</font></p>
1794 <ul style='margin-top:0in;margin-bottom:0in'>
1795 <li><font face="Arial" size="2">VC++ 2005 Express</font></li>
1796 <li><font face="Arial" size="2">VC++ 2008 Express</font></li>
1797 <li><font face="Arial" size="2">VC++ 2010 Express</font></li>
1798 <li><font face="Arial" size="2">VC++ Express 2012 for Windows Desktop</font></li>
1799 <li><font face="Arial" size="2">VC++ Express 2013 for Windows Desktop</font></li>
1800 <li><font face="Arial" size="2">VC++ Express 2015 for Windows Desktop</font></li>
1801 </ul>
1802 <p style=margin:0in>&nbsp;</p>
1803 <p style=margin:0in><font face="Arial" size="2">Supported ATL versions:</font></p>
1804 <ul style='margin-top:0in;margin-bottom:0in'>
1805 <li><font face="Arial" size="2">from Platform SDK (ATL 3)</font></li>
1806 <li><font face="Arial" size="2">from Windows Driver Kit (ATL 8)</font></li>
1807 </ul>
1808 <p style=margin:0in>&nbsp;</p>
1809 <p style=margin:0in><font face="Arial" size="2">Download Links:</font></p>
1810 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a target="_blank" href="https://www.visualstudio.com/downloads/download-visual-studio-vs#d-community">Visual Studio Community 2013 and 2015</a></font></p>
1811 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a target="_blank" href="https://www.visualstudio.com/downloads/download-visual-studio-vs">Visual Studio Express 2013 and 2015 for Windows Desktop</a></font></p>
1812 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a target="_blank" href="http://www.microsoft.com/en-us/download/details.aspx?id=34673">Visual Studio Express 2012 for Windows Desktop</a></font></p>
1813 <p style=margin:0in>&nbsp;</p>
1814 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a target="_blank" href="http://www.microsoft.com/en-us/download/details.aspx?id=11800">Windows Driver Kit Version 7.1.0</a></font></p>
1815 <p style=margin:0in>&nbsp;</p>
1816 <p style=margin:0in><font face="Arial" size="2">Older versions are not avilable for download any more. If you already have them, you can use them as descibed here.</font></p>
1817 <p style=margin:0in>&nbsp;</p>
1818 <p style=margin:0in>&nbsp;</p>
1819 <p style=margin:0in><b><font face="Arial">
1820 <a name="Notes"></a>Notes</font></b></p>
1821 <p style=margin:0in>&nbsp;</p>
1822 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; WTL provides
1823 several classes that are also present in ATL 7.0 and 7.1. The classes are: <b>
1824 CSize</b>, <b>CPoint</b>, <b>CRect</b>, and <b>CString</b> in atlmisc.h.
1825 While their existence will not cause any problems, their usage might. You should
1826 qualify the class you want to use with a namespace to resolve ambiguity, either
1827 ATL or WTL namespace, depending on which implementation you want to use.
1828 Alternatively, you can conditionally exclude WTL implementations, by defining
1829 preprocessor symbol <b>_WTL_NO_WTYPES</b> for CSize, CPoint, and CRect; and <b>_WTL_NO_CSTRING</b>
1830 for CString.</font></p>
1831 <p style=margin:0in>&nbsp;</p>
1832 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; If
1833 you use WTL 9.0 with VC++ 6.0/ATL 3.0 and define _ATL_STATIC_REGISTRY, you'll
1834 get errors referring to the ambiguous symbol ATL. This is caused by a bug in ATL
1835 3.0 - in atlbase.h, the file statreg.h is included inside of the ATL namespace,
1836 and it contains another namespace ATL declaration. Because of that, the compiler
1837 cannot decide between ATL:: and ATL::ATL:: namespaces. The solution is either to
1838 fix the atlbase.h, or to surround atlbase.h include declaration with following
1839 statements:</font></p>
1840 <p style=margin:0in>&nbsp;</p>
1841 <p style=margin:0in><font face="Arial" size="2"><b>&nbsp;&nbsp;&nbsp; #define
1842 ATL&nbsp;&nbsp; ATLFIX</b></font></p>
1843 <p style=margin:0in><font face="Arial" size="2">&nbsp;&nbsp;&nbsp; #include &lt;atlapp.h&gt;</font></p>
1844 <p style=margin:0in><font face="Arial" size="2">
1845 <b>&nbsp;&nbsp;&nbsp; #undef ATL</b></font></p>
1846 <p style=margin:0in><font face="Arial" size="2">
1847 <b>&nbsp;&nbsp;&nbsp; namespace ATL = ::ATLFIX;</b></font></p>
1848 <p style=margin:0in>&nbsp;</p>
1849 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp;
1850 Windows XP allows applications to use Common Controls version 6, which supports
1851 only Unicode applications. While WTL allows creation of Ansi applications that
1852 use Common Controls 6, that should be used only for test programs and is not
1853 recommended or supported for released projects. If you want to use Common
1854 Controls 6, build your application as Unicode.</font></p>
1855 <p style=margin:0in>&nbsp;</p>
1856 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp;
1857 If you build your app that hosts ActiveX controls
1858 with VC++ 7.x, you can see this assert failing:<br>
1859 <span class="style2"><strong><br>
1860 &nbsp;&nbsp;&nbsp; !InlineIsEqualGUID(*m_plibid, GUID_NULL) &amp;&amp; &quot;Did you forget
1861 to pass the LIBID to CComModule::Init?&quot;<br>
1862 <br>
1863 </strong></span><font face="Arial" size="2">There are two ways to fix this:</font></p>
1864 <ul>
1865 <li>
1866 <p style=margin:0in><font face="Arial" size="2">In the main .CPP file of your
1867 project, replace the line</font><br>
1868 <span class="style2"><strong>&nbsp;&nbsp;&nbsp; hRes = _Module.Init(NULL, hInstance);<br>
1869 </strong></span><font face="Arial" size="2">with this one</font><br>
1870 <span class="style2"><strong>&nbsp;&nbsp;&nbsp; hRes = _Module.Init(NULL, hInstance, &amp;LIBID_ATLLib);<br>
1871 &nbsp;</strong></span></p>
1872 </li>
1873 <li>
1874 <p style=margin:0in><font face="Arial" size="2">Compile you project with _ATL_DLL
1875 defined (dynamic link to ATL)</font></p>
1876 </li>
1877 </ul>
1878 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp;
1879 Several of the sample programs included with WTL were extended to support
1880 building for Windows CE. These samples are not specially redesigned for Windows
1881 CE, but just modified to allow you to compile and run them on the Windows CE
1882 platforms. The samples are: BmpView, GuidGen, and MTPad.</font></p>
1883 <p style=margin:0in>&nbsp;</p>
1884 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; WTL
1885 supports building projects with EVC++ 3.0 only for Pocket PC and Pocket PC 2002
1886 platforms, as other platforms don't provide minimum support for ATL or other
1887 required libraries.</font></p>
1888 <p style=margin:0in>&nbsp;</p>
1889 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; The
1890 old AppWizards for VC++ 6.0 and eVC++ 4.0/3.0 are not included in this version
1891 of WTL because they cannot be a part of an Open Source project. They are still
1892 available in the previous release, WTL 7.1.</font></p>
1893 <p style=margin:0in>&nbsp;</p>
1894 <p style=margin:0in><font face="Arial" size="2"><b>~</b>&nbsp;&nbsp;&nbsp; Visual
1895 Studio 2012 and higher use default subsystem version 6.0 (Windows Vista). Previous
1896 versions of Visual Studio used 5.01 (Windows XP). That means that applications built
1897 with Visual Studio 2012 and higher cannot run on Windows XP. Attempting to run would
1898 result in an error that it is not a valid Win32 application. If you want to run your
1899 applications on Windows XP, you need to change subsystem version to 5.01. You can do
1900 that by going to Project Properties -> Linker -> System -> Minimum Required Version,
1901 and entering 5.01 as a value.</font></p>
1902 <p style=margin:0in>&nbsp;</p>
1903 <p style=margin:0in>&nbsp;</p>
1904 <p style=margin:0in><b><font face="Arial">
1905
1906 <a name="Changes Between WTL 9.1 and 9.0"></a>Changes Between WTL 9.1 and 9.0</font></b></p>
1907 <p style=margin:0in>&nbsp;</p>
1908 <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
1909 <blockquote style='margin-top:0in;margin-bottom:0in'>
1910 <p style=margin:0in><font face="Arial" size="2">
1911 Full compatibility with VS2015<br>
1912 NuGet support and package<br>
1913 Microsoft Public License (MS-PL)<br>
1914 New sample: MemDlg - demonstrates use of in-memory dialogs
1915 </blockquote>
1916 <p style=margin:0in>&nbsp;</p>
1917 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
1918 <blockquote style='margin-top:0in;margin-bottom:0in'>
1919 <p style=margin:0in><font face="Arial" size="2">
1920 Fixes for code analysis warnings<br>
1921 Fixes for strict const-qualification conformance (/Zc:strictStrings)<br>
1922 CEditFindReplaceImpl::UseShadowBuffer(): Use AtlGetCommCtrlVersion() instead of GetProcAddress()<br>
1923 Misc improvements: missing initialization, undefined messages, better #ifdefs<br>
1924 CFrameWndClassInfo: Use GetSystemMetrics() for icon sizes<br>
1925 BEGIN_MSG_MAP_EX and BEGIN_DDX_MAP: Fix for C4555: expression has no effect<br>
1926 CResource::LoadEx(): Fix for the wrong order for parameters to ::FindResourceEx()<br>
1927 CPaneContainerImpl:</font></p>
1928 <ul style='margin-top:0in;margin-bottom:0in'>
1929 <li><p style=margin:0in><font face="Arial" size="2">New extended styles: PANECNT_DIVIDER and PANECNT_GRADIENT</font></p></li>
1930 <li><p style=margin:0in><font face="Arial" size="2">Fixed background drawing for close button</font></p></li>
1931 </ul>
1932 <p style=margin:0in><font face="Arial" size="2">
1933 CImageListManaged: Fix for assert when using attach or operator =<br>
1934 WTLExplorer sample cleanup<br>
1935 GenericWndClass::Register(): Fix for Windows CE<br>
1936 App Wizard: Improved code for generating project configurations<br>
1937 CSplitterImpl::OnCaptureChanged(): Fixed so it moves splitter bar only if move was in progress<br>
1938 CDynamicUpdateUI::UIRemoveUpdateElement() leaks memory if UPDUI_TEXT is set<br>
1939 CToolInfo and CToolTipCtrl: nIDTool argument should be UINT_PTR instead of UINT<br>
1940 CSplitterImpl: Added GetSplitterPosPct()<br>
1941 CCommandBarCtrlImpl: Fixed incorrect use of m_wndParent when AttachToWindow() is used
1942 </blockquote>
1943 <p style=margin:0in>&nbsp;</p>
1944 <p style=margin:0in>&nbsp;</p>
1945 <p style=margin:0in><b><font face="Arial">
1946
1947 <a name="Changes Between WTL 9.0 and 8.0"></a>Changes Between WTL 9.0 and 8.0</font></b></p>
1948 <p style=margin:0in>&nbsp;</p>
1949 <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
1950 <blockquote style='margin-top:0in;margin-bottom:0in'>
1951 <p style=margin:0in><font face="Arial" size="2">
1952 Full compatibility with VS2008, VS2010, VS2012, and VS2013<br>
1953 New CRegKeyEx class for uniform support for registry<br>
1954 New MinCrtHelper functions for uniform support for _ATL_MIN_CRT<br>
1955 New DWM classes in atldwm.h<br>
1956 New Ribbon classes in atlribbon.h<br>
1957 New CDialogBaseUnits class<br>
1958 Extended DDX support to TabCtrl, ComboBox, ListBox and ListView selection index<br>
1959 Improved font handling in CHyperLink, CPaneContainer, CTabView<br>
1960 CHyperlink: Added options for auto-create link font and single-line mode<br>
1961 CBitmapButtonImpl: Added checked state, GetCheck()/SetCheck(), and check mode extended styles<br>
1962 UpdateUI: Added support for radio menu items for popup menus<br>
1963 Added support for new VersionHelpers.h in WinSDK 8.1 - GetVersionEx() is now deprecated<br>
1964 Improved global support for old SDK headers, and for original headers in VC6 and VC7.x<br>
1965 Global support for builds with NOMINMAX defined<br>
1966 Global support for builds with STRICT_TYPED_ITEMIDS defined<br>
1967 Global support for builds with _ATL_ALL_USER_WARNINGS defined<br>
1968 Splitter Window:</font></p>
1969 <ul style='margin-top:0in;margin-bottom:0in'>
1970 <li><p style=margin:0in><font face="Arial" size="2">Added keyboard handling</font></p></li>
1971 <li><p style=margin:0in><font face="Arial" size="2">Added default position for splitter bar</font></p></li>
1972 <li><p style=margin:0in><font face="Arial" size="2">Changed orientation from template argument to data member to reduce memory use</font></p></li>
1973 <li><p style=margin:0in><font face="Arial" size="2">Added SPLIT_GRADIENTBAR and SPLIT_FIXEDBARSIZE extended styles</font></p></li>
1974 </ul>
1975 <p style=margin:0in><font face="Arial" size="2">
1976 Added CImageListManaged to manage the lifetime of wrapped image list<br>
1977 Added Vista standard menu bar look option for Command bar<br>
1978 Added new Rich Edit wrappers for _RICHEDIT_VER >= 0x0800<br>
1979 Added new Win8 methods to Theme classes<br>
1980 Added override of SubclassWindow() to CSplitterWindowImpl, CPaneContainerImpl, CTabViewImpl,<br>
1981 &nbsp;&nbsp;CScrollImpl, CMapScrollImpl, CZoomScrollImpl, and CScrollContainerImpl<br>
1982 CZoomScrollImpl:</font></p>
1983 <ul style='margin-top:0in;margin-bottom:0in'>
1984 <li><p style=margin:0in><font face="Arial" size="2">Added zoom child windows option</font></p></li>
1985 <li><p style=margin:0in><font face="Arial" size="2">Added zoom scale max limit</font></p></li>
1986 </ul>
1987 <p style=margin:0in><font face="Arial" size="2">
1988 AppWizard:</font></p>
1989 <ul style='margin-top:0in;margin-bottom:0in'>
1990 <li><p style=margin:0in><font face="Arial" size="2">Support for VS2008, VS2010, VS2012, and VS2013</font></p></li>
1991 <li><p style=margin:0in><font face="Arial" size="2">New universal setup for all versions of Visual Studio</font></p></li>
1992 <li><p style=margin:0in><font face="Arial" size="2">Support for ribbon control</font></p></li>
1993 </ul>
1994 <p style=margin:0in><font face="Arial" size="2">
1995 Updated samples and added VS2005 project files<br>
1996 New sample: MTPad7 - demonstrates Ribbon UI</font></p>
1997 </blockquote>
1998 <p style=margin:0in>&nbsp;</p>
1999 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
2000 <blockquote style='margin-top:0in;margin-bottom:0in'>
2001 <p style=margin:0in><font face="Arial" size="2">General:</font></p>
2002 <ul style='margin-top:0in;margin-bottom:0in'>
2003 <li><p style=margin:0in><font face="Arial" size="2">Fixed security warning for _vstprintf in atlapp.h</font></p></li>
2004 <li><p style=margin:0in><font face="Arial" size="2">Added RunTimeHelper::IsThemeAvailable that detects if themes can be used in the app</font></p></li>
2005 <li><p style=margin:0in><font face="Arial" size="2">VS2012: DLL version functions are defined as they are removed from ATL11</font></p></li>
2006 <li><p style=margin:0in><font face="Arial" size="2">Added CWndProcThunk initialization for _ATL_VER >= 0x0800</font></p></li>
2007 <li><p style=margin:0in><font face="Arial" size="2">Added RunTimeHelper::SizeOf_TOOLINFO() for different Windows versions at runtime</font></p></li>
2008 <li><p style=margin:0in><font face="Arial" size="2">Added AtlCreateControlFont()</font></p></li>
2009 </ul>
2010 <p style=margin:0in>&nbsp;</p>
2011 <p style=margin:0in><font face="Arial" size="2">Controls:</font></p>
2012 <ul style='margin-top:0in;margin-bottom:0in'>
2013 <li><p style=margin:0in><font face="Arial" size="2">Extended CListViewCtrl::SelectItem() to multi-selection list view controls</font></p></li>
2014 <li><p style=margin:0in><font face="Arial" size="2">Added another variant of CListViewCtrl::FindItem for strings</font></p></li>
2015 <li><p style=margin:0in><font face="Arial" size="2">Added new CToolBarCtrl methods - InsertSeparator() and AddSeparator()</font></p></li>
2016 <li><p style=margin:0in><font face="Arial" size="2">Added CToolBarCtrl::GetItemDropDownRect()</font></p></li>
2017 <li><p style=margin:0in><font face="Arial" size="2">Added another variant of CToolTipCtrl::TrackActivate()</font></p></li>
2018 </ul>
2019 <p style=margin:0in>&nbsp;</p>
2020 <p style=margin:0in><font face="Arial" size="2">Cracked Handlers:</font></p>
2021 <ul style='margin-top:0in;margin-bottom:0in'>
2022 <li><p style=margin:0in><font face="Arial" size="2">Fixed handlers with menu arguments</font></p></li>
2023 <li><p style=margin:0in><font face="Arial" size="2">Fixed MSG_WM_SYSCOMMAND handler</font></p></li>
2024 <li><p style=margin:0in><font face="Arial" size="2">Added MSG_WM_MOUSEHWHEEL handler</font></p></li>
2025 </ul>
2026 <p style=margin:0in>&nbsp;</p>
2027 <p style=margin:0in><font face="Arial" size="2">App Wizard:</font></p>
2028 <ul style='margin-top:0in;margin-bottom:0in'>
2029 <li><p style=margin:0in><font face="Arial" size="2">Fix for TabView project code generation</font></p></li>
2030 <li><p style=margin:0in><font face="Arial" size="2">Improved generated code for VC++ Express to support various versions of ATL</font></p></li>
2031 <li><p style=margin:0in><font face="Arial" size="2">Fix for missing UIUpdateChildWindows() in dialog projects</font></p></li>
2032 </ul>
2033 <p style=margin:0in>&nbsp;</p>
2034 <p style=margin:0in><font face="Arial" size="2">App Wizard CE / App Wizard Mobile:</font></p>
2035 <ul style='margin-top:0in;margin-bottom:0in'>
2036 <li><p style=margin:0in><font face="Arial" size="2">Updated AppWizCE for VS2008 - used different CLSID for Platforms object</font></p></li>
2037 <li><p style=margin:0in><font face="Arial" size="2">Fix: VS2008 uses _SECURE_ATL code only</font></p></li>
2038 <li><p style=margin:0in><font face="Arial" size="2">Fix for resource creation failure</font></p></li>
2039 </ul>
2040 <p style=margin:0in>&nbsp;</p>
2041 <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
2042 <ul style='margin-top:0in;margin-bottom:0in'>
2043 <li><p style=margin:0in><font face="Arial" size="2">Fix: CLogFont uses ::GetDeviceCaps with wrong default hDC = NULL</font></p></li>
2044 <li><p style=margin:0in><font face="Arial" size="2">Fixed CPen::GetExtLogPen</font></p></li>
2045 <li><p style=margin:0in><font face="Arial" size="2">Fixed CFrameWindowImpl::OnToolTipText*() handlers not to reset text buffer</font></p></li>
2046 <li><p style=margin:0in><font face="Arial" size="2">Added support for chevron menus for multi-line toolbars</font></p></li>
2047 <li><p style=margin:0in><font face="Arial" size="2">Fix: CFileDialog(false) fails on Windows Mobile 5 or 6</font></p></li>
2048 <li><p style=margin:0in><font face="Arial" size="2">Fix: CFolderDialog::SetOKText should use lParam for string</font></p></li>
2049 <li><p style=margin:0in><font face="Arial" size="2">Added CFolderDialog::SetPidlRoot()</font></p></li>
2050 <li><p style=margin:0in><font face="Arial" size="2">Fixed CMemDlgTemplate::AddControl</font></p></li>
2051 <li><p style=margin:0in><font face="Arial" size="2">Added option to disable item dragging in CTabViewImpl</font></p></li>
2052 <li><p style=margin:0in><font face="Arial" size="2">Fixed CTabView::ShowTabControl(false) and UpdateLayout() to hide empty space</font></p></li>
2053 <li><p style=margin:0in><font face="Arial" size="2">CTabView: Fixed value of the active page when inserting pages before it</font></p></li>
2054 <li><p style=margin:0in><font face="Arial" size="2">PaneContainer: Added support for vertical title bar text</font></p></li>
2055 <li><p style=margin:0in><font face="Arial" size="2">atlsplit.h: Added missing support for WM_PRINTCLIENT</font></p></li>
2056 <li><p style=margin:0in><font face="Arial" size="2">Fix: CScrollImpl should not scroll horizontally if not needed</font></p></li>
2057 <li><p style=margin:0in><font face="Arial" size="2">Fixed CScrollImpl<T>::ScrollToView() to use offset correctly</font></p></li>
2058 <li><p style=margin:0in><font face="Arial" size="2">Fixed CPrintDialogExImpl::GetDefaults()</font></p></li>
2059 <li><p style=margin:0in><font face="Arial" size="2">atltheme.h: Added CBufferedAnimation::StopAllAnimations()</font></p></li>
2060 <li><p style=margin:0in><font face="Arial" size="2">Added support for I64 format to CString::Format()</font></p></li>
2061 <li><p style=margin:0in><font face="Arial" size="2">Fix: CStdIndirectDialogImpl - DLGTEMPLATEEX not supported on Mobile devices</font></p></li>
2062 <li><p style=margin:0in><font face="Arial" size="2">Fix: Missing CRichInkCtrlT::SetSel(), added CRichInkCtrlT::Undo()</font></p></li>
2063 </ul>
2064 </blockquote>
2065 <p style=margin:0in>&nbsp;</p>
2066 <p style=margin:0in>&nbsp;</p>
2067 <p style=margin:0in><b><font face="Arial">
2068 <a name="Changes Between WTL 8.0 and 7.5"></a>Changes Between WTL 8.0 and 7.5</font></b></p>
2069 <p style=margin:0in>&nbsp;</p>
2070 <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
2071 <blockquote style='margin-top:0in;margin-bottom:0in'>
2072 <p style=margin:0in><font face="Arial" size="2">RunTimeHelper functions for
2073 correct struct sizes on different versions of Windows<br>ModuleHelper functions for uniform support of ATL3 and ATL7 module classes<br>SecureHelper functions for support of secure and non-secure run-time
2074 functions<br>Support for new Vista features:</font></p>
2075 <ul style='margin-top:0in;margin-bottom:0in'>
2076 <li>
2077 <p style=margin:0in><font face="Arial" size="2">Support for new messages for common controls, dialogs, etc.</font></p>
2078 </li>
2079 <li>
2080 <p style=margin:0in><font face="Arial" size="2">Support for TaskDialog</font></p>
2081 </li>
2082 <li>
2083 <p style=margin:0in><font face="Arial" size="2">New Shell file dialogs (IFileOpenDialog and IFileSaveDialog)</font></p>
2084 </li>
2085 <li>
2086 <p style=margin:0in><font face="Arial" size="2">New Aero Wizard support classes</font></p>
2087 </li>
2088 <li>
2089 <p style=margin:0in><font face="Arial" size="2">New classes for Buffered Paint and Buffered Animation</font></p>
2090 </li>
2091 </ul>
2092 <p style=margin:0in><font face="Arial" size="2">New TabView classes<br>New dialog class that uses in-memory dialog templates<br>New CMultiFileDialogImpl and CMultiFileDialog classes that support
2093 multi-select file dialogs<br>Added message cracker handler prototypes for all handlers<br>Replaced use of _alloca with CTempBuffer everywhere (and added CTempBuffer
2094 version for ATL3)<br>New classes for find/replace support for Edit or RichEdit<br>New class CFileDialogEx that supports GetOpenFileNameEx for Windows Mobile 5<br>
2095 New features for the App Wizard:</font></p>
2096 <ul style='margin-top:0in;margin-bottom:0in'>
2097 <li>
2098 <p style=margin:0in><font face="Arial" size="2">New default version values</font></p>
2099 </li>
2100 <li>
2101 <p style=margin:0in><font face="Arial" size="2">Unicode build option</font></p>
2102 </li>
2103 <li>
2104 <p style=margin:0in><font face="Arial" size="2">Support for TabView applications</font></p>
2105 </li>
2106 <li>
2107 <p style=margin:0in><font face="Arial" size="2">Support for Explorer applications</font></p>
2108 </li>
2109 </ul>
2110 <p style=margin:0in><font face="Arial" size="2">Updates for the desktop App Wizard:</font></p>
2111 <ul style='margin-top:0in;margin-bottom:0in'>
2112 <li>
2113 <p style=margin:0in><font face="Arial" size="2">Added calls to set font for views based on controls that use font</font></p>
2114 </li>
2115 <li>
2116 <p style=margin:0in><font face="Arial" size="2">Added scroll window as another view type</font></p>
2117 </li>
2118 </ul>
2119 <p style=margin:0in><font face="Arial" size="2">Support for VC2005 Express:</font></p>
2120 <ul style='margin-top:0in;margin-bottom:0in'>
2121 <li>
2122 <p style=margin:0in><font face="Arial" size="2">Setup for VS2005x</font></p>
2123 </li>
2124 <li>
2125 <p style=margin:0in><font face="Arial" size="2">Changes in default.js to take into account that VC2005x does not have a
2126 resource editor</font></p></li>
2127 <li>
2128 <p style=margin:0in><font face="Arial" size="2">Generated code allows use of ATL3 from the Platform SDK</font></p>
2129 </li>
2130 </ul>
2131 <p style=margin:0in><font face="Arial" size="2">New AppWizard for Mobile 2003 and 2005 platforms<br>
2132 New samples:</font></p>
2133 <ul style='margin-top:0in;margin-bottom:0in'>
2134 <li>
2135 <p style=margin:0in><font face="Arial" size="2">Aero - demonstrates the
2136 Vista Glass UI</font></p></li>
2137 <li>
2138 <p style=margin:0in><font face="Arial" size="2">MiniPie - Windows Mobile 2005 PPC and Smartphone sample</font></p>
2139 </li>
2140 <li>
2141 <p style=margin:0in><font face="Arial" size="2">TabBrowser - a web browser using TabView class</font></p>
2142 </li>
2143 </ul>
2144 <p style=margin:0in><font face="Arial" size="2">MTPad sample updated to show usage of CRichEditFindReplaceImpl and
2145 CEditCommands/CRichEditCommands</font></p>
2146 </blockquote>
2147 <p style=margin:0in>&nbsp;</p>
2148 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
2149 <blockquote style='margin-top:0in;margin-bottom:0in'>
2150 <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
2151 <ul style='margin-top:0in;margin-bottom:0in'>
2152 <li>
2153 <p style=margin:0in><font face="Arial" size="2">Added support for menu items
2154 with bitmaps on Vista</font></p></li>
2155 <li>
2156 <p style=margin:0in><font face="Arial" size="2">Fix: Keyboard cues shown
2157 even if the window is disabled</font></p></li>
2158 </ul>
2159 <p style=margin:0in>&nbsp;</p>
2160 <p style=margin:0in><font face="Arial" size="2">CFolderDialog:</font></p>
2161 <ul style='margin-top:0in;margin-bottom:0in'>
2162 <li>
2163 <p style=margin:0in><font face="Arial" size="2">Added support for PIDLs in
2164 addition to the file path</font></p></li>
2165 <li>
2166 <p style=margin:0in><font face="Arial" size="2">Replaced use of SHGetMalloc
2167 with CoTaskMemFree</font></p></li>
2168 </ul>
2169 <p style=margin:0in>&nbsp;</p>
2170 <p style=margin:0in><font face="Arial" size="2">Scroll Windows:</font></p>
2171 <ul style='margin-top:0in;margin-bottom:0in'>
2172 <li>
2173 <p style=margin:0in><font face="Arial" size="2">Fix: CZoomScrollImpl - some
2174 methods should be overridable</font></p></li>
2175 <li>
2176 <p style=margin:0in><font face="Arial" size="2">Added support for
2177 WM_MOUSEHWHEEL in CScrollImpl</font></p></li>
2178 </ul>
2179 <p style=margin:0in>&nbsp;</p>
2180 <p style=margin:0in><font face="Arial" size="2">App Wizard:</font></p>
2181 <ul style='margin-top:0in;margin-bottom:0in'>
2182 <li>
2183 <p style=margin:0in><font face="Arial" size="2">Fix: AppWizard fails to add
2184 files if C:\Temp does not exist</font></p></li>
2185 <li>
2186 <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard generates
2187 security warning when loaded</font></p></li>
2188 <li>
2189 <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard generates
2190 level 4 warning for modal dlg project</font></p></li>
2191 <li>
2192 <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard setupXX.js
2193 scripts silently fail on Vista</font></p></li>
2194 <li>
2195 <p style=margin:0in><font face="Arial" size="2">Fix: Added code to
2196 unregister message filer and idle processing</font></p></li>
2197 <li>
2198 <p style=margin:0in><font face="Arial" size="2">Fix: Added WS_CLIPSIBLINGS
2199 to dialog forms to avoid rebar drawing problems</font></p></li>
2200 </ul>
2201 <p style=margin:0in>&nbsp;</p>
2202 <p style=margin:0in><font face="Arial" size="2">App Wizard CE:</font></p>
2203 <ul style='margin-top:0in;margin-bottom:0in'>
2204 <li>
2205 <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard CE should
2206 not have rich edit as a view option</font></p></li>
2207 <li>
2208 <p style=margin:0in><font face="Arial" size="2">Fix: App Wizard CE generates
2209 level 4 warnings for single instance apps</font></p></li>
2210 <li>
2211 <p style=margin:0in><font face="Arial" size="2">Added support for Windows
2212 Mobile 6 SDKs</font></p></li>
2213 </ul>
2214 <p style=margin:0in>&nbsp;</p>
2215 <p style=margin:0in><font face="Arial" size="2">Cracked Handlers:</font></p>
2216 <ul style='margin-top:0in;margin-bottom:0in'>
2217 <li>
2218 <p style=margin:0in><font face="Arial" size="2">Fix: Corrected MSG_WM_TIMER
2219 and handler prototype, removed unused argument (breaking change)</font></p>
2220 </li>
2221 <li>
2222 <p style=margin:0in><font face="Arial" size="2">Fix: atlcrack.h does not
2223 support WTL namespace</font></p></li>
2224 </ul>
2225 <p style=margin:0in>&nbsp;</p>
2226 <p style=margin:0in><font face="Arial" size="2">CDialogResize:</font></p>
2227 <ul style='margin-top:0in;margin-bottom:0in'>
2228 <li>
2229 <p style=margin:0in><font face="Arial" size="2">Added SetIcon(NULL, FALSE)
2230 for CDialogResize to remove the generic icon for resizable dialogs</font></p>
2231 </li>
2232 <li>
2233 <p style=margin:0in><font face="Arial" size="2">Fix: Enabled size/move for
2234 both X and Y</font></p></li>
2235 <li>
2236 <p style=margin:0in><font face="Arial" size="2">Added center flags for
2237 controls</font></p></li>
2238 </ul>
2239 <p style=margin:0in>&nbsp;</p>
2240 <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
2241 <ul style='margin-top:0in;margin-bottom:0in'>
2242 <li>
2243 <p style=margin:0in><font face="Arial" size="2">Fix: Const issue with title
2244 argument of AddSimpleReBarBand</font></p></li>
2245 <li>
2246 <p style=margin:0in><font face="Arial" size="2">Fix: DECLARE_FRAME_WND_CLASS
2247 definition missing WTL namespace</font></p></li>
2248 </ul>
2249 <p style=margin:0in>&nbsp;</p>
2250 <p style=margin:0in><font face="Arial" size="2">Windows CE:</font></p>
2251 <ul style='margin-top:0in;margin-bottom:0in'>
2252 <li>
2253 <p style=margin:0in><font face="Arial" size="2">Fix: Some symbols not
2254 defined for CE 4.0</font></p></li>
2255 <li>
2256 <p style=margin:0in><font face="Arial" size="2">Fix: Incorrect WinCE
2257 exclusions</font></p></li>
2258 <li>
2259 <p style=margin:0in><font face="Arial" size="2">Fix: Pocket PC - assert
2260 after navigating a CHyperLink</font></p></li>
2261 <li>
2262 <p style=margin:0in><font face="Arial" size="2">Fix: Property sheet with
2263 listview on WM5.0 causes stack overflow</font></p></li>
2264 <li>
2265 <p style=margin:0in><font face="Arial" size="2">Fix: CFindFile::GetFilePath()
2266 fails on diskless root requests</font></p></li>
2267 <li>
2268 <p style=margin:0in><font face="Arial" size="2">Fix: VS 2005 dialog editor
2269 bug - DS_FIXEDSYS used but not defined</font></p></li>
2270 <li>
2271 <p style=margin:0in><font face="Arial" size="2">Fix: Windows Mobile 2005
2272 compatibility issues</font></p></li>
2273 <li>
2274 <p style=margin:0in><font face="Arial" size="2">Fix: CFullScreenFrame on
2275 Smartphone 20003</font></p></li>
2276 <li>
2277 <p style=margin:0in><font face="Arial" size="2">Fix: SmartPhone back key
2278 handling in CAppWindow</font></p></li>
2279 <li>
2280 <p style=margin:0in><font face="Arial" size="2">Added orientation aware
2281 support to CAppStdDialogImpl</font></p></li>
2282 <li>
2283 <p style=margin:0in><font face="Arial" size="2">Added CAxDialogImpl base for
2284 CStdDialogImpl, CStdDialogResizeImpl and CStdOrientedDialogImpl</font></p>
2285 </li>
2286 <li>
2287 <p style=margin:0in><font face="Arial" size="2">Added various CStdDialogxxx
2288 enhancements</font></p></li>
2289 <li>
2290 <p style=margin:0in><font face="Arial" size="2">Fix: CStdDialogBase does not
2291 scale dialog title on VGA</font></p></li>
2292 <li>
2293 <p style=margin:0in><font face="Arial" size="2">Fix: DIBINFO16 triggers code
2294 analysis warning</font></p></li>
2295 <li>
2296 <p style=margin:0in><font face="Arial" size="2">Added LPCTSTR
2297 AtlLoadString(UINT uID) - CE only overload</font></p></li>
2298 <li>
2299 <p style=margin:0in><font face="Arial" size="2">Added imaging draw support
2300 to CZoomScrollImpl</font></p></li>
2301 <li>
2302 <p style=margin:0in><font face="Arial" size="2">Added CBottomTabViewImpl and
2303 CBottomTabView classes for PPC</font></p></li>
2304 </ul>
2305 <p style=margin:0in>&nbsp;</p>
2306 <p style=margin:0in><font face="Arial" size="2">CFindFile:</font></p>
2307 <ul style='margin-top:0in;margin-bottom:0in'>
2308 <li>
2309 <p style=margin:0in><font face="Arial" size="2">Fix: CFindFile class uses
2310 CRT functions</font></p></li>
2311 <li>
2312 <p style=margin:0in><font face="Arial" size="2">Fix: FindFile() uses lstrcpy
2313 without checking length</font></p></li>
2314 </ul>
2315 <p style=margin:0in>&nbsp;</p>
2316 <p style=margin:0in><font face="Arial" size="2">General:</font></p>
2317 <ul style='margin-top:0in;margin-bottom:0in'>
2318 <li>
2319 <p style=margin:0in><font face="Arial" size="2">Fix: Adding ReBar bands
2320 fails with new Windows SDK</font></p></li>
2321 <li>
2322 <p style=margin:0in><font face="Arial" size="2">Added support for relative
2323 include paths</font></p></li>
2324 <li>
2325 <p style=margin:0in><font face="Arial" size="2">Fix: Using std::min and
2326 std::max</font></p></li>
2327 <li>
2328 <p style=margin:0in><font face="Arial" size="2">Fix: Problems using WTL with
2329 MFC</font></p></li>
2330 <li>
2331 <p style=margin:0in><font face="Arial" size="2">Improved support for Secure
2332 CRT</font></p></li>
2333 <li>
2334 <p style=margin:0in><font face="Arial" size="2">Changed implementation of
2335 CSize, CPoint, CRect, and CString to be inside class definitions</font></p>
2336 </li>
2337 <li>
2338 <p style=margin:0in><font face="Arial" size="2">atltheme.h: Corrected method
2339 signatures for differences in uxtheme.h versions</font></p></li>
2340 <li>
2341 <p style=margin:0in><font face="Arial" size="2">Replaced malloc/free with
2342 new/delete where appropriate</font></p></li>
2343 </ul>
2344 <p style=margin:0in>&nbsp;</p>
2345 <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
2346 <ul style='margin-top:0in;margin-bottom:0in'>
2347 <li>
2348 <p style=margin:0in><font face="Arial" size="2">Fix: CString::FormatV can
2349 cause GPF with Unicode strings</font></p></li>
2350 <li>
2351 <p style=margin:0in><font face="Arial" size="2">CHyperLink: Added handler
2352 for WM_SIZE</font></p></li>
2353 <li>
2354 <p style=margin:0in><font face="Arial" size="2">Fix: CTheme needs
2355 constructor from HTHEME handle</font></p></li>
2356 <li>
2357 <p style=margin:0in><font face="Arial" size="2">Added Add* methods to
2358 several control classes in atlctrls.h to augment Insert* methods</font></p>
2359 </li>
2360 <li>
2361 <p style=margin:0in><font face="Arial" size="2">Fix: Incorrect casting in
2362 CRichEditCtrl::GetLine()</font></p></li>
2363 <li>
2364 <p style=margin:0in><font face="Arial" size="2">Fix:
2365 CTreeViewCtrl::GetItemState changed to return only state-bits as specified
2366 by mask</font></p></li>
2367 <li>
2368 <p style=margin:0in><font face="Arial" size="2">Fix: CBitmapButton::DoPaint
2369 - wrong button image</font></p></li>
2370 <li>
2371 <p style=margin:0in><font face="Arial" size="2">Added another variant of
2372 CDCT::Drawtext with LPTSTR argument that allows text change</font></p></li>
2373 <li>
2374 <p style=margin:0in><font face="Arial" size="2">Fix:
2375 CRecentDocumentListBase::AddToList() uses lstrcpy</font></p></li>
2376 <li>
2377 <p style=margin:0in><font face="Arial" size="2">Fix: AtlLoadString(uID,
2378 lpBuffer, nBufferMax) has unnecessary code</font></p></li>
2379 <li>
2380 <p style=margin:0in><font face="Arial" size="2">Fix: CCursor::LoadOEMCursor
2381 asserts on IDC_HAND</font></p></li>
2382 <li>
2383 <p style=margin:0in><font face="Arial" size="2">Fix: Memory leak when using
2384 CRT functions while printing</font></p></li>
2385 <li>
2386 <p style=margin:0in><font face="Arial" size="2">Fix: Undefined CString
2387 namespace</font></p></li>
2388 <li>
2389 <p style=margin:0in><font face="Arial" size="2">CPaneContainer: Added border
2390 styles</font></p></li>
2391 <li>
2392 <p style=margin:0in><font face="Arial" size="2">CSplitterImpl: Added
2393 SetSplitterPosPct, and changed App Wizard code to use it</font></p></li>
2394 </ul>
2395 </blockquote>
2396 <p style=margin:0in>&nbsp;</p>
2397 <p style=margin:0in>&nbsp;</p>
2398 <p style=margin:0in><b><font face="Arial">
2399 <a name="Changes Between WTL 7.5 and 7.1"></a>Changes Between WTL 7.5 and 7.1</font></b></p>
2400 <p style=margin:0in>&nbsp;</p>
2401 <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
2402 <blockquote style='margin-top:0in;margin-bottom:0in'>
2403 <p style=margin:0in><font face="Arial" size="2">VS2005 Compatibility:
2404 Added support for Visual Studio 2005 - both desktop and Windows CE<br>
2405 Classes for icons, cursors, accelerator tables<br>
2406 CSortListViewImpl, CSortListViewCtrlImpl, and CSortListViewCtrl classes<br>
2407 Impl classes for Wizard 97 style wizards: CWizard97Sheet,
2408 CWizard97Page, CWizard97ExteriorPage, CWizard97InteriorPage<br>
2409 CMemoryDC and CDoubleBufferWindowImpl classes<br>
2410 Windows CE specific classes in new header, atlwince.h<br>
2411 CScrollContainer class<br>
2412 CZoomScrollImpl and CZoomScrollWindowImpl classes<br>
2413 CZoomPrintPreviewWindowImpl and CZoomPrintPreviewWindow classes<br>
2414 Global functions: AtlGetBitmapResourceInfo,
2415 AtlGetBitmapResourceBitsPerPixel<br>
2416 New REFLECT_* macros to enable selective reflection of messages<br>
2417 App Wizard: Added App Wizard for VS2005<br>
2418 App Wizard: Added App Wizard for Windows CE for VS2005<br>
2419 New samples: WTLExplorer, ImageView, SPControls<br>
2420 &nbsp;</font></p>
2421 </blockquote>
2422 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
2423 <blockquote style='margin-top:0in;margin-bottom:0in'>
2424 <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
2425 <ul style='margin-top:0in;margin-bottom:0in'>
2426 <li>
2427 <p style=margin:0in><font face="Arial" size="2">DrawBitmapDisabled()
2428 doesn't work correctly on Longhorn</font></p></li>
2429 <li>
2430 <p style=margin:0in><font face="Arial" size="2">Submenu size not correct if
2431 command bar is off-screen</font></p></li>
2432 <li>
2433 <p style=margin:0in><font face="Arial" size="2">Added handler for
2434 WM_SETTINGCHANGE to improve theme color changes</font></p></li>
2435 <li>
2436 <p style=margin:0in><font face="Arial" size="2">Better support for
2437 8/16/24-bit images</font></p></li>
2438 <li>
2439 <p style=margin:0in><font face="Arial" size="2">Command Bar with 2 Levels of
2440 submenus remains active</font></p></li>
2441 <li>
2442 <p style=margin:0in><font face="Arial" size="2">Hook procedure fails to call
2443 next hook</font></p></li>
2444 <li>
2445 <p style=margin:0in><font face="Arial" size="2">OnDestroy() should not
2446 decrement hook use if AttachToWindow() is used</font></p></li>
2447 </ul>
2448 <p style=margin:0in>&nbsp;</p>
2449 <p style=margin:0in><font face="Arial" size="2">MDI Command Bar:</font></p>
2450 <ul style='margin-top:0in;margin-bottom:0in'>
2451 <li>
2452 <p style=margin:0in><font face="Arial" size="2">Grows bigger if you
2453 switch between two maximized MDI child window types</font></p></li>
2454 <li>
2455 <p style=margin:0in><font face="Arial" size="2">Move all hook messages
2456 processing to a separate function and use pT</font></p></li>
2457 <li>
2458 <p style=margin:0in><font face="Arial" size="2">MDI icon &amp; buttons should
2459 have themed background</font></p></li>
2460 <li>
2461 <p style=margin:0in><font face="Arial" size="2">Should make MDI buttons gray
2462 when inactive<br>&nbsp;</font></p></li>
2463 </ul>
2464 <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
2465 <ul style='margin-top:0in;margin-bottom:0in'>
2466 <li>
2467 <p style=margin:0in><font face="Arial" size="2">Helper functions not
2468 overloaded properly</font></p></li>
2469 <li>
2470 <p style=margin:0in><font face="Arial" size="2">Some return types are
2471 'const CString&amp;' and could be just 'CString&amp;'</font></p></li>
2472 <li>
2473 <p style=margin:0in><font face="Arial" size="2">FormatV() passes size in
2474 characters to _alloca, should be in bytes</font></p></li>
2475 <li>
2476 <p style=margin:0in><font face="Arial" size="2">Fixed stack corruption in
2477 FormatV()</font></p></li>
2478 <li>
2479 <p style=margin:0in><font face="Arial" size="2">Improved boundaries checking
2480 for integer overflows/underflows<br>&nbsp;</font></p></li>
2481 </ul>
2482 <p style=margin:0in><font face="Arial" size="2">CScrollImpl:</font></p>
2483 <ul style='margin-top:0in;margin-bottom:0in'>
2484 <li>
2485 <p style=margin:0in><font face="Arial" size="2">Scroll bars problem when
2486 changing range</font></p></li>
2487 <li>
2488 <p style=margin:0in><font face="Arial" size="2">SetScrollOffset() doesn't
2489 move child windows</font></p></li>
2490 <li>
2491 <p style=margin:0in><font face="Arial" size="2">Range and thumb drawing
2492 problems</font></p></li>
2493 <li>
2494 <p style=margin:0in><font face="Arial" size="2">Possible overflow in
2495 OnMouseWheel()</font></p></li>
2496 <li>
2497 <p style=margin:0in><font face="Arial" size="2">Support for
2498 SIF_DISABLENOSCROLL</font></p></li>
2499 <li>
2500 <p style=margin:0in><font face="Arial" size="2">Added ScrollToView methods</font></p>
2501 </li>
2502 </ul>
2503 <p style=margin:0in>&nbsp;</p>
2504 <p style=margin:0in><font face="Arial" size="2">CMapScrollImpl:</font></p>
2505 <ul style='margin-top:0in;margin-bottom:0in'>
2506 <li>
2507 <p style=margin:0in><font face="Arial" size="2">SetScrollSize() incorrectly
2508 inverts xMin and xMax</font></p></li>
2509 <li>
2510 <p style=margin:0in><font face="Arial" size="2">SetScrollSize() uses bRedraw
2511 = NULL</font></p></li>
2512 </ul>
2513 <p style=margin:0in>&nbsp;</p>
2514 <p style=margin:0in><font face="Arial" size="2">CTheme:</font></p>
2515 <ul style='margin-top:0in;margin-bottom:0in'>
2516 <li>
2517 <p style=margin:0in><font face="Arial" size="2">GetThemeFont() bad parameter
2518 ordering</font></p></li>
2519 <li>
2520 <p style=margin:0in><font face="Arial" size="2">Uses LOGFONT and TEXTMETRIC
2521 incorrectly (SDK header problem)</font></p></li>
2522 </ul>
2523 <p style=margin:0in>&nbsp;</p>
2524 <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
2525 <ul style='margin-top:0in;margin-bottom:0in'>
2526 <li>
2527 <p style=margin:0in><font face="Arial" size="2">Improved sizing for Windows
2528 CE</font></p></li>
2529 <li>
2530 <p style=margin:0in><font face="Arial" size="2">CreateSimpleToolBarCtrl()
2531 should handle 24-bit bitmaps</font></p></li>
2532 <li>
2533 <p style=margin:0in><font face="Arial" size="2">Changed WinCE
2534 CCECommandBarCtrl typedef and added a PPC CMenuBarCtrl</font></p></li>
2535 <li>
2536 <p style=margin:0in><font face="Arial" size="2">UpdatesBarPosition() doesn't
2537 take Windows CE command bar into account</font></p></li>
2538 </ul>
2539 <p style=margin:0in>&nbsp;</p>
2540 <p style=margin:0in><font face="Arial" size="2">CDialogResize:</font></p>
2541 <ul style='margin-top:0in;margin-bottom:0in'>
2542 <li>
2543 <p style=margin:0in><font face="Arial" size="2">Enabled use for Windows CE</font></p>
2544 </li>
2545 <li>
2546 <p style=margin:0in><font face="Arial" size="2">Add WS_EX_DLGMODALFRAME to
2547 prevent empty icon</font></p></li>
2548 </ul>
2549 <p style=margin:0in>&nbsp;</p>
2550 <p style=margin:0in><font face="Arial" size="2">CReBarCtrl:</font></p>
2551 <ul style='margin-top:0in;margin-bottom:0in'>
2552 <li>
2553 <p style=margin:0in><font face="Arial" size="2">Background not painted when
2554 resized</font></p></li>
2555 <li>
2556 <p style=margin:0in><font face="Arial" size="2">Fixed typo in LockBands()</font></p>
2557 </li>
2558 <li>
2559 <p style=margin:0in><font face="Arial" size="2">MaximizeBand needs BOOL
2560 fIdeal argument</font></p></li>
2561 </ul>
2562 <p style=margin:0in>&nbsp;</p>
2563 <p style=margin:0in><font face="Arial" size="2">CRichEdit:</font></p>
2564 <ul style='margin-top:0in;margin-bottom:0in'>
2565 <li>
2566 <p style=margin:0in><font face="Arial" size="2">GetSelText() should
2567 support UNICODE strings</font></p>
2568 </li>
2569 <li>
2570 <p style=margin:0in><font face="Arial" size="2">GetSelText() uses lpstr instead of lpstrText</font></p></li>
2571 </ul>
2572 <p style=margin:0in>&nbsp;</p>
2573 <p style=margin:0in><font face="Arial" size="2">CHyperLink:</font></p>
2574 <ul style='margin-top:0in;margin-bottom:0in'>
2575 <li>
2576 <p style=margin:0in><font face="Arial" size="2">Added _xttoi() helper to
2577 avoid CRT in _ATL_MIN_CRT</font></p></li>
2578 <li>
2579 <p style=margin:0in><font face="Arial" size="2">Fixed resource leak by
2580 destroying tooltip window<br>&nbsp;</font></p></li>
2581 </ul>
2582 <p style=margin:0in><font face="Arial" size="2">CPropertySheetImpl:</font></p>
2583 <ul style='margin-top:0in;margin-bottom:0in'>
2584 <li>
2585 <p style=margin:0in><font face="Arial" size="2">Improved support for Windows
2586 CE</font></p></li>
2587 <li>
2588 <p style=margin:0in><font face="Arial" size="2">Sheet without title
2589 generates a memory fault on Windows CE</font></p></li>
2590 </ul>
2591 <p style=margin:0in>&nbsp;</p>
2592 <p style=margin:0in><font face="Arial" size="2">CFolderDialog:</font></p>
2593 <ul style='margin-top:0in;margin-bottom:0in'>
2594 <li>
2595 <p style=margin:0in><font face="Arial" size="2">Add a way to set an initial
2596 folder</font></p></li>
2597 <li>
2598 <p style=margin:0in><font face="Arial" size="2">Uses BFFM_IUNKNOWN which is
2599 not always defined</font></p></li>
2600 </ul>
2601 <p style=margin:0in>&nbsp;</p>
2602 <p style=margin:0in><font face="Arial" size="2">Update UI:</font></p>
2603 <ul style='margin-top:0in;margin-bottom:0in'>
2604 <li>
2605 <p style=margin:0in><font face="Arial" size="2">Add support to
2606 dynamically add UpdateUI elements</font></p></li>
2607 <li>
2608 <p style=margin:0in><font face="Arial" size="2">UIUpdateMenuBarElement()
2609 should use EnableMenu() instead of SetMenuItemInfo() for Windows CE</font></p>
2610 </li>
2611 </ul>
2612 <p style=margin:0in>&nbsp;</p>
2613 <p style=margin:0in><font face="Arial" size="2">CDC:</font></p>
2614 <ul style='margin-top:0in;margin-bottom:0in'>
2615 <li>
2616 <p style=margin:0in><font face="Arial" size="2">FillSolidRect() should
2617 restore background color</font></p></li>
2618 <li>
2619 <p style=margin:0in><font face="Arial" size="2">GetClipRgn() method
2620 missing</font></p></li>
2621 </ul>
2622 <p style=margin:0in>&nbsp;</p>
2623 <p style=margin:0in><font face="Arial" size="2">Printing:</font></p>
2624 <ul style='margin-top:0in;margin-bottom:0in'>
2625 <li>
2626 <p style=margin:0in><font face="Arial" size="2">
2627 CPrinter::CreatePrinterDC() and CreatePrinterIC() members should be
2628 const</font></p></li>
2629 <li>
2630 <p style=margin:0in><font face="Arial" size="2">CDevMode::CopyToHDEVMODE() is missing a call to GlobalUnlock()</font></p>
2631 </li>
2632 </ul>
2633 <p style=margin:0in>&nbsp;</p>
2634 <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
2635 <ul style='margin-top:0in;margin-bottom:0in'>
2636 <li>
2637 <p style=margin:0in><font face="Arial" size="2">Use WTL subfolder to
2638 create WTL category for VC7.x and VC8</font></p></li>
2639 <li>
2640 <p style=margin:0in><font face="Arial" size="2">Rename files from
2641 WTLApp7x to WTLAppWiz, and add VS2005 setup file</font></p></li>
2642 <li>
2643 <p style=margin:0in><font face="Arial" size="2">Fixed setup
2644 for x64</font></p></li>
2645 </ul>
2646 <p style=margin:0in>&nbsp;</p>
2647 <p style=margin:0in><font face="Arial" size="2">General:</font></p>
2648 <ul style='margin-top:0in;margin-bottom:0in'>
2649 <li>
2650 <p style=margin:0in><font face="Arial" size="2">Redefinition of _MAX_FNAME
2651 with Dinkumware Standard C++ Library on Windows CE</font></p></li>
2652 <li>
2653 <p style=margin:0in><font face="Arial" size="2">Added ATLVERIFY macro
2654 for ATL3</font></p></li>
2655 <li>
2656 <p style=margin:0in><font face="Arial" size="2">Support warning level 4</font></p>
2657 </li>
2658 <li>
2659 <p style=margin:0in><font face="Arial" size="2">Missing methods
2660 CToolBarCtrl::SetButtonInfo, InsertButton, CTabCtrl::SetItem,
2661 CComboBoxEx::InsertItem, SetItem</font></p></li>
2662 <li>
2663 <p style=margin:0in><font face="Arial" size="2">Missing support for
2664 WM_PRINTCLIENT</font></p></li>
2665 <li>
2666 <p style=margin:0in><font face="Arial" size="2">Removed usage of IsBad*
2667 functions</font></p></li>
2668 <li>
2669 <p style=margin:0in><font face="Arial" size="2">Fixed various compiler
2670 warnings</font></p></li>
2671 <li>
2672 <p style=margin:0in><font face="Arial" size="2">TCHAR bugs in various
2673 files</font></p></li>
2674 <li>
2675 <p style=margin:0in><font face="Arial" size="2">Improved Windows CE support and changes for Visual Studio 2005</font></p></li>
2676 </ul>
2677 <p style=margin:0in>&nbsp;</p>
2678 <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
2679 <ul style='margin-top:0in;margin-bottom:0in'>
2680 <li>
2681 <p style=margin:0in><font face="Arial" size="2">CMDIChildWindowImpl:
2682 HMENU should be destroyed in OnDestroy()</font></p>
2683 </li>
2684 <li>
2685 <p style=margin:0in><font face="Arial" size="2">CStatic: Should use
2686 STM_SETIMAGE instead of STM_SETICON for SetIcon() on Windows CE</font></p>
2687 </li>
2688 <li>
2689 <p style=margin:0in><font face="Arial" size="2">CButton: GetButtonStyle()
2690 uses wrong mask</font></p></li>
2691 <li>
2692 <p style=margin:0in><font face="Arial" size="2">CImageList: Made
2693 Duplicate() method const</font></p></li>
2694 <li>
2695 <p style=margin:0in><font face="Arial" size="2">CListViewCtrl: Made
2696 SubItemHitTest() method const</font></p></li>
2697 <li>
2698 <p style=margin:0in><font face="Arial" size="2">CTreeViewCtrl: GetItem()
2699 and SetItem() incorrectly restricted to _WIN32_IE &gt;= 0x0500</font></p>
2700 </li>
2701 <li>
2702 <p style=margin:0in><font face="Arial" size="2">CMonthCalendarCtrl:
2703 GetMonthRange() should be GetMaxTodayWidth()</font></p></li>
2704 <li>
2705 <p style=margin:0in><font face="Arial" size="2">CDateTimePickerCtrl:
2706 SetFormat() should have const argument</font></p></li>
2707 <li>
2708 <p style=margin:0in><font face="Arial" size="2">CBitmapButtonImpl: Fixed
2709 resource leak by destroying tooltip window</font></p></li>
2710 <li>
2711 <p style=margin:0in><font face="Arial" size="2">
2712 CMultiPaneStatusBarCtrlImpl: Cannot handle wide panes without resource
2713 strings</font></p></li>
2714 <li>
2715 <p style=margin:0in><font face="Arial" size="2">CCheckListViewCtrlImpl:
2716 Call CheckSelectedItems() through pT</font></p></li>
2717 <li>
2718 <p style=margin:0in><font face="Arial" size="2">CPaneContainerImpl:
2719 SetPaneContainerExtendedStyle() should use pT to call CalcSize()</font></p></li>
2720 <li>
2721 <p style=margin:0in><font face="Arial" size="2">CFindFile: Enabled for
2722 Windows CE</font></p></li>
2723 <li>
2724 <p style=margin:0in><font face="Arial" size="2">CPropertyPageImpl: Added
2725 handlers for callback messages</font></p></li>
2726 <li>
2727 <p style=margin:0in><font face="Arial" size="2">atlcrack.h: Added return
2728 value for MSG_WM_APPCOMMAND</font></p></li>
2729 <li>
2730 <p style=margin:0in><font face="Arial" size="2">CMenu: New method variants: AppendMenu, InsterMenu, ModifyMenu</font></p></li>
2731 <li>
2732 <p style=margin:0in><font face="Arial" size="2">CFont: Added arguments
2733 for bold and italic to CreatePointFont()</font></p></li>
2734 <li>
2735 <p style=margin:0in><font face="Arial" size="2">CSize: Added scalar
2736 operators for WTL::CSize and ATL::CSize</font></p></li>
2737 <li>
2738 <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:
2739 Allow changing the &quot;DocumentCount&quot; and &quot;Document%i&quot; registry values
2740 strings</font></p></li>
2741 <li>
2742 <p style=margin:0in><font face="Arial" size="2">CSplitterWindowImpl:
2743 Enabled use for Windows CE</font></p></li>
2744 </ul>
2745 </blockquote>
2746 <p style=margin:0in><br>
2747 &nbsp;</p>
2748 <p style=margin:0in><b><font face="Arial">
2749 <a name="Changes Between WTL 7.1 and 7.0"></a>Changes Between WTL 7.1 and 7.0</font></b></p>
2750 <p style=margin:0in>&nbsp;</p>
2751 <p style=margin:0in><font face="Arial" size="2">New and improved:</font></p>
2752 <blockquote style='margin-top:0in;margin-bottom:0in'>
2753 <p style=margin:0in><font face="Arial" size="2">VC7 Compatibility: Support for
2754 ATL7 Module classes and critical sections and AppWizard setup for VC++ 7.1</font></p>
2755 <p style=margin:0in><font face="Arial" size="2">Windows CE Support: Full
2756 compatibility with Windows CE platforms and AppWizard for eMbedded Visual C++</font></p>
2757 <p style=margin:0in><font face="Arial" size="2">Namespace Support: Automatic
2758 &quot;using ATL&quot; (ATL7 only) or &quot;using WTL&quot; can now be turned off</font></p>
2759 <p style=margin:0in><font face="Arial" size="2">CHyperLink New Features: not
2760 underlined, underlined when hover, command button, link tags</font></p>
2761 <p style=margin:0in><font face="Arial" size="2">CCustomWaitCursor class
2762 supports custom and animated wait cursors</font></p>
2763 <p style=margin:0in><font face="Arial" size="2">AtlCreateBoldFont() for
2764 creating bold version of an existing font</font></p>
2765 </blockquote>
2766 <p style=margin:0in>&nbsp;</p>
2767 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
2768 <blockquote style='margin-top:0in;margin-bottom:0in'>
2769 <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
2770 <ul style='margin-top:0in;margin-bottom:0in'>
2771 <li>
2772 <p style=margin:0in><font face="Arial" size="2">CreateSimpleToolBarCtrl() -
2773 remove dead code, improve error checking, add a global function that uses it</font></p>
2774 </li>
2775 <li>
2776 <p style=margin:0in><font face="Arial" size="2">Fix - PrepareChevronMenu() fails to
2777 get toolbar strings for Unicode</font></p>
2778 </li>
2779 <li>
2780 <p style=margin:0in><font face="Arial" size="2">CFrameWindowImplBase::Create()
2781 - improve ASSERT not to use m_hWnd if creation fails</font></p>
2782 </li>
2783 <li>
2784 <p style=margin:0in><font face="Arial" size="2">Fix - CFrameWndClassInfo::Register -
2785 should use %p formatting only for _WIN32_WINNT &gt;= 0x0500 or for _WIN64</font></p>
2786 </li>
2787 <li>
2788 <p style=margin:0in><font face="Arial" size="2">Fix - Chevron menus not positioned
2789 correctly with RTL</font></p>
2790 </li>
2791 <li>
2792 <p style=margin:0in><font face="Arial" size="2">Fix - CMDIChildWindowImpl: Problems
2793 creating maximized child windows and handling focus</font></p>
2794 </li>
2795 <li>
2796 <p style=margin:0in><font face="Arial" size="2">Fix - CMDIChildWindowImpl: Should
2797 activate on WM_MOUSEACTIVATE</font></p>
2798 </li>
2799 </ul>
2800 <p style=margin:0in>&nbsp;</p>
2801 <p style=margin:0in><font face="Arial" size="2">UpdateUI:</font></p>
2802 <ul style='margin-top:0in;margin-bottom:0in'>
2803 <li>
2804 <p style=margin:0in><font face="Arial" size="2">Fix - Incorrectly clears default
2805 item from the system menu in MDI apps</font></p>
2806 </li>
2807 <li>
2808 <p style=margin:0in><font face="Arial" size="2">Added UISetCheck with bool
2809 instead of int for the check state</font></p>
2810 </li>
2811 </ul>
2812 <p style=margin:0in>&nbsp;</p>
2813 <p style=margin:0in><font face="Arial" size="2">DDX:</font></p>
2814 <ul style='margin-top:0in;margin-bottom:0in'>
2815 <li>
2816 <p style=margin:0in><font face="Arial" size="2">Fix - Doesn't provide a way to
2817 change floating point precision</font></p>
2818 </li>
2819 <li>
2820 <p style=margin:0in><font face="Arial" size="2">Added DDX_CONTROL_HANDLE for
2821 non-CWindowImpl objects</font></p>
2822 </li>
2823 <li>
2824 <p style=margin:0in><font face="Arial" size="2">Added DDX_Check variant with
2825 bool instead of int for the check state</font></p>
2826 </li>
2827 </ul>
2828 <p style=margin:0in>&nbsp;</p>
2829 <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
2830 <ul style='margin-top:0in;margin-bottom:0in'>
2831 <li>
2832 <p style=margin:0in><font face="Arial" size="2">Fix - OnDrawItem() and OnMeasureItem()
2833 don't do a good check for owner-draw menu items</font></p>
2834 </li>
2835 <li>
2836 <p style=margin:0in><font face="Arial" size="2">Fix - Disabled 32-bit images not
2837 painted correctly in 3D menu mode</font></p>
2838 </li>
2839 <li>
2840 <p style=margin:0in><font face="Arial" size="2">Fix - Popup menus not positioned
2841 correctly with RTL</font></p>
2842 </li>
2843 <li>
2844 <p style=margin:0in><font face="Arial" size="2">Fix - Uses GCL_HICONSM instead of
2845 GCLP_HICONSM with GetClassLongPtr()</font></p>
2846 </li>
2847 </ul>
2848 <p style=margin:0in>&nbsp;</p>
2849 <p style=margin:0in><font face="Arial" size="2">MDI Command Bar:</font></p>
2850 <ul style='margin-top:0in;margin-bottom:0in'>
2851 <li>
2852 <p style=margin:0in><font face="Arial" size="2">Fix - Doesn't refresh icon if MDI
2853 children are different</font></p>
2854 </li>
2855 <li>
2856 <p style=margin:0in><font face="Arial" size="2">OnAllHookMessages() - improve
2857 code to handle MDI child window class icon</font></p>
2858 </li>
2859 <li>
2860 <p style=margin:0in><font face="Arial" size="2">Fix - OnNcLButtonDown() uses
2861 TPM_VERPOSANIMATION without checking Windows version</font></p>
2862 </li>
2863 <li>
2864 <p style=margin:0in><font face="Arial" size="2">Fix - Maximized MDI buttons in wrong
2865 place for RTL</font></p>
2866 </li>
2867 <li>
2868 <p style=margin:0in><font face="Arial" size="2">Should adjust cxIdeal for
2869 rebar bands for IE4</font></p>
2870 </li>
2871 <li>
2872 <p style=margin:0in><font face="Arial" size="2">Add support for different
2873 top-level menu widths by handling ideal size for rebar bands</font></p>
2874 </li>
2875 </ul>
2876 <p style=margin:0in>&nbsp;</p>
2877 <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
2878 <ul style='margin-top:0in;margin-bottom:0in'>
2879 <li>
2880 <p style=margin:0in><font face="Arial" size="2">Fix - Doesn't support MSDI
2881 application as a COM Server</font></p>
2882 </li>
2883 <li>
2884 <p style=margin:0in><font face="Arial" size="2">Fix - MDI with Form View - stack
2885 overflow closing maximized MDI child windows</font></p>
2886 </li>
2887 <li>
2888 <p style=margin:0in><font face="Arial" size="2">Fix - Generates VERSION resource
2889 name 'test1' regardless of the project name</font></p>
2890 </li>
2891 <li>
2892 <p style=margin:0in><font face="Arial" size="2">Fix - Dialog project with control
2893 hosting doesn't derive a dialog from CAxDialogImpl</font></p>
2894 </li>
2895 <li>
2896 <p style=margin:0in><font face="Arial" size="2">Fix - COM Server doesn't register
2897 type library</font></p>
2898 </li>
2899 <li>
2900 <p style=margin:0in><font face="Arial" size="2">Fix - COM Server doesn't register
2901 AppID properly</font></p>
2902 </li>
2903 </ul>
2904 <p style=margin:0in>&nbsp;</p>
2905 <p style=margin:0in><font face="Arial" size="2">CTreeViewCtrl:</font></p>
2906 <ul style='margin-top:0in;margin-bottom:0in'>
2907 <li>
2908 <p style=margin:0in><font face="Arial" size="2">Fix - GetItemData() needs better
2909 return value</font></p>
2910 </li>
2911 <li>
2912 <p style=margin:0in><font face="Arial" size="2">Fix - GetItemState() should use
2913 TVM_GETITEMSTATE instead of TVM_GETITEM for IE5</font></p>
2914 </li>
2915 <li>
2916 <p style=margin:0in><font face="Arial" size="2">GetItem() and SetItem() -
2917 added
2918 new variants that use TVITEMEX</font></p>
2919 </li>
2920 <li>
2921 <p style=margin:0in><font face="Arial" size="2">Fix - SortChildren() should add
2922 recurse flag argument</font></p>
2923 </li>
2924 <li>
2925 <p style=margin:0in><font face="Arial" size="2">Fix - CTreeItem doesn't support
2926 CTreeViewCtrlExT that has different TBase than CWindow</font></p>
2927 </li>
2928 </ul>
2929 <p style=margin:0in>&nbsp;</p>
2930 <p style=margin:0in><font face="Arial" size="2">CThemeImpl:</font></p>
2931 <ul style='margin-top:0in;margin-bottom:0in'>
2932 <li>
2933 <p style=margin:0in><font face="Arial" size="2">Fix - Uses scalar delete instead of
2934 the vector one</font></p>
2935 </li>
2936 <li>
2937 <p style=margin:0in><font face="Arial" size="2">Fix - EnableThemeDialogTexture()
2938 argument is BOOL instead of DWORD</font></p>
2939 </li>
2940 </ul>
2941 <p style=margin:0in>&nbsp;</p>
2942 <p style=margin:0in><font face="Arial" size="2">CFolderDialog:</font></p>
2943 <ul style='margin-top:0in;margin-bottom:0in'>
2944 <li>
2945 <p style=margin:0in><font face="Arial" size="2">Fix - EnableOK() passes wrong
2946 arguments to BFFM_ENABLEOK</font></p>
2947 </li>
2948 <li>
2949 <p style=margin:0in><font face="Arial" size="2">Fix - Always clears m_hWnd, which
2950 causes problem for nested messages</font></p>
2951 </li>
2952 </ul>
2953 <p style=margin:0in>&nbsp;</p>
2954 <p style=margin:0in><font face="Arial" size="2">CDialogResize:</font></p>
2955 <ul style='margin-top:0in;margin-bottom:0in'>
2956 <li>
2957 <p style=margin:0in><font face="Arial" size="2">Fix - DlgResize_Init() forces dialog
2958 to be visible by using SetRedraw()</font></p>
2959 </li>
2960 <li>
2961 <p style=margin:0in><font face="Arial" size="2">Forcing WS_THICKFRAME is not
2962 enough to make dialog resizable</font></p>
2963 </li>
2964 <li>
2965 <p style=margin:0in><font face="Arial" size="2">Min track size should be used
2966 for child dialogs as well</font></p>
2967 </li>
2968 <li>
2969 <p style=margin:0in><font face="Arial" size="2">Fix - DlgResize_PositionControl()
2970 incorrectly checks return value from MapWindowPoints()</font></p>
2971 </li>
2972 </ul>
2973 <p style=margin:0in>&nbsp;</p>
2974 <p style=margin:0in><font face="Arial" size="2">CAppModule:</font></p>
2975 <ul style='margin-top:0in;margin-bottom:0in'>
2976 <li>
2977 <p style=margin:0in><font face="Arial" size="2">Fix - CAppModule methods not
2978 thread-safe</font></p>
2979 </li>
2980 <li>
2981 <p style=margin:0in><font face="Arial" size="2">Fix - AddSettingChangeNotify()
2982 unusable in multithreaded apps because of delayed initialization</font></p>
2983 </li>
2984 </ul>
2985 <p style=margin:0in>&nbsp;</p>
2986 <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
2987 <ul style='margin-top:0in;margin-bottom:0in'>
2988 <li>
2989 <p style=margin:0in><font face="Arial" size="2">Fix - Delete() doesn't allow
2990 deleting more than the length of the string</font></p>
2991 </li>
2992 <li>
2993 <p style=margin:0in><font face="Arial" size="2">Fix - Append() can cause buffer
2994 overrun</font></p>
2995 </li>
2996 <li>
2997 <p style=margin:0in><font face="Arial" size="2">Fix - MakeReverse() can cause an
2998 infinite loop</font></p>
2999 </li>
3000 <li>
3001 <p style=margin:0in><font face="Arial" size="2">Fix - _cstrstr() unnecessarily
3002 inefficient</font></p>
3003 </li>
3004 <li>
3005 <p style=margin:0in><font face="Arial" size="2">Fix - FindOneOf() is not DBCS-aware</font></p>
3006 </li>
3007 <li>
3008 <p style=margin:0in><font face="Arial" size="2">Fix - Format() does not recognize %E</font></p>
3009 </li>
3010 <li>
3011 <p style=margin:0in><font face="Arial" size="2">Fix - TrimLeft() and TrimRight() are
3012 only half-way DBCS-aware</font></p>
3013 </li>
3014 <li>
3015 <p style=margin:0in><font face="Arial" size="2">Fix - May cause assertions or
3016 undefined behavior with SBCS</font></p>
3017 </li>
3018 </ul>
3019 <p style=margin:0in>&nbsp;</p>
3020 <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:</font></p>
3021 <ul style='margin-top:0in;margin-bottom:0in'>
3022 <li>
3023 <p style=margin:0in><font face="Arial" size="2">Fix - SetMaxEntries() has an
3024 incorrect ASSERT</font></p>
3025 </li>
3026 <li>
3027 <p style=margin:0in><font face="Arial" size="2">Add CString variant of the
3028 GetFromList() method</font></p>
3029 </li>
3030 <li>
3031 <p style=margin:0in><font face="Arial" size="2">Add a way to replace command
3032 IDs used for the MRU list</font></p>
3033 </li>
3034 <li>
3035 <p style=margin:0in><font face="Arial" size="2">Add a way to replace registry
3036 key name</font></p>
3037 </li>
3038 </ul>
3039 <p style=margin:0in>&nbsp;</p>
3040 <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
3041 <ul style='margin-top:0in;margin-bottom:0in'>
3042 <li>
3043 <p style=margin:0in><font face="Arial" size="2">CMessageLoop::Run() - improve
3044 the loop by checking bDoIdle before calling PeekMessage()</font></p>
3045 </li>
3046 <li>
3047 <p style=margin:0in><font face="Arial" size="2">CServerAppModule: Clean-up
3048 unused code</font></p>
3049 </li>
3050 <li>
3051 <p style=margin:0in><font face="Arial" size="2">Fix - CServerAppModule::MonitorProc()
3052 - no need to call _endthreadex()</font></p>
3053 </li>
3054 <li>
3055 <p style=margin:0in><font face="Arial" size="2">Fix - CListBox::GetText() and
3056 CComboBox::GetLBText() (CString variants) don't check for LBERR/CB_ERR</font></p>
3057 </li>
3058 <li>
3059 <p style=margin:0in><font face="Arial" size="2">Fix - CAxPropertyPageImpl doesn't
3060 create ActiveX controls with ATL7</font></p>
3061 </li>
3062 <li>
3063 <p style=margin:0in><font face="Arial" size="2">Fix - CDC::GetTextExtentExPoint()
3064 missing</font></p>
3065 </li>
3066 <li>
3067 <p style=margin:0in><font face="Arial" size="2">CDC::SetWindowExt() should
3068 have default value NULL for the lpSizeRet argument</font></p>
3069 </li>
3070 <li>
3071 <p style=margin:0in><font face="Arial" size="2">Fix - CPropertySheetWindow missing
3072 methods for PSM_INSERTPAGE, PSM_SETHEADERTITLE, and PSM_SETHEADERSUBTITLE;
3073 AddPage should return BOOL</font></p>
3074 </li>
3075 <li>
3076 <p style=margin:0in><font face="Arial" size="2">Fix - CMapScrollImpl::SetScrollSize()
3077 uses wrong variable</font></p>
3078 </li>
3079 <li>
3080 <p style=margin:0in><font face="Arial" size="2">Fix - CHyperLink: WM_UPDATEUISTATE
3081 causes repaint without WM_PAINT</font></p>
3082 </li>
3083 <li>
3084 <p style=margin:0in><font face="Arial" size="2">Fix - CUpDownCtrl::GetPos() returns
3085 incorrect value</font></p>
3086 </li>
3087 <li>
3088 <p style=margin:0in><font face="Arial" size="2">Fix - CUpDownCtrl::GetPos32()
3089 doesn't have default arg value</font></p>
3090 </li>
3091 <li>
3092 <p style=margin:0in><font face="Arial" size="2">Fix - CMultiPaneStatusBarCtrl:
3093 Always uses size grip for positioning panes</font></p>
3094 </li>
3095 <li>
3096 <p style=margin:0in><font face="Arial" size="2">Fix - CTabCtrl::InsertItem() should
3097 return int, not BOOL</font></p>
3098 </li>
3099 <li>
3100 <p style=margin:0in><font face="Arial" size="2">CReBarCtrl: Added LockBands()
3101 method</font></p>
3102 </li>
3103 <li>
3104 <p style=margin:0in><font face="Arial" size="2">Fix - CFont: uninitialized variable
3105 passed to DPtoLP</font></p>
3106 </li>
3107 <li>
3108 <p style=margin:0in><font face="Arial" size="2">Fix - CPrintDialogImpl: Crash when
3109 displaying Print Setup dialog</font></p>
3110 </li>
3111 <li>
3112 <p style=margin:0in><font face="Arial" size="2">Fix -
3113 CPageSetupDialogImpl::PaintHookProc() - should use T* and return UINT_PTR
3114 instead of UINT</font></p>
3115 </li>
3116 <li>
3117 <p style=margin:0in><font face="Arial" size="2">Fix - CPrintJob doesn't support
3118 printing to a file</font></p>
3119 </li>
3120 <li>
3121 <p style=margin:0in><font face="Arial" size="2">Fix - CSplitterImpl: Doesn't handle
3122 WM_CAPTURECHANGED - can get in an invalid state</font></p>
3123 </li>
3124 <li>
3125 <p style=margin:0in><font face="Arial" size="2">CRichEditCtrl: Add method for
3126 EM_SETTABSTOPS</font></p>
3127 </li>
3128 <li>
3129 <p style=margin:0in><font face="Arial" size="2">Fix - CFindFile::GetFilePath()
3130 checks for a trailing slash, but doesn't use that info</font></p>
3131 </li>
3132 </ul>
3133 <p style=margin:0in>&nbsp;</p>
3134 <p style=margin:0in><font face="Arial" size="2">General:</font></p>
3135 <ul style='margin-top:0in;margin-bottom:0in'>
3136 <li>
3137 <p style=margin:0in><font face="Arial" size="2">Fix - Problems compiling with /Zc:forScope
3138 ('for' loop scope conformance)</font></p>
3139 </li>
3140 <li>
3141 <p style=margin:0in><font face="Arial" size="2">Use named constants instead of
3142 values for pixel sizes, buffer lengths, etc.</font></p>
3143 </li>
3144 <li>
3145 <p style=margin:0in><font face="Arial" size="2">Support building with Managed
3146 C++ (/CLR)</font></p>
3147 </li>
3148 <li>
3149 <p style=margin:0in><font face="Arial" size="2">CMenuItemInfo - add run-time
3150 support for different versions of Windows</font></p>
3151 </li>
3152 <li>
3153 <p style=margin:0in><font face="Arial" size="2">CommCtrl.h change - additional
3154 fields in IMAGELISTDRAWPARAMS now depend on _WIN32_IE instead of _WIN32_WINNT</font></p>
3155 </li>
3156 <li>
3157 <p style=margin:0in><font face="Arial" size="2">Fix - Incorrect usage of CRegKey::QueryStringValue()</font></p>
3158 </li>
3159 <li>
3160 <p style=margin:0in><font face="Arial" size="2">Fix - Operator = for GDI and USER
3161 wrappers leaks handle if it's managed variant</font></p>
3162 </li>
3163 <li>
3164 <p style=margin:0in><font face="Arial" size="2">Fix - GDI and USER wrappers break
3165 under self-assignments</font></p>
3166 </li>
3167 <li>
3168 <p style=margin:0in><font face="Arial" size="2">Fix - Chaining messages with cracked
3169 handlers broken with ATL7</font></p>
3170 </li>
3171 <li>
3172 <p style=margin:0in><font face="Arial" size="2">Initialize all variables and
3173 structures prior to use</font></p>
3174 </li>
3175 <li>
3176 <p style=margin:0in><font face="Arial" size="2">Use new common control struct
3177 names</font></p>
3178 </li>
3179 </ul>
3180 </blockquote>
3181 <p style=margin:0in>&nbsp;</p>
3182 <p style=margin:0in>&nbsp;</p>
3183 <p style=margin:0in><b><font face="Arial">
3184 <a name="Changes Between WTL 7.0 and 3.1"></a>Changes Between WTL 7.0 and 3.1</font></b></p>
3185 <p style=margin:0in>&nbsp;</p>
3186 <p style=margin:0in><font face="Arial" size="2">New classes and features:</font></p>
3187 <blockquote style='margin-top:0in;margin-bottom:0in'>
3188 <p style=margin:0in><font face="Arial" size="2">Support for new Common Controls v6 messages</font></p>
3189 <p style=margin:0in><font face="Arial" size="2">Support for Visual Studio .NET and ATL 7.0</font></p>
3190 <p style=margin:0in><font face="Arial" size="2">WTLApp70 - new AppWizard for Visual Studio
3191 .NET</font></p>
3192 <p style=margin:0in><font face="Arial" size="2">CThemeImpl - implements support for Windows XP
3193 themes</font></p>
3194 <p style=margin:0in><font face="Arial" size="2">CMDICommandBarCtrl - implements Command Bar for
3195 MDI applications</font></p>
3196 </blockquote>
3197 <p style=margin:0in>&nbsp;</p>
3198 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
3199 <blockquote style='margin-top:0in;margin-bottom:0in'>
3200 <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
3201 <ul style='margin-top:0in;margin-bottom:0in'>
3202 <li><font face="Arial" size="2">Bogus assert in OnDestroy</font></li>
3203 <li><font face="Arial" size="2">Check marks can be truncated in large font
3204 settings</font></li>
3205 <li><font face="Arial" size="2">Use pT to access GetSystemSettings,
3206 DrawMenuText, DrawBitmapDisabled, Draw3DCheckmark, DoPopupMenu,
3207 DoTrackPopupMenu, TakeFocus, GiveFocusBack, so they can be overridden</font></li>
3208 <li><font face="Arial" size="2">No hot-tracking if main window is not active</font></li>
3209 <li><font face="Arial" size="2">Top level items not painted inactive if app
3210 looses activation while drop down menu is displayed</font></li>
3211 <li><font face="Arial" size="2">Added Windows XP flat menus support</font></li>
3212 <li><font face="Arial" size="2">Drop-down menu doesn't close if clicked
3213 again (Windows XP only)</font></li>
3214 <li><font face="Arial" size="2">Menu item text and accelerator text too
3215 close with some settings</font></li>
3216 <li><font face="Arial" size="2">Keyboard can still access clipped menu items</font></li>
3217 <li><font face="Arial" size="2">Added support for hiding keyboard navigation
3218 indicators until Alt key is pressed (system setting)</font></li>
3219 <li><font face="Arial" size="2">Added AddIcon and ReplaceIcon variants for
3220 icon resources</font></li>
3221 <li><font face="Arial" size="2">Image size calculated differently in
3222 different places</font></li>
3223 <li><font face="Arial" size="2">Add support for 32-bit (alpha channel)
3224 bitmaps for Windows XP</font></li>
3225 <li><font face="Arial" size="2">Fixed width calculation for default menu
3226 items</font></li>
3227 </ul>
3228 <p style=margin:0in>&nbsp;</p>
3229 <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
3230 <ul style='margin-top:0in;margin-bottom:0in'>
3231 <li><font face="Arial" size="2">AddSimpleReBarBandCtrl sets toolbar extended
3232 styles without preserving old ones</font></li>
3233 <li><font face="Arial" size="2">PrepareChevronMenu should not create menu
3234 items for buttons with TBSTATE_HIDDEN</font></li>
3235 <li><font face="Arial" size="2">TPM_VERPOSANIMATION will not be defined in
3236 atlframe.h if atlctrlw.h is included first</font></li>
3237 <li><font face="Arial" size="2">CreateSimpleToolBarCtrl - height might be
3238 too small if large font is used</font></li>
3239 <li><font face="Arial" size="2">PrepareChevronMenu uses TB_GETBUTTONTEXT,
3240 better use TB_GETBUTTONINFO</font></li>
3241 <li><font face="Arial" size="2">Chevron menu doesn't close if clicked again
3242 (Windows XP only)</font></li>
3243 <li><font face="Arial" size="2">Should check local classes for superclassing</font></li>
3244 <li><font face="Arial" size="2">Add support for 32-bit (alpha channel)
3245 bitmaps for Windows XP</font></li>
3246 </ul>
3247 <p style=margin:0in>&nbsp;</p>
3248 <p style=margin:0in><font face="Arial" size="2">Update UI:</font></p>
3249 <ul style='margin-top:0in;margin-bottom:0in'>
3250 <li><font face="Arial" size="2">UISetText can clear other menu item flags</font></li>
3251 <li><font face="Arial" size="2">CUpdateUI::UIUpdateState assigns value with
3252 |= instead of =</font></li>
3253 <li><font face="Arial" size="2">Added UISetDefault() and fix default state
3254 to work with menus</font></li>
3255 </ul>
3256 <p style=margin:0in>&nbsp;</p>
3257 <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
3258 <ul style='margin-top:0in;margin-bottom:0in'>
3259 <li><font face="Arial" size="2">GetBuffer() and GetBufferSetLength() should
3260 return NULL in out-of-memory condition</font></li>
3261 <li><font face="Arial" size="2">Added missing methods: separate c-tors for
3262 LPCSTR and LPCWSTR, CollateNoCase, TrimRight and TrimLeft variants, Find
3263 variants, moved FormatV to public</font></li>
3264 <li><font face="Arial" size="2">Fix _IsValidString usage</font></li>
3265 <li><font face="Arial" size="2">FormatV incorrectly calculates buffer size
3266 (too big)</font></li>
3267 <li><font face="Arial" size="2">Usage of _ttoi causes problems with _ATL_MIN_CRT
3268 in VC7</font></li>
3269 </ul>
3270 <p style=margin:0in>&nbsp;</p>
3271 <p style=margin:0in><font face="Arial" size="2">CDC:</font></p>
3272 <ul style='margin-top:0in;margin-bottom:0in'>
3273 <li><font face="Arial" size="2">GetTabbedTextExtent() should return DWORD
3274 instead of BOOL</font></li>
3275 <li><font face="Arial" size="2">Add FillRect() that accept color index
3276 instead of a brush handle</font></li>
3277 <li><font face="Arial" size="2">DrawDragRect() leaks regions and a brush</font></li>
3278 <li><font face="Arial" size="2">Improved DitherBlt() - added brushes as
3279 arguments for used colors</font></li>
3280 <li><font face="Arial" size="2">Added DrawShadowText() (uses LoadLibrary/GetProcAddress
3281 to run on older Windows)</font></li>
3282 </ul>
3283 <p style=margin:0in>&nbsp;</p>
3284 <p style=margin:0in><font face="Arial" size="2">CListViewCtrl:</font></p>
3285 <ul style='margin-top:0in;margin-bottom:0in'>
3286 <li><font face="Arial" size="2">SetItemState should use LVM_SETITEMSTATE</font></li>
3287 <li><font face="Arial" size="2">SetItemCount should return a BOOL</font></li>
3288 </ul>
3289 <p style=margin:0in>&nbsp;</p>
3290 <p style=margin:0in><font face="Arial" size="2">CRichEditCtrl:</font></p>
3291 <ul style='margin-top:0in;margin-bottom:0in'>
3292 <li><font face="Arial" size="2">Added SetCharFormat() variant that accepts
3293 flags (for SCF_ALL)</font></li>
3294 <li><font face="Arial" size="2">CharFromPos() should pass a pointer to
3295 POINTL in lParam</font></li>
3296 <li><font face="Arial" size="2">GetTextRange() - should add Unicode variant
3297 for rich edit version &gt;= 2</font></li>
3298 <li><font face="Arial" size="2">Added another FormatRange() that can accept
3299 a pointer to FORMATRANGE (needed for passing NULL to clear cache)</font></li>
3300 </ul>
3301 <p style=margin:0in>&nbsp;</p>
3302 <p style=margin:0in><font face="Arial" size="2">CHyperLink:</font></p>
3303 <ul style='margin-top:0in;margin-bottom:0in'>
3304 <li><font face="Arial" size="2">Allow overriding of Navigate and
3305 CalcLabelRect</font></li>
3306 <li><font face="Arial" size="2">Doesn't handle right or center alignment</font></li>
3307 </ul>
3308 <p style=margin:0in>&nbsp;</p>
3309 <p style=margin:0in><font face="Arial" size="2">CColorDialog:</font></p>
3310 <ul style='margin-top:0in;margin-bottom:0in'>
3311 <li><font face="Arial" size="2">Has static variables that were not
3312 initialized with _ATL_MIN_CRT</font></li>
3313 <li><font face="Arial" size="2">Fixed HookProc for ColorOK message - the
3314 message is not sent, but the hook proc is called directly</font></li>
3315 </ul>
3316 <p style=margin:0in>&nbsp;</p>
3317 <p style=margin:0in><font face="Arial" size="2">atlcrack.h:</font></p>
3318 <ul style='margin-top:0in;margin-bottom:0in'>
3319 <li><font face="Arial" size="2">MSG_WM_TIMER crack macro should cast to
3320 TIMERPROC instead of TIMERPROC*</font></li>
3321 <li><font face="Arial" size="2">Add cracked handlers for all new messages in
3322 Common Controls 6</font></li>
3323 </ul>
3324 <p style=margin:0in>&nbsp;</p>
3325 <p style=margin:0in><font face="Arial" size="2">atlapp.h:</font></p>
3326 <ul style='margin-top:0in;margin-bottom:0in'>
3327 <li><font face="Arial" size="2">Fixed problems with atlTraceUI with ATL7</font></li>
3328 <li><font face="Arial" size="2">#ifdefs for ATL7 were in the wrong place</font></li>
3329 </ul>
3330 <p style=margin:0in>&nbsp;</p>
3331 <p style=margin:0in><font face="Arial" size="2">atlctrls.h:</font></p>
3332 <ul style='margin-top:0in;margin-bottom:0in'>
3333 <li><font face="Arial" size="2">Add support in control classes for all new
3334 messages in Common Controls 6</font></li>
3335 </ul>
3336 <p style=margin:0in>&nbsp;</p>
3337 <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:</font></p>
3338 <ul style='margin-top:0in;margin-bottom:0in'>
3339 <li><font face="Arial" size="2">AtlCompactPath corrupts memory if filename
3340 is longer than requested compact size</font></li>
3341 <li><font face="Arial" size="2">ReadFromRegistry incorrectly checks for
3342 error when reading from registry</font></li>
3343 </ul>
3344 <p style=margin:0in>&nbsp;</p>
3345 <p style=margin:0in><font face="Arial" size="2">CSplitterWindow:</font></p>
3346 <ul style='margin-top:0in;margin-bottom:0in'>
3347 <li><font face="Arial" size="2">Incorrect calculation of middle position</font></li>
3348 <li><font face="Arial" size="2">3D border now drawn only if WS_EX_CLIENTEDGE
3349 is set</font></li>
3350 </ul>
3351 <p style=margin:0in>&nbsp;</p>
3352 <p style=margin:0in><font face="Arial" size="2">Printing:</font></p>
3353 <ul style='margin-top:0in;margin-bottom:0in'>
3354 <li><font face="Arial" size="2">Uses DWORD instead of an int for a job ID</font></li>
3355 <li><font face="Arial" size="2">CPrintJob::CancelPrintJob shouldn't have a
3356 return value</font></li>
3357 </ul>
3358 <p style=margin:0in>&nbsp;</p>
3359 <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
3360 <ul style='margin-top:0in;margin-bottom:0in'>
3361 <li><font face="Arial" size="2">CRegKey::QueryValue and SetValue are
3362 deprecated in ATL7</font></li>
3363 <li><font face="Arial" size="2">Added direct support for ATL7</font></li>
3364 <li><font face="Arial" size="2">Replace ScreenToClient and ClientToScreen
3365 with MapWindowPoints to support RTL layout</font></li>
3366 <li><font face="Arial" size="2">CFindFile::GetFilePath(LPTSTR...) returns
3367 path without the file name</font></li>
3368 <li><font face="Arial" size="2">MDI: Updating client edge in
3369 WM_WINDOWPOSCHANGING causes minimize/maximize/restore animation problems,
3370 use WM_WINDOWPOSCHANGED</font></li>
3371 <li><font face="Arial" size="2">Custom Draw: Added
3372 CCustomDraw::OnSubItemPrePaint() overrideable method</font></li>
3373 <li><font face="Arial" size="2">CFolderDialogImpl uses 'this' for
3374 BROWSEINFO.lParam instead of T*</font></li>
3375 <li><font face="Arial" size="2">CImageList::Destroy shouldn't use Detach()</font></li>
3376 <li><font face="Arial" size="2">ATL7 has its own AtlLoadString</font></li>
3377 <li><font face="Arial" size="2">CPropertySheet doesn't close when you press
3378 X button</font></li>
3379 <li><font face="Arial" size="2">Fixed problems for _U_STRINGorID and others
3380 that moved from atlbase.h to atlwin.h in ATL7</font></li>
3381 <li><font face="Arial" size="2">Add AtlMessageBox() that accepts either
3382 in-memory or resource strings</font></li>
3383 <li><font face="Arial" size="2">CScrollImpl: fixed bug with scrolling child
3384 windows</font></li>
3385 <li><font face="Arial" size="2">CPropertyPageImpl: Add new notification
3386 handlers to enable direct return values (use #ifdef _WTL_NEW_PAGE_NOTIFY_HANDLERS
3387 to use them)</font></li>
3388 <li><font face="Arial" size="2">Add AtlInitCommonControls() to simplify use</font></li>
3389 <li><font face="Arial" size="2">DDX: Fixed usage of the size of char arrays
3390 for DDX</font></li>
3391 <li><font face="Arial" size="2">CPageSetupDialog: changed usage of
3392 CWndProcThunk because of changes in ATL7</font></li>
3393 <li><font face="Arial" size="2">Fix confusing precedence in expressions</font></li>
3394 <li><font face="Arial" size="2">Removed forward declarations because default
3395 values for template arguments shouldn't be specified in two places (we don't
3396 need them anyway)</font></li>
3397 <li><font face="Arial" size="2">Win64: Fix /Wp64 warnings from 32-bit VC7
3398 compiler caused by SDK headers</font></li>
3399 <li><font face="Arial" size="2">Fix direct usage of English strings (they
3400 can be #defined to something else now)</font></li>
3401 <li><font face="Arial" size="2">AtlGetCommCtrlVersion not defined if _ATL_DLL
3402 is in ATL 3.0 (and CmdBar is using it)</font></li>
3403 </ul>
3404 <p style=margin:0in>&nbsp;</p>
3405 <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
3406 <ul style='margin-top:0in;margin-bottom:0in'>
3407 <li><font face="Arial" size="2">Added manifest for Common Controls 6</font></li>
3408 <li><font face="Arial" size="2">Loading Rich Edit DLL should use HMODULE</font></li>
3409 <li><font face="Arial" size="2">Should not use atlimpl.cpp for ATL7</font></li>
3410 <li><font face="Arial" size="2">Added message handler prototypes to
3411 generated files</font></li>
3412 <li><font face="Arial" size="2">VERSION resource always has VALUE &quot;OLESelfRegister&quot;
3413 (now only for COM servers)</font></li>
3414 <li><font face="Arial" size="2">Added option for putting implementation in
3415 CPP files</font></li>
3416 <li><font face="Arial" size="2">d-tor for the thread manager class in MSDI
3417 project executed after the heap is destroyed</font></li>
3418 <li><font face="Arial" size="2">Wrong settings when changing to a dialog
3419 project and back (AppWizard 6.0 only)</font></li>
3420 <li><font face="Arial" size="2">Remove cut/copy/paste accelerators for form
3421 view and dialogs projects</font></li>
3422 <li><font face="Arial" size="2">Fix toolbar bitmaps so they are not
3423 transparent (problem with Windows XP flat menus only)</font></li>
3424 <li><font face="Arial" size="2">Used CMDICommandBarCtrl for MDI apps</font></li>
3425 <li><font face="Arial" size="2">Add symbols required for VC7 Class Wizard to
3426 recognize an ATL project</font></li>
3427 <li><font face="Arial" size="2">Changed default styles for the rebar, so it
3428 does look OK without CmdBar and with manifest</font></li>
3429 <li><font face="Arial" size="2">Added setup programs for both AppWizards</font></li>
3430 <li><font face="Arial" size="2">Remove ignored resource attributes:
3431 MOVEABLE, PURE, etc. (AppWizard 7.0 only)</font></li>
3432 <li><font face="Arial" size="2">Add call to DefWindowProc to WinMain to
3433 resolve possible problems if MSLU is used</font></li>
3434 </ul>
3435 <p style=margin:0in>&nbsp;</p>
3436 <p style=margin:0in><font face="Arial" size="2">Samples:</font></p>
3437 <ul style='margin-top:0in;margin-bottom:0in'>
3438 <li><font face="Arial" size="2">Updated toolbar bitmaps, added #ifdefs for
3439 ATL7, added manifest file for CommCtrl6, qualified _U_RECT with WTL
3440 namespace, updated use of deprecated CRegKey functions, added VC7 projects</font></li>
3441 <li><font face="Arial" size="2">Added Alpha sample</font></li>
3442 </ul>
3443 </blockquote>
3444 <p style=margin:0in>&nbsp;</p>
3445 <p style=margin:0in>&nbsp;</p>
3446 <p style=margin:0in><b><font face="Arial">
3447 <a name="Changes Between WTL 3.1 and 3.0"></a>Changes Between WTL 3.1 and
3448 3.0</font></b></p>
3449 <p style=margin:0in>&nbsp;</p>
3450 <p style=margin:0in><font face="Arial" size="2">New classes:</font></p>
3451 <blockquote style='margin-top:0in;margin-bottom:0in'>
3452 <p style=margin:0in><font face="Arial" size="2">CPaneContainer - implements a window that
3453 provides a title bar and a close button (like Explorer)</font></p>
3454 <p style=margin:0in><font face="Arial" size="2">CDialogResize - an MI class that allows
3455 resizing of dialogs (or any windows with child windows/controls)</font></p>
3456 <p style=margin:0in><font face="Arial" size="2">CAxPropertyPageImpl - implements a property
3457 page that can host ActiveX controls</font></p>
3458 </blockquote>
3459 <p style=margin:0in>&nbsp;</p>
3460 <p style=margin:0in><font face="Arial" size="2">Fixes and enhancements:</font></p>
3461 <blockquote style='margin-top:0in;margin-bottom:0in'>
3462 <p style=margin:0in><font face="Arial" size="2">CServerAppModule now clears m_hEventShutdown to
3463 avoid calling CloseHandle twice</font></p>
3464 <p style=margin:0in>&nbsp;</p>
3465 <p style=margin:0in><font face="Arial" size="2">CString:</font></p>
3466 <ul style='margin-top:0in;margin-bottom:0in'>
3467 <li><font face="Arial" size="2">operator += now leaves original string
3468 intact if it's out of memory</font></li>
3469 <li><font face="Arial" size="2">Fixed bad DWORD_PTR usage in TrimRight,
3470 TrimLeft, Replace, Remove</font></li>
3471 <li><font face="Arial" size="2">Removed dependencies on CRT for projects
3472 that don't use it</font></li>
3473 <li><font face="Arial" size="2">Insert - fixed string corruption in release
3474 builds</font></li>
3475 <li><font face="Arial" size="2">Added optional floating point formatting
3476 (for projects that use CRT)</font></li>
3477 </ul>
3478 <p style=margin:0in>&nbsp;</p>
3479 <p style=margin:0in><font face="Arial" size="2">CEdit and CRichEditCtrl: SetSelAll and
3480 SetSelNone had reversed implementation</font></p>
3481 <p style=margin:0in>&nbsp;</p>
3482 <p style=margin:0in><font face="Arial" size="2">atlres.h: Changed IDs so that they are
3483 compatible with MFC's afxres.h</font></p>
3484 <p style=margin:0in>&nbsp;</p>
3485 <p style=margin:0in><font face="Arial" size="2">Command Bar:</font></p>
3486 <ul style='margin-top:0in;margin-bottom:0in'>
3487 <li><font face="Arial" size="2">Added LoadMappedImages()</font></li>
3488 <li><font face="Arial" size="2">Changed handling of left and right arrow
3489 keys so that they don't close context menus</font></li>
3490 <li><font face="Arial" size="2">Add code to handle left/right arrow keys
3491 correctly on mirrored (RTL) systems</font></li>
3492 <li><font face="Arial" size="2">Removed handler that eats parent window's
3493 WM_SETTINGCHANGE</font></li>
3494 <li><font face="Arial" size="2">Fixed bitmap resource leak in
3495 Draw3DCheckmark</font></li>
3496 <li><font face="Arial" size="2">Fixed incorrect usage of CharLower in
3497 OnMenuChar</font></li>
3498 <li><font face="Arial" size="2">Fixed wrong color for the disabled items in
3499 hi-contrast mode</font></li>
3500 <li><font face="Arial" size="2">Added code to gray menu items if main window
3501 is inactive</font></li>
3502 <li><font face="Arial" size="2">Fixed keyboard mnemonic handling for IE 4</font></li>
3503 <li><font face="Arial" size="2">Fixed hook problems with multiple cmdbars in
3504 the same thread</font></li>
3505 <li><font face="Arial" size="2">Added support for radio menu items</font></li>
3506 <li><font face="Arial" size="2">Added support for disabled top-level menu
3507 items (also added in CFrameWindowImpl::PrepareChevronMenu)</font></li>
3508 <li><font face="Arial" size="2">Added keyboard shortcut (Alt+/) to invoke
3509 chevron menu</font></li>
3510 <li><font face="Arial" size="2">Added support to override menu item length
3511 in a derived class</font></li>
3512 </ul>
3513 <p style=margin:0in>&nbsp;</p>
3514 <p style=margin:0in><font face="Arial" size="2">CBitmapButton:</font></p>
3515 <ul style='margin-top:0in;margin-bottom:0in'>
3516 <li><font face="Arial" size="2">Bypassed BUTTON DefWindowProc for hover
3517 style so that the button doesn't take focus</font></li>
3518 <li><font face="Arial" size="2">Added BMPBTN_AUTOFIRE extended style</font></li>
3519 </ul>
3520 <p style=margin:0in>&nbsp;</p>
3521 <p style=margin:0in><font face="Arial" size="2">CDC:</font></p>
3522 <ul style='margin-top:0in;margin-bottom:0in'>
3523 <li><font face="Arial" size="2">Added _WTL_FORWARD_DECLARE_CSTRING define to
3524 allow usage of methods that accept CString</font></li>
3525 <li><font face="Arial" size="2">Fixed errors in GetTextFace and
3526 GetMenuItemString</font></li>
3527 <li><font face="Arial" size="2">Added GetCharWidth32</font></li>
3528 <li><font face="Arial" size="2">Added DrawIconEx method</font></li>
3529 </ul>
3530 <p style=margin:0in>&nbsp;</p>
3531 <p style=margin:0in><font face="Arial" size="2">CMenu:</font></p>
3532 <ul style='margin-top:0in;margin-bottom:0in'>
3533 <li><font face="Arial" size="2">Implement following missing methods:<br>
3534 &nbsp;&nbsp;&nbsp; GetMenuDefaultItem<br>
3535 &nbsp;&nbsp;&nbsp; GetMenuInfo<br>
3536 &nbsp;&nbsp;&nbsp; GetMenuItemRect<br>
3537 &nbsp;&nbsp;&nbsp; HiliteMenuItem<br>
3538 &nbsp;&nbsp;&nbsp; IsMenu<br>
3539 &nbsp;&nbsp;&nbsp; MenuItemFromPoint<br>
3540 &nbsp;&nbsp;&nbsp; SetMenuDefaultItem<br>
3541 &nbsp;&nbsp;&nbsp; SetMenuInfo</font></li>
3542 <li><font face="Arial" size="2">GetMenuString - fixed to include space for
3543 terminating NULL character in returning string</font></li>
3544 </ul>
3545 <p style=margin:0in>&nbsp;</p>
3546 <p style=margin:0in><font face="Arial" size="2">GDI and USER classes should destroy the
3547 GDI/USER objects in Attach if GDI/USER resource is managed</font></p>
3548 <p style=margin:0in>&nbsp;</p>
3549 <p style=margin:0in><font face="Arial" size="2">CFrameWindowImpl:</font></p>
3550 <ul style='margin-top:0in;margin-bottom:0in'>
3551 <li><font face="Arial" size="2">OnToolTipText shouldn't save tool tip text
3552 if it's not for a menu</font></li>
3553 <li><font face="Arial" size="2">AddSimpleReBarBandCtrl now adds chevron
3554 style only for toolbars with buttons</font></li>
3555 <li><font face="Arial" size="2">AddSimpleReBarBand(Ctrl) - calc band ID if
3556 not specified</font></li>
3557 </ul>
3558 <p style=margin:0in>&nbsp;</p>
3559 <p style=margin:0in><font face="Arial" size="2">CRecentDocumentList:</font></p>
3560 <ul style='margin-top:0in;margin-bottom:0in'>
3561 <li><font face="Arial" size="2">Fix - UpdateMenu deletes wrong menu item
3562 when the list is empty</font></li>
3563 <li><font face="Arial" size="2">Added code to allow restricting the number
3564 of characters displayed by MRU menu items</font></li>
3565 </ul>
3566 <p style=margin:0in>&nbsp;</p>
3567 <p style=margin:0in><font face="Arial" size="2">Update UI:</font></p>
3568 <ul style='margin-top:0in;margin-bottom:0in'>
3569 <li><font face="Arial" size="2">Added support for blocking accelerators for
3570 disabled items</font></li>
3571 <li><font face="Arial" size="2">Improved search code assuming there are no
3572 duplicate entries (and added checks for duplicates)</font></li>
3573 </ul>
3574 <p style=margin:0in>&nbsp;</p>
3575 <p style=margin:0in><font face="Arial" size="2">CSplitterWindow:</font></p>
3576 <ul style='margin-top:0in;margin-bottom:0in'>
3577 <li><font face="Arial" size="2">CSplitterWindowImpl should derive from
3578 CSplitterImpl&lt;T , t_bVertical&gt; to allow overriding of methods</font></li>
3579 <li><font face="Arial" size="2">Added single pane mode and SetSinglePaneMode/GetSinglePaneMode</font></li>
3580 <li><font face="Arial" size="2">Added right/bottom aligned resize mode using
3581 extended styles SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED</font></li>
3582 </ul>
3583 <p style=margin:0in>&nbsp;</p>
3584 <p style=margin:0in><font face="Arial" size="2">atlcrack.h: Added handlers for following new
3585 messages:<br>
3586 &nbsp;&nbsp;&nbsp; WM_APPCOMMAND<br>
3587 &nbsp;&nbsp;&nbsp; WM_NCXBUTTONDOWN<br>
3588 &nbsp;&nbsp;&nbsp; WM_NCXBUTTONUP<br>
3589 &nbsp;&nbsp;&nbsp; WM_NCXBUTTONDBLCLK<br>
3590 &nbsp;&nbsp;&nbsp; WM_XBUTTONDOWN<br>
3591 &nbsp;&nbsp;&nbsp; WM_XBUTTONUP<br>
3592 &nbsp;&nbsp;&nbsp; WM_XBUTTONDBLCLK</font></p>
3593 <p style=margin:0in>&nbsp;</p>
3594 <p style=margin:0in><font face="Arial" size="2">Win64:</font></p>
3595 <ul style='margin-top:0in;margin-bottom:0in'>
3596 <li><font face="Arial" size="2">Dialog return value should use
3597 DWLP_MSGRESULT and SetWindowLongPtr</font></li>
3598 <li><font face="Arial" size="2">CMenu::InsertMenu, AppendMenu, ModifyMenu
3599 should have UINT_PTR for the menu ID</font></li>
3600 <li><font face="Arial" size="2">Added appropriate type casts</font></li>
3601 <li><font face="Arial" size="2">CFrameWindowImpl::m_szAutoName - changed the
3602 size to fit the pointer value size</font></li>
3603 <li><font face="Arial" size="2">CListViewCtrl::SortItems should use LPARAM
3604 for user data instead of DWORD</font></li>
3605 </ul>
3606 <p style=margin:0in>&nbsp;</p>
3607 <p style=margin:0in><font face="Arial" size="2">Misc:</font></p>
3608 <ul style='margin-top:0in;margin-bottom:0in'>
3609 <li><font face="Arial" size="2">Added optional mask argument to all methods
3610 for setting extended styles</font></li>
3611 <li><font face="Arial" size="2">CMDIWindow::MDIRestore - fixed to send
3612 WM_MDIRESTORE instead of WM_MDIICONARRANGE</font></li>
3613 <li><font face="Arial" size="2">CListViewCtrl: Added SortItemsEx method</font></li>
3614 <li><font face="Arial" size="2">CToolBarCtrl::GetButtonInfo - fixed to
3615 return int instead of BOOL</font></li>
3616 <li><font face="Arial" size="2">Added CToolBarCtrl::SetButtonSize and
3617 SetBitmapSize that accept cx and cy instead of SIZE</font></li>
3618 <li><font face="Arial" size="2">Printing: Changed how GetNewDevModeForPage
3619 works (comments in code)</font></li>
3620 <li><font face="Arial" size="2">CFileDialogImpl::_OnTypeChange incorrectly
3621 calls pT-&gt;OnSelChange instead of pT-&gt;OnTypeChange</font></li>
3622 <li><font face="Arial" size="2">CMultiPaneStatusBarCtrl::GetPaneTipText -
3623 fixed to use index instead of and ID internally</font></li>
3624 <li><font face="Arial" size="2">CWinDataExchange: Added references to
3625 arguments of DoDataExchange, so there are no level 4 warning even if the map
3626 is empty</font></li>
3627 <li><font face="Arial" size="2">CPropertySheetWindow: Added new, IE 5.0
3628 specific methods</font></li>
3629 <li><font face="Arial" size="2">CPropertyPageImpl: Added new, IE 5.0
3630 specific methods</font></li>
3631 </ul>
3632 <p style=margin:0in>&nbsp;</p>
3633 <p style=margin:0in><font face="Arial" size="2">AppWizard:</font></p>
3634 <ul style='margin-top:0in;margin-bottom:0in'>
3635 <li><font face="Arial" size="2">added calls to RemoveMessageFilter and
3636 RemoveIdleHandler in CMainFrame::OnDestroy for COM server projects</font></li>
3637 <li><font face="Arial" size="2">added scroll bars for HTML view</font></li>
3638 <li><font face="Arial" size="2">CAppServerModule now handles -embedding as
3639 well as -automation</font></li>
3640 <li><font face="Arial" size="2">corrected code in CMainFrame::OnShowToolBar
3641 to correctly identify the toolbar in a rebar</font></li>
3642 <li><font face="Arial" size="2">dialog based app code now derives from
3643 CUpdateUI as public</font></li>
3644 </ul>
3645 </blockquote>
3646 <p style=margin:0in>&nbsp;</p>
3647
3648 <p style=margin:0in><font face="Arial" size="2">- end of readme.html -</font></p>
3649
3650 </body>
3651
3652 </html>
+0
-0
src/third_party/zinnia less more
(Empty file)