├── .gitattributes
├── .gitignore
├── LICENSE
├── NOTICE
├── README.md
├── bin
└── ckrctxt.exe
├── ckrctxt.sln
├── ckrctxt.vcxproj
├── ckrctxt.vcxproj.filters
└── src
├── RcTextChecker.cpp
├── RcTextChecker.h
├── RcTextReader.cpp
├── RcTextReader.h
├── TextDlg.cpp
├── TextDlg.h
├── TextEntity.cpp
├── TextEntity.h
├── TextMeasurer.cpp
├── TextMeasurer.h
├── TextReporter.cpp
├── TextReporter.h
├── TextSize.h
├── ckrctxt.rc
├── compatibility.manifest
├── dpi_aware.manifest
├── resource.h
├── stdafx.cpp
├── stdafx.h
└── targetver.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
30 | # Visual Studio
31 | *.aps
32 | *.bat
33 | *.db
34 | *.opendb
35 | *.opensdf
36 | *.sdf
37 | *.suo
38 | *.user
39 | .vs/**
40 | !bin/*
41 | build.*
42 | Debug
43 | Release
44 | ipch
45 |
46 | # =========================
47 | # Operating System Files
48 | # =========================
49 |
50 | # OSX
51 | # =========================
52 |
53 | .DS_Store
54 | .AppleDouble
55 | .LSOverride
56 |
57 | # Thumbnails
58 | ._*
59 |
60 | # Files that might appear in the root of a volume
61 | .DocumentRevisions-V100
62 | .fseventsd
63 | .Spotlight-V100
64 | .TemporaryItems
65 | .Trashes
66 | .VolumeIcon.icns
67 |
68 | # Directories potentially created on remote AFP share
69 | .AppleDB
70 | .AppleDesktop
71 | Network Trash Folder
72 | Temporary Items
73 | .apdisk
74 |
75 | # Windows
76 | # =========================
77 |
78 | # Windows image file caches
79 | Thumbs.db
80 | ehthumbs.db
81 |
82 | # Folder config file
83 | Desktop.ini
84 |
85 | # Recycle Bin used on file shares
86 | $RECYCLE.BIN/
87 |
88 | # Windows Installer files
89 | *.cab
90 | *.msi
91 | *.msm
92 | *.msp
93 |
94 | # Windows shortcuts
95 | *.lnk
96 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright 2016 Caphyon Ltd.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ckrctxt :: RC Text Bounds Checker
2 | =================================
3 |
4 | `ckrctxt` is a simple tool that can check if any static *text block* (single or multi line) from a Visual Studio [resource file (RC)][RC] doesn't fit on given rectangle **size**.
5 | On application UI the text appears truncated or *clipped*.
6 |
7 | I assume most software developers write Win32 applications to be [High DPI][hidpi] aware.
8 | Otherwise, it would be immediately visible if an application is [not ready for High DPI][issues] because everything appears blury and text is pixelated.
9 |
10 | From all [High DPI issues][issues], this tool is a solution for the most subtle one: [Clipped UI elements or text][clipped].
11 |
12 | A dialog created with Visual Studio resource editor usually looks fine on standard DPI.
13 | However, after changing the Windows display DPI to other standard configuration (125%, 150%, 200% and up to 500% on Windows 10) you might notice that the full text doesn't fit anymore.
14 |
15 | `ckrctxt` tool was created to automatically detect such problems at build for [Advanced Installer][advinst].
16 |
17 | [advinst]: http://www.advancedinstaller.com/
18 | [hidpi]: https://msdn.microsoft.com/en-us/library/dd464646.aspx
19 | [issues]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266.aspx#appendix_c_common_high_dpi_issues
20 | [clipped]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266.aspx#clipped_ui_elements_or_text
21 | [RC]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa380599.aspx
22 |
23 |
24 | ### Build automation
25 |
26 | An integration into any build system will basically execute:
27 |
28 | ckrctxt --file [path-to-project].rc
29 |
30 | Performance: it can scan a RC file with 40k lines, from which 4.5k text blocks to analyse in just *~300ms*.
31 |
32 |
33 | ### Command line options
34 |
35 | Usage: ckrctxt [options]
36 |
37 | Options:
38 | -q, --quiet no output, just return the counter
39 | --no-header do not show header for current DPI
40 | -f, --file NAME Resource Script file name or path
41 |
42 |
43 | Examples
44 | --------
45 |
46 | Single line text found at 150% display DPI:
47 |
48 | display dpi: 144|144 (150%)
49 |
50 | Dialog ID: IDD_EDIT_BUILD
51 | -------------------------------
52 | 15225: LTEXT "Version:"
53 | - detected text size: (59,19)px
54 | - detected rect size: (25,8)du -> (56,19)px
55 | + minimum required rectangle size: (26,8)du
56 |
57 | 15227: LTEXT "Build:"
58 | - detected text size: (41,19)px
59 | - detected rect size: (16,8)du -> (36,19)px
60 | + minimum required rectangle size: (18,8)du
61 |
62 | Dialog ID: IDD_FORM_CREATE_FILE
63 | -------------------------------
64 | 17156: CONTROL "Create file with encoding:"
65 | - detected text size: (181,19)px
66 | - detected rect size: (90,10)du -> (178,24)px
67 | + minimum required rectangle size: (93,10)du
68 |
69 | Quick indication: the *CONTROL* element on line *17156* from *IDD_FORM_CREATE_FILE* dialog should have *93du* width.
70 |
71 | Multi line text found at 150% display DPI:
72 |
73 | display dpi: 144|144 (150%)
74 |
75 | Dialog ID: IDD_WIZARD_INSTALL
76 | -------------------------------
77 | 17246: CONTROL "The XYZ will not be installed by default.
78 | The user can choose to install it from ...
79 | or by selecting ..."
80 | - detected text size: (377,52)px
81 | - detected rect size: (267,29)du -> (383,47)px
82 | + minimum required rectangle size: (263,32)du [MULTILINE]
83 |
84 | Quick indication: the *CONTROL* element on line *17246* from *IDD_WIZARD_INSTALL* dialog should be extended to four lines (*32du*).
85 |
86 | Full description:
87 |
88 | - the multi line text from this checkbox fits in a rectangle of (377,52) pixels
89 | - the rectangle of this *CONTROL* element is (267,29) dialog units, converted to pixels this is (383,47)
90 | - the required text height is 52px, but the rectangle height is 47px
91 | - the solution is to modify the rectangle height to 52px, aproximated to 32du
92 |
93 |
94 | Implementation limits
95 | ---------------------
96 |
97 | At this time, the internal parser searches only for these text [elements][ID]:
98 |
99 | - `[LCR]TEXT`
100 | - `[DEF]PUSHBUTTON`
101 | - `CONTROL` (check, 3state, radio)
102 | - `RADIOBUTTON`
103 |
104 | [ID]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa381043.aspx
105 |
--------------------------------------------------------------------------------
/bin/ckrctxt.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Caphyon/ckrctxt/cfbc031664eeadc7f2ceebaf15031ad6060d7b68/bin/ckrctxt.exe
--------------------------------------------------------------------------------
/ckrctxt.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 14
3 | VisualStudioVersion = 14.0.24720.0
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ckrctxt", "ckrctxt.vcxproj", "{BB0D725B-F417-4C61-8942-5B40F0125F27}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|x86 = Debug|x86
10 | Release|x86 = Release|x86
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {BB0D725B-F417-4C61-8942-5B40F0125F27}.Debug|x86.ActiveCfg = Debug|Win32
14 | {BB0D725B-F417-4C61-8942-5B40F0125F27}.Debug|x86.Build.0 = Debug|Win32
15 | {BB0D725B-F417-4C61-8942-5B40F0125F27}.Release|x86.ActiveCfg = Release|Win32
16 | {BB0D725B-F417-4C61-8942-5B40F0125F27}.Release|x86.Build.0 = Release|Win32
17 | EndGlobalSection
18 | GlobalSection(SolutionProperties) = preSolution
19 | HideSolutionNode = FALSE
20 | EndGlobalSection
21 | EndGlobal
22 |
--------------------------------------------------------------------------------
/ckrctxt.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Create
33 | Create
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | {BB0D725B-F417-4C61-8942-5B40F0125F27}
46 | Win32Proj
47 | ckrctxt
48 |
49 |
50 |
51 | Application
52 | true
53 | Unicode
54 | v140
55 |
56 |
57 | Application
58 | false
59 | true
60 | Unicode
61 | v140
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 |
81 | Use
82 | Level4
83 | Disabled
84 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
85 | ProgramDatabase
86 | true
87 | true
88 | false
89 | $(ProjectDir);../../third-party
90 | MultiThreadedDebug
91 |
92 |
93 | Console
94 | true
95 |
96 |
97 |
98 |
99 | src/compatibility.manifest;src/dpi_aware.manifest
100 |
101 |
102 |
103 |
104 | Level4
105 | Use
106 | MaxSpeed
107 | true
108 | true
109 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
110 | ProgramDatabase
111 | true
112 | true
113 | false
114 | $(ProjectDir);../../third-party
115 | AnySuitable
116 | Speed
117 | true
118 | MultiThreaded
119 |
120 |
121 | Console
122 | true
123 | true
124 | true
125 |
126 |
127 |
128 |
129 | src/compatibility.manifest;src/dpi_aware.manifest
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/ckrctxt.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {824f8c77-0d5e-4d27-b524-87c59b38ee8d}
18 |
19 |
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Resource Files
44 |
45 |
46 | win
47 |
48 |
49 | win
50 |
51 |
52 |
53 |
54 | Resource Files
55 |
56 |
57 |
58 |
59 | win
60 |
61 |
62 | Source Files
63 |
64 |
65 | Source Files
66 |
67 |
68 | Source Files
69 |
70 |
71 | Source Files
72 |
73 |
74 | Source Files
75 |
76 |
77 | Source Files
78 |
79 |
80 |
81 |
82 | win
83 |
84 |
85 | win
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/RcTextChecker.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "stdafx.h"
16 | #include "RcTextChecker.h"
17 | #include "RcTextReader.h"
18 | #include "TextDlg.h"
19 | #include "TextEntity.h"
20 | #include "TextSize.h"
21 | #include "TextMeasurer.h"
22 | #include "TextReporter.h"
23 |
24 | using namespace std;
25 |
26 | int RcTextChecker::Run(const wstring & aFilename, bool quiet) const
27 | {
28 | // open resource script file
29 | RcTextReader rsfile(aFilename);
30 | if ( !rsfile.IsOpen() )
31 | {
32 | wcout << L"Err: resource script file '" << aFilename
33 | << L"' was not found or could not be opened!" << endl << endl;
34 | return -1;
35 | }
36 |
37 | TextEntity textEnt; // one text block from resource script file
38 | TextMeasurer textMsr;
39 | TextReporter textRep( wcout, rsfile.GetCodepage() );
40 |
41 | int count = 0;
42 | while (true)
43 | {
44 | rsfile >> textEnt;
45 | if ( !rsfile.HasFoundText() )
46 | break;
47 |
48 | // compute text block size (px)
49 | textMsr.ComputeSize(textEnt);
50 |
51 | // text doesn't fit in rectangle area
52 | if ( textMsr.IsResizeNeeded() )
53 | {
54 | if (!quiet)
55 | textRep << textMsr.GetRealSize();
56 | ++count;
57 | }
58 | }
59 |
60 | return count;
61 | }
62 |
63 | //----------------------------------------------------------------------------
64 | // Global helper functions.
65 |
66 | void usage(char * aMsg = nullptr);
67 | void printDPI();
68 |
69 | int _tmain(int argc, _TCHAR ** argv)
70 | {
71 | if (argc < 3)
72 | {
73 | usage( "Err: expected at least two arguments!" );
74 | return -1;
75 | }
76 |
77 | bool quiet = false;
78 | bool showdpi = true;
79 | wstring rsname; // resource script file name
80 | for (int i = 1; i < argc; ++i) // read command arguments
81 | {
82 | wstring argvi( argv[i] );
83 | if ( (argvi == L"-f") || (argvi == L"--file") )
84 | {
85 | if (++i < argc)
86 | rsname = wstring( argv[i] );
87 | }
88 | else if ( (argvi == L"-q") || (argvi == L"--quiet") )
89 | quiet = true;
90 | else if (argvi == L"--no-header")
91 | showdpi = false;
92 | else
93 | wcout << L"Err: unknown argument: " << argv[i] << endl;
94 | }
95 |
96 | // check if we've got a name
97 | if ( rsname.empty() )
98 | {
99 | cout << endl;
100 | usage();
101 | return -1;
102 | }
103 |
104 | // DPI header
105 | if (!quiet && showdpi)
106 | printDPI();
107 |
108 | DWORD start = ::GetTickCount();
109 | RcTextChecker batch;
110 | int count = batch.Run(rsname, quiet);
111 | DWORD finish = ::GetTickCount();
112 |
113 | // display summary
114 | if (!quiet && (count > 0))
115 | cout << "No. of detected problems: " << count
116 | << " (in " << (finish - start) << "ms)" << endl << endl;
117 |
118 | return count;
119 | }
120 |
121 | // show all supported arguments
122 | void usage(char * aMsg)
123 | {
124 | if (nullptr != aMsg)
125 | cout << aMsg << endl
126 | << endl;
127 |
128 | cout << "Usage: ckrctxt [options]" << endl
129 | << endl
130 | << "Options:" << endl
131 | << "-q, --quiet no output, just return the counter" << endl
132 | << "--no-header do not show header for current DPI" << endl
133 | << "-f, --file NAME Resource Script file name or path" << endl
134 | << endl;
135 | }
136 |
137 | // show current DPI settings
138 | void printDPI()
139 | {
140 | int dpiY = ::GetDeviceCaps(::GetDC(NULL), LOGPIXELSY);
141 | int dpiX = ::GetDeviceCaps(::GetDC(NULL), LOGPIXELSX);
142 | cout << "display dpi: " << dpiX << "|" << dpiY
143 | << " (" << ::MulDiv(dpiY, 100, 96) << "%)"
144 | << endl << endl;
145 | }
146 |
--------------------------------------------------------------------------------
/src/RcTextChecker.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | /**
18 | * Check and report the required size for all nonconforming
19 | * text blocks read from a Visual Studio resource script file.
20 | *
21 | * @author Teodor MICU
22 | */
23 | class RcTextChecker
24 | {
25 | public:
26 | /**
27 | * Run batch...
28 | *
29 | * @return detected number of text blocks that don't fit on rectangle area
30 | */
31 | int Run(const std::wstring & aFilename, bool quiet = false) const;
32 | };
33 |
--------------------------------------------------------------------------------
/src/RcTextReader.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "stdafx.h"
16 | #include "RcTextReader.h"
17 | #include "TextEntity.h"
18 |
19 | using namespace std;
20 |
21 | namespace
22 | {
23 | // NAME DIALOGEX 0, 0, 340, 180
24 | const wregex kDlgExp(L"^([^ ]+) DIALOGEX [0-9]+, [0-9]+, [0-9]+, [0-9]+$");
25 |
26 | // LTEXT "Text",ID_TEXT,53,25,156,24[,FLAGS]
27 | const wregex kTxtExp(L"^ +([LCR]TEXT) +\"(.+)\",([^,]+),"
28 | L"(\\d+),(\\d+),(\\d+),(\\d+)(?:,(.*))?$");
29 |
30 | // CONTROL "Run as..",ID_RUN,"Button",FLAGS,30,190,81,10
31 | const wregex kCtlExp(L"^ +(CONTROL) +\"(.+)\",([^,]+),\"([A-Za-z]+)\",([^,]*),"
32 | L"(\\d+),(\\d+),(\\d+),(\\d+)$");
33 |
34 | // RADIOBUTTON "Use..",IDC_USE,30,48,142,10[,FLAGS]
35 | const wregex kRbtExp(L"^ +(RADIOBUTTON) +\"(.+)\",([^,]+),"
36 | L"(\\d+),(\\d+),(\\d+),(\\d+).*$");
37 |
38 | // [DEF]PUSHBUTTON "OK",ID_OK,103,47,50,16[,FLAGS]
39 | const wregex kBtnExp(L"^ +((?:DEF)?PUSHBUTTON) +\"(.+)\",([^,]+),"
40 | L"(\\d+),(\\d+),(\\d+),(\\d+)(?:,(.*))?$");
41 | }
42 |
43 | //----------------------------------------------------------------------------
44 | // Class definition - RcTextReader public methods.
45 |
46 | RcTextReader::RcTextReader(const wstring & aFilename)
47 | : mIStream(aFilename), mCodepage(CODEPAGE_ENGLISH), mFound(false), mLineNr(0)
48 | {
49 | // detect ANSI code page
50 | string cp = DotCodepage(aFilename);
51 | if (CODEPAGE_ENGLISH != mCodepage) // custom ANSI encoding
52 | mIStream.imbue( std::locale(cp) );
53 | }
54 |
55 | bool RcTextReader::IsOpen() const
56 | {
57 | return mIStream.is_open();
58 | }
59 |
60 | UINT RcTextReader::GetCodepage() const
61 | {
62 | return mCodepage;
63 | }
64 |
65 | bool RcTextReader::HasFoundText() const
66 | {
67 | return mFound;
68 | }
69 |
70 | RcTextReader & RcTextReader::operator>>(TextEntity & aTextEnt)
71 | {
72 | wstring line; // first line read
73 | wstring line23; // (optional) extra lines read
74 | TextEntity::TypeCode code = TextEntity::OTHER;
75 |
76 | wsmatch mr; // match results
77 |
78 | mFound = false;
79 | while ( mIStream.good() )
80 | {
81 | // get first line, might be a sequence of two or three
82 | getline(mIStream, line);
83 | ++mLineNr;
84 |
85 | // empty line, or one CR (#13)
86 | if (line.size() <= 1)
87 | continue;
88 |
89 | // update current dialog name
90 | if (L' ' != line[0]) // not a SPACE
91 | {
92 | if ( regex_match(line, mr, kDlgExp) )
93 | mDlgName = mr[1];
94 |
95 | // all TEXT lines start with four spaces
96 | continue;
97 | }
98 |
99 | // get next lines, one CONTROL line might be split in multiple lines
100 | while ( (L',' == line[line.size()-1]) ||
101 | (L'|' == line[line.size()-1]) )
102 | {
103 | getline(mIStream, line23);
104 | ++mLineNr;
105 |
106 | wstring::size_type first = line23.find_first_not_of(L" \t");
107 | wstring::size_type last = line23.find_last_not_of(L" \t\r");
108 | line.append( line23.substr(first, last-first+1) );
109 | }
110 |
111 | // detect type
112 | if ( regex_match(line, mr, kTxtExp) )
113 | code = TextEntity::TEXT;
114 | else if ( regex_match(line, mr, kBtnExp) )
115 | code = TextEntity::PUSHBUTTON;
116 | else if ( regex_match(line, mr, kCtlExp) )
117 | code = TextEntity::CONTROLBUTTON;
118 | else if ( regex_match(line, mr, kRbtExp) )
119 | code = TextEntity::RADIOBUTTON;
120 | else
121 | continue;
122 |
123 | // ignore these small buttons (resized and repositioned in code)
124 | if ( (TextEntity::PUSHBUTTON == code) && (L"..." == mr[2]) )
125 | continue;
126 |
127 | // ignore (on purpose) truncated static text
128 | if ( (TextEntity::TEXT == code) && (mr[8].matched) )
129 | {
130 | if ( wstring::npos != mr[8].str().find(L"ELLIPSIS") )
131 | continue;
132 | }
133 |
134 | mFound = true;
135 | break;
136 | } // end while
137 |
138 | // stop processing if no text block was found
139 | if (!mFound)
140 | return *this;
141 |
142 | aTextEnt.mText = mr[2];
143 | aTextEnt.mType = mr[1];
144 |
145 | // TODO: SS_NOPREFIX flag -> no escape
146 | // "" is an escape sequence
147 | aTextEnt.ReplaceAll(L"\"\"", L"\"");
148 |
149 | // && is an escape sequence
150 | aTextEnt.ReplaceAll(L"&&", L"&");
151 |
152 | // remove & from text string if followed by an alpha
153 | wstring::size_type amppos = aTextEnt.mText.find(L"&");
154 | if ( (amppos < aTextEnt.mText.size()) &&
155 | isalpha(aTextEnt.mText[amppos+1]) )
156 | aTextEnt.mText.erase(amppos, 1);
157 |
158 | aTextEnt.mMultiLine = true; // TEXT does word wrap by default
159 | switch (code)
160 | {
161 | case TextEntity::CONTROLBUTTON:
162 | // must have at least 9 values (+1)
163 | assert(mr.size() >= 10);
164 |
165 | // multiline control button
166 | if ( (L"Button" == mr[4]) &&
167 | (wstring::npos == mr[5].str().find(L"BS_MULTILINE")) )
168 | {
169 | aTextEnt.mMultiLine = false;
170 | }
171 | // multiline static text
172 | else if ( (L"Static"== mr[4]) &&
173 | (wstring::npos != mr[5].str().find(L"SS_LEFTNOWORDWRAP")) )
174 | {
175 | code = TextEntity::TEXT;
176 | aTextEnt.mMultiLine = false;
177 | }
178 |
179 | aTextEnt.mRc.left = stoi( mr[6] ); // X
180 | aTextEnt.mRc.top = stoi( mr[7] ); // Y
181 | aTextEnt.mRc.right = stoi( mr[8] ); // Width
182 | aTextEnt.mRc.bottom = stoi( mr[9] ); // Height
183 | break;
184 |
185 | case TextEntity::RADIOBUTTON:
186 | case TextEntity::PUSHBUTTON:
187 | // multiline push button
188 | if ( (mr.size() < 9) ||
189 | (wstring::npos == mr[8].str().find(L"BS_MULTILINE")) )
190 | aTextEnt.mMultiLine = false;
191 | // NO break;
192 |
193 | case TextEntity::TEXT:
194 | // must have at least 7 values (+1)
195 | assert(mr.size() >= 8);
196 |
197 | aTextEnt.mRc.left = stoi( mr[4] ); // X
198 | aTextEnt.mRc.top = stoi( mr[5] ); // Y
199 | aTextEnt.mRc.right = stoi( mr[6] ); // Width
200 | aTextEnt.mRc.bottom = stoi( mr[7] ); // Height
201 | break;
202 |
203 | default:
204 | assert(!"unsupported type code!");
205 | } // end switch
206 |
207 | aTextEnt.mDlgName = mDlgName;
208 | aTextEnt.mLineNr = mLineNr;
209 | aTextEnt.mCode = code;
210 | return *this;
211 | }
212 |
213 | //----------------------------------------------------------------------------
214 | // Class definition - RcTextReader private methods.
215 |
216 | string RcTextReader::DotCodepage(const wstring & aFilename)
217 | {
218 | ifstream file(aFilename);
219 | if ( !file.is_open() )
220 | return string(".1252");
221 |
222 | string line;
223 | smatch mr; // match results
224 | regex exp("^#pragma code_page\\((\\d+)\\)$");
225 |
226 | while ( !file.eof() )
227 | {
228 | getline(file, line);
229 |
230 | // empty line
231 | if (line.size() <= 1)
232 | continue;
233 |
234 | // skip anything but macros
235 | if ('#' != line[0])
236 | continue;
237 |
238 | if ( regex_match(line, mr, exp) )
239 | break;
240 | }
241 | file.close();
242 |
243 | // no #pragma code_page()
244 | if ( mr.empty() )
245 | return string(".1252");
246 |
247 | mCodepage = stoi( mr[1] );
248 | return "." + mr[1].str();
249 | }
250 |
--------------------------------------------------------------------------------
/src/RcTextReader.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | struct TextEntity;
18 |
19 | /**
20 | * Reader for a resource script file. Ignores all non-text blocks.
21 | *
22 | * @author Teodor MICU
23 | */
24 | class RcTextReader
25 | {
26 | public:
27 | /**
28 | * Class constructor.
29 | */
30 | RcTextReader(const std::wstring & /*aFilename*/);
31 |
32 | /**
33 | * @return true if the file was found and is open for reading
34 | */
35 | bool IsOpen() const;
36 |
37 | /**
38 | * @return the ANSI codepage found in the resource script file
39 | */
40 | UINT GetCodepage() const;
41 |
42 | /**
43 | * Method that checks if a text block was (previously) read from file.
44 | *
45 | * @return true if last extraction was successful, false otherwise
46 | */
47 | bool HasFoundText() const;
48 |
49 | /**
50 | * Read the next text block with all associated parameters.
51 | */
52 | RcTextReader & operator>>(TextEntity & /*aTextEnt*/);
53 |
54 | private:
55 | /**
56 | * Get the string from pragma code_page() directive, dot prefixed.
57 | * (".1252" for ENGLISH_US, the default ANSI encoding)
58 | */
59 | std::string DotCodepage(const std::wstring & /*aFilename*/);
60 |
61 | std::wifstream mIStream; // (file) input stream
62 | UINT mCodepage;
63 |
64 | // attributes read from the resource script file
65 | std::wstring mDlgName; // current dialog name
66 | int mLineNr; // current line# read from file
67 | bool mFound; // new text block read from file
68 | };
69 |
--------------------------------------------------------------------------------
/src/TextDlg.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "stdafx.h"
16 | #include "TextDlg.h"
17 |
18 | LRESULT TextDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
19 | {
20 | mDC = GetDC();
21 | mDC.SelectFont( GetFont() );
22 |
23 | // base units for non-system font (custom)
24 | // http://support.microsoft.com/kb/145994
25 | RECT dlgbu = { 0, 0, 4, 8 };
26 | MapDialogRect(&dlgbu);
27 | mDlgBU.cx = dlgbu.right;
28 | mDlgBU.cy = dlgbu.bottom;
29 |
30 | // detect text height
31 | TEXTMETRIC tm;
32 | mDC.GetTextMetrics( &tm );
33 |
34 | CSize szText;
35 | szText.cx = tm.tmAveCharWidth;
36 | szText.cy = tm.tmHeight;
37 | mDC.LPtoDP(&szText);
38 | mTxtHeight = szText.cy;
39 |
40 | return TRUE;
41 | }
42 |
43 | CSize TextDlg::GetDlgBaseUnits() const
44 | {
45 | return mDlgBU;
46 | }
47 |
48 | CSize TextDlg::GetTextSize(const std::wstring & aText) const
49 | {
50 | CSize szText;
51 | mDC.GetTextExtent(aText.c_str(), -1, &szText);
52 | mDC.LPtoDP(&szText);
53 |
54 | return szText;
55 | }
56 |
57 | LONG TextDlg::GetTextHeight() const
58 | {
59 | return mTxtHeight;
60 | }
61 |
62 | CSize TextDlg::DUtoPX(LONG aWidthDU, LONG aHeightDU) const
63 | {
64 | RECT rc = { 0, 0, aWidthDU, aHeightDU };
65 | ::MapDialogRect(*this, &rc);
66 |
67 | return CSize(rc.right, rc.bottom);
68 | }
69 |
70 | CSize TextDlg::PXtoDU(LONG aWidthDU, LONG aHeightDU) const
71 | {
72 | LONG widthDU = ::MulDiv(aWidthDU, 4, mDlgBU.cx);
73 | LONG heightDU = ::MulDiv(aHeightDU, 8, mDlgBU.cy);
74 |
75 | return CSize(widthDU, heightDU);
76 | }
77 |
--------------------------------------------------------------------------------
/src/TextDlg.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | #include "resource.h"
18 |
19 | /**
20 | * Simple dialog used for computing the required size for some text.
21 | *
22 | * @author Teodor MICU
23 | */
24 | class TextDlg : public CDialogImpl
25 | {
26 | public:
27 | enum { IDD = IDD_MEASURE_DIALOG };
28 |
29 | BEGIN_MSG_MAP(TextDlg)
30 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
31 | END_MSG_MAP()
32 |
33 | /**
34 | * Calculate dialog base units based on the current font.
35 | */
36 | CSize GetDlgBaseUnits() const;
37 |
38 | /**
39 | * Calculate the size of text based on the current font.
40 | */
41 | CSize GetTextSize(const std::wstring & /*aText*/) const;
42 |
43 | /**
44 | * Calculate the height of (one line) text based on the current font.
45 | */
46 | LONG GetTextHeight() const;
47 |
48 | /**
49 | * Convert du->px based on the current font.
50 | */
51 | CSize DUtoPX(LONG /*aWidthDU*/, LONG /*aHeightDU*/) const;
52 |
53 | /**
54 | * Convert px->du based on the current font.
55 | */
56 | CSize PXtoDU(LONG /*aWidthDU*/, LONG /*aHeightDU*/) const;
57 |
58 | private:
59 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
60 |
61 | CDCHandle mDC; // handle for device context
62 | CSize mDlgBU; // dialog base units
63 | LONG mTxtHeight;
64 | };
65 |
--------------------------------------------------------------------------------
/src/TextEntity.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "stdafx.h"
16 | #include "TextEntity.h"
17 | #include "TextSize.h"
18 |
19 | using std::wstring;
20 |
21 | TextEntity::operator TextSize() const
22 | {
23 | TextSize szText;
24 | szText.mDlgName = this->mDlgName;
25 | szText.mLineNr = this->mLineNr;
26 | szText.mText = this->mText;
27 | szText.mType = this->mType;
28 | szText.mMultiLine = this->mMultiLine;
29 | szText.mRcWidthDU = this->mRc.right;
30 | szText.mRcHeightDU = this->mRc.bottom;
31 |
32 | return szText;
33 | }
34 |
35 | void TextEntity::ReplaceAll(const wstring & aToken, const wstring & aReplace)
36 | {
37 | if (mText.empty() || aToken.empty())
38 | return;
39 |
40 | size_t pos = mText.find(aToken);
41 | while (pos != wstring::npos)
42 | {
43 | mText.replace(pos, aToken.length(), aReplace);
44 | pos = mText.find(aToken, pos + aReplace.length());
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/TextEntity.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | struct TextSize;
18 |
19 | /**
20 | * A text block with all associated parameters.
21 | * (usually read from a Visual Studio resource script file)
22 | * - [LCR]TEXT
23 | * - [DEF]PUSHBUTTON
24 | * - CONTROL(check, 3state, radio)
25 | * - RADIOBUTTON
26 | *
27 | * @author Teodor MICU
28 | */
29 | struct TextEntity
30 | {
31 | operator TextSize() const;
32 | void ReplaceAll(const std::wstring & aToken, const std::wstring & aReplace);
33 |
34 | enum TypeCode
35 | {
36 | TEXT = 0, // LTEXT, CTEXT, RTEXT
37 | PUSHBUTTON, // PUSHBUTTON, DEFPUSHBUTTON
38 | CONTROLBUTTON, // CONTROL: checkbox, 3state, radiobutton
39 | RADIOBUTTON, // RADIOBUTTON
40 | OTHER
41 | };
42 |
43 | std::wstring mDlgName; // dialog on which this text block was found
44 | int mLineNr; // line# were this text block was found
45 | std::wstring mText; // text string literal
46 | std::wstring mType; // type string literal
47 | TypeCode mCode; // associated code for mType
48 | bool mMultiLine; // found or implicit multiline flag
49 | RECT mRc; // rectangle coordinates and size (du)
50 | };
51 |
--------------------------------------------------------------------------------
/src/TextMeasurer.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "stdafx.h"
16 | #include "TextMeasurer.h"
17 | #include "TextEntity.h"
18 | #include "TextSize.h"
19 |
20 | using std::wstring;
21 |
22 | TextMeasurer::TextMeasurer()
23 | : mTextEnt(nullptr), mRcWidth(0), mRcHeight(0), mTxtWidth(0), mTxtHeight(0)
24 | {
25 | mDlg.Create(NULL);
26 | }
27 |
28 | TextMeasurer::~TextMeasurer()
29 | {
30 | mDlg.DestroyWindow();
31 | }
32 |
33 | void TextMeasurer::ComputeSize(TextEntity & aTextEnt)
34 | {
35 | mTextEnt = &aTextEnt;
36 |
37 | // we assume text block was already read from file prior to this call
38 | assert(mTextEnt->mText.size() > 0);
39 |
40 | LONG & rcWidthDU = mTextEnt->mRc.right;
41 | LONG & rcHeightDU = mTextEnt->mRc.bottom;
42 | CSize sz;
43 |
44 | // adjust visible text area in rectangle (du)
45 | switch (mTextEnt->mCode)
46 | {
47 | case TextEntity::RADIOBUTTON:
48 | case TextEntity::CONTROLBUTTON:
49 | // compute rectangle width (px)
50 | sz = mDlg.DUtoPX(rcWidthDU, rcHeightDU);
51 | mRcWidth = sz.cx - ::GetSystemMetrics(SM_CXMENUCHECK);
52 | mRcHeight = sz.cy;
53 | break;
54 |
55 | case TextEntity::PUSHBUTTON:
56 | // compute rectangle width (px)
57 | sz = mDlg.DUtoPX(rcWidthDU - PUSHBUTTON_X, rcHeightDU);
58 | mRcWidth = sz.cx;
59 | mRcHeight = sz.cy;
60 | break;
61 |
62 | default: // TEXT
63 | // compute rectangle width (px)
64 | sz = mDlg.DUtoPX(rcWidthDU, rcHeightDU);
65 | mRcWidth = sz.cx;
66 | mRcHeight = sz.cy;
67 | } // end switch
68 |
69 | sz = mDlg.GetTextSize(mTextEnt->mText);
70 | mTxtWidth = sz.cx;
71 | mTxtHeight = sz.cy;
72 |
73 | if (!mTextEnt->mMultiLine)
74 | return;
75 |
76 | // simple case: no escape sequence for new line
77 | if ( wstring::npos == mTextEnt->mText.find(L"\\n") )
78 | // rectangle height has space for just one line of text
79 | if ( (mTxtWidth <= mRcWidth) || (mRcHeight <= mTxtHeight) )
80 | return;
81 |
82 | // detect text height for empty lines found in some escape seq "\n\n"
83 | LONG baseUnitY = mDlg.GetTextHeight();
84 |
85 | mTxtWidth = mTxtHeight = 0;
86 | wstring wline; // substring wrapped on one line
87 | wstring::size_type offset = 0;
88 | wstring::size_type lastpos; // last known good position
89 | wstring::size_type nextpos = 0; // next position to try out
90 | wstring::size_type nextnl; // next new line sequence \n
91 | bool foundnl = false;
92 |
93 | // wrap text in multiple lines less or equal to mRcWidth
94 | do
95 | {
96 | lastpos = nextpos; // last word is included in current line
97 | nextpos = mTextEnt->mText.find(L" ", lastpos);
98 | if (wstring::npos == nextpos) // remaining text has no spaces
99 | nextpos = mTextEnt->mText.size();
100 | else
101 | ++nextpos; // +1 to include the current white space
102 |
103 | // \n escape sequence forces END of line
104 | nextnl = mTextEnt->mText.find(L"\\n", lastpos);
105 | if (nextnl < nextpos)
106 | {
107 | foundnl = true;
108 | nextpos = nextnl;
109 | }
110 |
111 | // compute width of current line
112 | wline = mTextEnt->mText.substr(offset, nextpos-offset);
113 | sz = mDlg.GetTextSize(wline);
114 |
115 | if (sz.cx <= mRcWidth) // current substring is not full
116 | {
117 | if (!foundnl)
118 | continue;
119 | }
120 | // one word is NOT too big to fit on one line?
121 | else if (offset < lastpos)
122 | {
123 | if ( !foundnl &&
124 | (mTextEnt->mText.size() != nextpos) ) // not end of text
125 | {
126 | assert( iswspace(wline[wline.size()-1]) );
127 |
128 | // remove trailing white space from current line
129 | wline.pop_back();
130 | sz = mDlg.GetTextSize(wline);
131 | }
132 |
133 | if (sz.cx > mRcWidth) // doesn't fit w/ last space
134 | {
135 | // current substring is too big, get back to last position
136 | nextpos = lastpos;
137 | foundnl = false;
138 |
139 | // recompute width of current line
140 | wline = mTextEnt->mText.substr(offset, nextpos-offset);
141 | sz = mDlg.GetTextSize(wline);
142 | }
143 | }
144 |
145 | if (mTxtWidth < sz.cx) // adjust maximum (line of) text width
146 | mTxtWidth = sz.cx;
147 |
148 | if (offset == nextpos) // adjust text height (px)
149 | mTxtHeight += baseUnitY; // empty line -> no text to measure
150 | else
151 | mTxtHeight += sz.cy; // non-empty text
152 |
153 | if (foundnl)
154 | {
155 | foundnl = false;
156 | nextpos += 2; // advance over "\n"
157 | }
158 |
159 | // start of a new line
160 | offset = nextpos;
161 | } while (nextpos < mTextEnt->mText.size());
162 |
163 | if (mTextEnt->mText.size() == offset) // last word was processed
164 | return;
165 |
166 | // last word was NOT processed
167 | wline = mTextEnt->mText.substr(offset);
168 | sz = mDlg.GetTextSize(wline);
169 |
170 | if (mTxtWidth < sz.cx) // adjust maximum (line of) text width
171 | mTxtWidth = sz.cx;
172 | mTxtHeight += sz.cy; // adjust text height (px)
173 | assert(mTxtWidth <= mRcWidth);
174 | }
175 |
176 | bool TextMeasurer::IsResizeNeeded() const
177 | {
178 | return (mTxtWidth > mRcWidth) || (mTxtHeight > mRcHeight);
179 | }
180 |
181 | TextSize TextMeasurer::GetRealSize() const
182 | {
183 | assert(nullptr != mTextEnt);
184 |
185 | TextSize szText = *mTextEnt;
186 | szText.mRcWidthPX = mRcWidth;
187 | szText.mRcHeightPX = mRcHeight;
188 | szText.mTxtWidthPX = mTxtWidth;
189 | szText.mTxtHeightPX = mTxtHeight;
190 |
191 | // convert pixels to dialog units
192 | CSize sz = mDlg.PXtoDU(mTxtWidth, mTxtHeight);
193 | szText.mTxtWidthDU = sz.cx;
194 | szText.mTxtHeightDU = sz.cy;
195 |
196 | // adjust text width on round-off error
197 | sz = mDlg.DUtoPX(szText.mTxtWidthDU, szText.mTxtHeightDU);
198 | if (szText.mTxtWidthPX > sz.cx) // usually only 1px loss
199 | ++szText.mTxtWidthDU;
200 | #if _DEBUG
201 | sz = mDlg.DUtoPX(szText.mTxtWidthDU, szText.mTxtHeightDU);
202 | assert(szText.mTxtWidthPX <= sz.cx);
203 | #endif
204 |
205 | // adjust computed text area to rectangle area
206 | switch (mTextEnt->mCode)
207 | {
208 | case TextEntity::RADIOBUTTON:
209 | case TextEntity::CONTROLBUTTON:
210 | szText.mTxtWidthDU += CONTROLBUTTON_X;
211 |
212 | // recommended size, but not required
213 | if (szText.mTxtHeightDU + CONTROLBUTTON_Y <= szText.mRcHeightDU)
214 | szText.mTxtHeightDU += CONTROLBUTTON_Y;
215 | break;
216 |
217 | case TextEntity::PUSHBUTTON:
218 | szText.mTxtWidthDU += PUSHBUTTON_X;
219 |
220 | // recommended size, but not required
221 | if (szText.mTxtHeightDU + PUSHBUTTON_Y <= szText.mRcHeightDU)
222 | szText.mTxtHeightDU += PUSHBUTTON_Y;
223 | break;
224 | } // end switch
225 |
226 | return szText;
227 | }
228 |
--------------------------------------------------------------------------------
/src/TextMeasurer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | #include "TextDlg.h"
18 |
19 | // Layout Specifications: Win32
20 | // http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818.aspx
21 | #define CONTROLBUTTON_X 12
22 | #define CONTROLBUTTON_Y (10 - 8)
23 | #define PUSHBUTTON_X (12 - 8)
24 | #define PUSHBUTTON_Y (14 - 8)
25 |
26 | struct TextEntity;
27 | struct TextSize;
28 |
29 | /**
30 | * Measures the (minimum) required size of a TextEntity.
31 | *
32 | * @author Teodor MICU
33 | */
34 | class TextMeasurer
35 | {
36 | public:
37 | /**
38 | * Class constructor.
39 | */
40 | TextMeasurer();
41 |
42 | /**
43 | * Class destructor.
44 | */
45 | ~TextMeasurer();
46 |
47 | /**
48 | * Detect the required rectangle width (X) and height (Y) so
49 | * that the given text string would fit after word wrap.
50 | *
51 | * If rectangle height (px) is equal to text height (px), the text is
52 | * measured for one line fit.
53 | * If the rectangle height is greater than the text height, the text
54 | * will be wrapped in lines less or equal to the rectangle width (px).
55 | */
56 | void ComputeSize(TextEntity & /*aTextEnt*/);
57 |
58 | /**
59 | * Check if rectangle area is big enough to fit the text.
60 | *
61 | * @return true is text doesn't fit in rectangle area, false otherwise
62 | */
63 | bool IsResizeNeeded() const;
64 |
65 | /**
66 | * @return current and computed size of a text in du&px
67 | */
68 | TextSize GetRealSize() const;
69 |
70 | private:
71 | TextDlg mDlg; // dialog were the size is computed
72 | TextEntity * mTextEnt; // text block to measure
73 | LONG mRcWidth; // computed rectangle width (px)
74 | LONG mRcHeight; // computed rectangle height (px)
75 | LONG mTxtWidth; // computed text width (px)
76 | LONG mTxtHeight; // computed text height (px)
77 | };
78 |
--------------------------------------------------------------------------------
/src/TextReporter.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "stdafx.h"
16 | #include "TextReporter.h"
17 | #include "TextSize.h"
18 |
19 | using std::endl;
20 |
21 | TextReporter::TextReporter(std::wostream & aOStream, UINT aCodepage)
22 | : mOStream(aOStream)
23 | {
24 | if (CODEPAGE_ENGLISH != aCodepage) // custom ANSI encoding
25 | {
26 | char cpstr[20];
27 | cpstr[0] = '.'; // ".1252"
28 | sprintf_s(cpstr+1, 20-2, "%d", aCodepage);
29 |
30 | aOStream.imbue( std::locale(cpstr) );
31 | ::SetConsoleOutputCP(aCodepage);
32 | }
33 | }
34 |
35 | TextReporter & TextReporter::operator<<(const TextSize & aSzText)
36 | {
37 | // we assume TextSize structure was already initialized
38 | assert(aSzText.mText.size() > 0);
39 |
40 | // write new header on dialog change
41 | if (mOldDlgName != aSzText.mDlgName)
42 | {
43 | mOStream << L"Dialog ID: " << aSzText.mDlgName << endl
44 | << L"-------------------------------" << endl;
45 | mOldDlgName = aSzText.mDlgName;
46 | }
47 |
48 | // write text and required size
49 | mOStream
50 | << aSzText.mLineNr << L": " << aSzText.mType
51 | << L" \"" << aSzText.mText << L'"' << endl
52 | << L"- detected text size: (" << aSzText.mTxtWidthPX << L","
53 | << aSzText.mTxtHeightPX << L")px" << endl
54 | << L"- detected rect size: (" << aSzText.mRcWidthDU << L","
55 | << aSzText.mRcHeightDU << L")du -> ("
56 | << aSzText.mRcWidthPX << L","
57 | << aSzText.mRcHeightPX << L")px" << endl
58 | << L"+ minimum required rectangle size: ("
59 | << aSzText.mTxtWidthDU << L","
60 | << aSzText.mTxtHeightDU << L")du";
61 |
62 | if ( aSzText.mMultiLine && (aSzText.mTxtHeightDU > 8) )
63 | mOStream << L" [MULTILINE]";
64 |
65 | mOStream << endl << endl;
66 | return *this;
67 | }
68 |
--------------------------------------------------------------------------------
/src/TextReporter.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | struct TextSize;
18 |
19 | /**
20 | * Print the current and required size of a text block.
21 | *
22 | * @author Teodor MICU
23 | */
24 | class TextReporter
25 | {
26 | public:
27 | /**
28 | * Class constructor.
29 | */
30 | TextReporter(std::wostream & /*aOStream*/, UINT aCodepage = CODEPAGE_ENGLISH);
31 |
32 | /**
33 | * Print the text block measurements.
34 | */
35 | TextReporter & operator<<(const TextSize & /*aSzText*/);
36 |
37 | private:
38 | std::wostream & mOStream; // output stream
39 | std::wstring mOldDlgName; // parent of this text block
40 | };
41 |
--------------------------------------------------------------------------------
/src/TextSize.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Caphyon Ltd.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http ://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #pragma once
16 |
17 | /**
18 | * Current and computed size of a TextEntity.
19 | *
20 | * @author Teodor MICU
21 | */
22 | struct TextSize
23 | {
24 | std::wstring mDlgName; // dialog on which this text block was found
25 | int mLineNr; // line# were this text block was found
26 | std::wstring mText; // text string literal
27 | std::wstring mType; // type string literal
28 | bool mMultiLine; // found or implicit multiline flag
29 |
30 | LONG mRcWidthDU; // rectangle width (du) -- read from resource
31 | LONG mRcWidthPX; // computed rectangle width (px)
32 | LONG mRcHeightDU; // rectangle height (du) -- read from resource
33 | LONG mRcHeightPX; // computed rectangle height (px)
34 |
35 | LONG mTxtWidthDU; // computed text width (du)
36 | LONG mTxtWidthPX; // computed text width (px)
37 | LONG mTxtHeightDU; // computed text height (du)
38 | LONG mTxtHeightPX; // computed text height (px)
39 | };
40 |
--------------------------------------------------------------------------------
/src/ckrctxt.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include "afxres.h"
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // English (United States) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
20 | #pragma code_page(1252)
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""afxres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Dialog
51 | //
52 |
53 | IDD_MEASURE_DIALOG DIALOGEX 0, 0, 316, 182
54 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
55 | CAPTION "Dialog"
56 | FONT 8, "MS Shell Dlg", 400, 0, 0x1
57 | BEGIN
58 | DEFPUSHBUTTON "OK",IDOK,204,161,50,14
59 | PUSHBUTTON "Cancel",IDCANCEL,259,161,50,14
60 | LTEXT "Product Name:",IDC_STATIC,25,23,50,8
61 | LTEXT "Product Version:",IDC_STATIC,25,42,55,8
62 | LTEXT "Technical Support URL:",IDC_STATIC,25,62,78,8
63 | LTEXT "After translation you can add the created dictionary to the project's translation dictionaries list or import it into the application.",IDC_STATIC2,24,91,219,16
64 | PUSHBUTTON "&Add Folder...",IDC_BUTTON1,165,39,47,14,BS_MULTILINE
65 | CONTROL "|",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,167,66,19,10
66 | CONTROL "Automate package installation by invoking UI controls in order to walk-through the installation steps. Leave it unchecked if the installer requires special user input.\nBy using this option, you agree to the installer License terms.",IDC_CHECK1,
67 | "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,25,120,278,26
68 | RADIOBUTTON "Use file from disk",IDC_RADIO2,222,66,69,10
69 | END
70 |
71 |
72 | /////////////////////////////////////////////////////////////////////////////
73 | //
74 | // DESIGNINFO
75 | //
76 |
77 | #ifdef APSTUDIO_INVOKED
78 | GUIDELINES DESIGNINFO
79 | BEGIN
80 | IDD_MEASURE_DIALOG, DIALOG
81 | BEGIN
82 | LEFTMARGIN, 7
83 | RIGHTMARGIN, 309
84 | TOPMARGIN, 7
85 | BOTTOMMARGIN, 175
86 | HORZGUIDE, 120
87 | END
88 | END
89 | #endif // APSTUDIO_INVOKED
90 |
91 |
92 | /////////////////////////////////////////////////////////////////////////////
93 | //
94 | // Version
95 | //
96 |
97 | VS_VERSION_INFO VERSIONINFO
98 | FILEVERSION 1,0,0,0
99 | PRODUCTVERSION 1,0,0,0
100 | FILEFLAGSMASK 0x3fL
101 | #ifdef _DEBUG
102 | FILEFLAGS 0x1L
103 | #else
104 | FILEFLAGS 0x0L
105 | #endif
106 | FILEOS 0x40004L
107 | FILETYPE 0x0L
108 | FILESUBTYPE 0x0L
109 | BEGIN
110 | BLOCK "StringFileInfo"
111 | BEGIN
112 | BLOCK "040904b0"
113 | BEGIN
114 | VALUE "FileDescription", "Visual Studio RC Text Bounds Checker"
115 | VALUE "FileVersion", "1.0.0.0"
116 | VALUE "InternalName", "ckrctxt.rc"
117 | VALUE "LegalCopyright", "(c) 2016"
118 | VALUE "OriginalFilename", "ckrctxt.exe"
119 | VALUE "ProductName", "Check RC Text"
120 | VALUE "ProductVersion", "1.0.0.0"
121 | END
122 | END
123 | BLOCK "VarFileInfo"
124 | BEGIN
125 | VALUE "Translation", 0x409, 1200
126 | END
127 | END
128 |
129 | #endif // English (United States) resources
130 | /////////////////////////////////////////////////////////////////////////////
131 |
132 |
133 |
134 | #ifndef APSTUDIO_INVOKED
135 | /////////////////////////////////////////////////////////////////////////////
136 | //
137 | // Generated from the TEXTINCLUDE 3 resource.
138 | //
139 |
140 |
141 | /////////////////////////////////////////////////////////////////////////////
142 | #endif // not APSTUDIO_INVOKED
143 |
144 |
--------------------------------------------------------------------------------
/src/compatibility.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/dpi_aware.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by ckrctxt.rc
4 | //
5 | #define IDD_MEASURE_DIALOG 101
6 | #define IDC_STATIC2 200
7 | #define IDC_BUTTON1 1001
8 | #define IDC_COMMAND1 1002
9 | #define IDC_RADIO1 1003
10 | #define IDC_CHECK1 1004
11 | #define IDC_RADIO2 1005
12 |
13 | // Next default values for new objects
14 | //
15 | #ifdef APSTUDIO_INVOKED
16 | #ifndef APSTUDIO_READONLY_SYMBOLS
17 | #define _APS_NEXT_RESOURCE_VALUE 102
18 | #define _APS_NEXT_COMMAND_VALUE 40001
19 | #define _APS_NEXT_CONTROL_VALUE 1006
20 | #define _APS_NEXT_SYMED_VALUE 101
21 | #endif
22 | #endif
23 |
--------------------------------------------------------------------------------
/src/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // ckrctxt.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/src/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #define CODEPAGE_ENGLISH 1252
9 |
10 | #include "targetver.h"
11 |
12 | #include
13 | #include
14 |
15 | // Windows Template Library (WTL) - extends ATL
16 | // http://sourceforge.net/projects/wtl/
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #if defined _M_IX86
26 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
27 | #elif defined _M_IA64
28 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
29 | #elif defined _M_X64
30 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
31 | #else
32 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
33 | #endif
34 |
--------------------------------------------------------------------------------
/src/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------