├── .gitattributes ├── .gitignore ├── CREDITS.md ├── Common.props ├── LICENSE ├── README.md ├── UniteWindow.sln └── UniteWindow ├── ConfigDialog.cpp ├── ConfigDialog.h ├── UniteWindow.cpp ├── UniteWindow.def ├── UniteWindow.h ├── UniteWindow.rc ├── UniteWindow.vcxproj ├── UniteWindow.vcxproj.filters ├── UniteWindow_Config_Load.cpp ├── UniteWindow_Config_Save.cpp ├── UniteWindow_Window.cpp ├── UniteWindow_Window_AviUtlWindow.cpp ├── UniteWindow_Window_ExeditWindow.cpp ├── UniteWindow_Window_SettingDialog.cpp ├── pch.cpp ├── pch.h └── resource.h /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | _bin/ 36 | _obj/ 37 | 38 | # Visual Studio 2015/2017 cache/options directory 39 | .vs/ 40 | # Uncomment if you have tasks that create the project's static files in wwwroot 41 | #wwwroot/ 42 | 43 | # Visual Studio 2017 auto generated files 44 | Generated\ Files/ 45 | 46 | # MSTest test Results 47 | [Tt]est[Rr]esult*/ 48 | [Bb]uild[Ll]og.* 49 | 50 | # NUnit 51 | *.VisualState.xml 52 | TestResult.xml 53 | nunit-*.xml 54 | 55 | # Build Results of an ATL Project 56 | [Dd]ebugPS/ 57 | [Rr]eleasePS/ 58 | dlldata.c 59 | 60 | # Benchmark Results 61 | BenchmarkDotNet.Artifacts/ 62 | 63 | # .NET Core 64 | project.lock.json 65 | project.fragment.lock.json 66 | artifacts/ 67 | 68 | # ASP.NET Scaffolding 69 | ScaffoldingReadMe.txt 70 | 71 | # StyleCop 72 | StyleCopReport.xml 73 | 74 | # Files built by Visual Studio 75 | *_i.c 76 | *_p.c 77 | *_h.h 78 | *.ilk 79 | *.meta 80 | *.obj 81 | *.iobj 82 | *.pch 83 | *.pdb 84 | *.ipdb 85 | *.pgc 86 | *.pgd 87 | *.rsp 88 | *.sbr 89 | *.tlb 90 | *.tli 91 | *.tlh 92 | *.tmp 93 | *.tmp_proj 94 | *_wpftmp.csproj 95 | *.log 96 | *.vspscc 97 | *.vssscc 98 | .builds 99 | *.pidb 100 | *.svclog 101 | *.scc 102 | 103 | # Chutzpah Test files 104 | _Chutzpah* 105 | 106 | # Visual C++ cache files 107 | ipch/ 108 | *.aps 109 | *.ncb 110 | *.opendb 111 | *.opensdf 112 | *.sdf 113 | *.cachefile 114 | *.VC.db 115 | *.VC.VC.opendb 116 | 117 | # Visual Studio profiler 118 | *.psess 119 | *.vsp 120 | *.vspx 121 | *.sap 122 | 123 | # Visual Studio Trace Files 124 | *.e2e 125 | 126 | # TFS 2012 Local Workspace 127 | $tf/ 128 | 129 | # Guidance Automation Toolkit 130 | *.gpState 131 | 132 | # ReSharper is a .NET coding add-in 133 | _ReSharper*/ 134 | *.[Rr]e[Ss]harper 135 | *.DotSettings.user 136 | 137 | # TeamCity is a build add-in 138 | _TeamCity* 139 | 140 | # DotCover is a Code Coverage Tool 141 | *.dotCover 142 | 143 | # AxoCover is a Code Coverage Tool 144 | .axoCover/* 145 | !.axoCover/settings.json 146 | 147 | # Coverlet is a free, cross platform Code Coverage Tool 148 | coverage*.json 149 | coverage*.xml 150 | coverage*.info 151 | 152 | # Visual Studio code coverage results 153 | *.coverage 154 | *.coveragexml 155 | 156 | # NCrunch 157 | _NCrunch_* 158 | .*crunch*.local.xml 159 | nCrunchTemp_* 160 | 161 | # MightyMoose 162 | *.mm.* 163 | AutoTest.Net/ 164 | 165 | # Web workbench (sass) 166 | .sass-cache/ 167 | 168 | # Installshield output folder 169 | [Ee]xpress/ 170 | 171 | # DocProject is a documentation generator add-in 172 | DocProject/buildhelp/ 173 | DocProject/Help/*.HxT 174 | DocProject/Help/*.HxC 175 | DocProject/Help/*.hhc 176 | DocProject/Help/*.hhk 177 | DocProject/Help/*.hhp 178 | DocProject/Help/Html2 179 | DocProject/Help/html 180 | 181 | # Click-Once directory 182 | publish/ 183 | 184 | # Publish Web Output 185 | *.[Pp]ublish.xml 186 | *.azurePubxml 187 | # Note: Comment the next line if you want to checkin your web deploy settings, 188 | # but database connection strings (with potential passwords) will be unencrypted 189 | *.pubxml 190 | *.publishproj 191 | 192 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 193 | # checkin your Azure Web App publish settings, but sensitive information contained 194 | # in these scripts will be unencrypted 195 | PublishScripts/ 196 | 197 | # NuGet Packages 198 | *.nupkg 199 | # NuGet Symbol Packages 200 | *.snupkg 201 | # The packages folder can be ignored because of Package Restore 202 | **/[Pp]ackages/* 203 | # except build/, which is used as an MSBuild target. 204 | !**/[Pp]ackages/build/ 205 | # Uncomment if necessary however generally it will be regenerated when needed 206 | #!**/[Pp]ackages/repositories.config 207 | # NuGet v3's project.json files produces more ignorable files 208 | *.nuget.props 209 | *.nuget.targets 210 | 211 | # Microsoft Azure Build Output 212 | csx/ 213 | *.build.csdef 214 | 215 | # Microsoft Azure Emulator 216 | ecf/ 217 | rcf/ 218 | 219 | # Windows Store app package directories and files 220 | AppPackages/ 221 | BundleArtifacts/ 222 | Package.StoreAssociation.xml 223 | _pkginfo.txt 224 | *.appx 225 | *.appxbundle 226 | *.appxupload 227 | 228 | # Visual Studio cache files 229 | # files ending in .cache can be ignored 230 | *.[Cc]ache 231 | # but keep track of directories ending in .cache 232 | !?*.[Cc]ache/ 233 | 234 | # Others 235 | ClientBin/ 236 | ~$* 237 | *~ 238 | *.dbmdl 239 | *.dbproj.schemaview 240 | *.jfm 241 | *.pfx 242 | *.publishsettings 243 | orleans.codegen.cs 244 | 245 | # Including strong name files can present a security risk 246 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 247 | #*.snk 248 | 249 | # Since there are multiple workflows, uncomment next line to ignore bower_components 250 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 251 | #bower_components/ 252 | 253 | # RIA/Silverlight projects 254 | Generated_Code/ 255 | 256 | # Backup & report files from converting an old project file 257 | # to a newer Visual Studio version. Backup files are not needed, 258 | # because we have git ;-) 259 | _UpgradeReport_Files/ 260 | Backup*/ 261 | UpgradeLog*.XML 262 | UpgradeLog*.htm 263 | ServiceFabricBackup/ 264 | *.rptproj.bak 265 | 266 | # SQL Server files 267 | *.mdf 268 | *.ldf 269 | *.ndf 270 | 271 | # Business Intelligence projects 272 | *.rdl.data 273 | *.bim.layout 274 | *.bim_*.settings 275 | *.rptproj.rsuser 276 | *- [Bb]ackup.rdl 277 | *- [Bb]ackup ([0-9]).rdl 278 | *- [Bb]ackup ([0-9][0-9]).rdl 279 | 280 | # Microsoft Fakes 281 | FakesAssemblies/ 282 | 283 | # GhostDoc plugin setting file 284 | *.GhostDoc.xml 285 | 286 | # Node.js Tools for Visual Studio 287 | .ntvs_analysis.dat 288 | node_modules/ 289 | 290 | # Visual Studio 6 build log 291 | *.plg 292 | 293 | # Visual Studio 6 workspace options file 294 | *.opt 295 | 296 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 297 | *.vbw 298 | 299 | # Visual Studio LightSwitch build output 300 | **/*.HTMLClient/GeneratedArtifacts 301 | **/*.DesktopClient/GeneratedArtifacts 302 | **/*.DesktopClient/ModelManifest.xml 303 | **/*.Server/GeneratedArtifacts 304 | **/*.Server/ModelManifest.xml 305 | _Pvt_Extensions 306 | 307 | # Paket dependency manager 308 | .paket/paket.exe 309 | paket-files/ 310 | 311 | # FAKE - F# Make 312 | .fake/ 313 | 314 | # CodeRush personal settings 315 | .cr/personal 316 | 317 | # Python Tools for Visual Studio (PTVS) 318 | __pycache__/ 319 | *.pyc 320 | 321 | # Cake - Uncomment if you are using it 322 | # tools/** 323 | # !tools/packages.config 324 | 325 | # Tabs Studio 326 | *.tss 327 | 328 | # Telerik's JustMock configuration file 329 | *.jmconfig 330 | 331 | # BizTalk build output 332 | *.btp.cs 333 | *.btm.cs 334 | *.odx.cs 335 | *.xsd.cs 336 | 337 | # OpenCover UI analysis results 338 | OpenCover/ 339 | 340 | # Azure Stream Analytics local run output 341 | ASALocalRun/ 342 | 343 | # MSBuild Binary and Structured Log 344 | *.binlog 345 | 346 | # NVidia Nsight GPU debugger configuration file 347 | *.nvuser 348 | 349 | # MFractors (Xamarin productivity tool) working folder 350 | .mfractor/ 351 | 352 | # Local History for Visual Studio 353 | .localhistory/ 354 | 355 | # BeatPulse healthcheck temp database 356 | healthchecksdb 357 | 358 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 359 | MigrationBackup/ 360 | 361 | # Ionide (cross platform F# VS Code tools) working folder 362 | .ionide/ 363 | 364 | # Fody - auto-generated XML schema 365 | FodyWeavers.xsd -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hebiiro/AviUtl-Plugin-UniteWindow/db5ad9837eb88479afbea34fc84eb3bafd73d607/CREDITS.md -------------------------------------------------------------------------------- /Common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(SolutionDir)_bin\ 7 | $(SolutionDir)_obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ 8 | 9 | 10 | 11 | $(IntDir) 12 | 13 | 14 | 15 | 16 | $(IntDir) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 hebiiro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AviUtl プラグイン - UniteWindow 2 | 3 | AviUtl のウィンドウを結合してシングルウィンドウにまとめます。 4 | [最新バージョンをダウンロード](../../releases/latest/) 5 | 6 | ![UniteWindow 1 0 0](https://user-images.githubusercontent.com/96464759/166472528-057c3fff-f724-40d2-9692-8a647e966f80.jpg) 7 | 8 | ## 導入方法 9 | 10 | 1. 以下のファイルを AviUtl の Plugins フォルダに配置します。 11 | * UniteWindow.aul 12 | * UniteWindow.xml 13 | * UniteWindow (フォルダ) 14 | 15 | ## 使用方法 16 | 17 | ボーダーをドラッグしてペインのサイズを調整します。Shift キーを押したままドラッグするとボーダーが十字になるように調整されます。 18 | 19 | ## 設定方法 20 | 21 | タイトルバーを右クリックしてシステムメニューを表示します。 22 | 23 | ### レイアウトのインポート 24 | 25 | レイアウトファイルを選択してインポートします。 26 | 27 | ### レイアウトのエクスポート 28 | 29 | レイアウトファイルを選択してエクスポートします。 30 | 31 | ### UniteWindowの設定 32 | 33 | UniteWindowの設定ダイアログを開きます。 34 | 35 | * ```レイアウトモード``` 36 | * ```垂直分割``` 最初に垂直ボーダーで分割するモードです。水平ボーダーは個別に位置調整ができます。 37 | * ```水平分割``` 最初に水平ボーダーで分割するモードです。垂直ボーダーは個別に位置調整ができます。 38 | 39 | * ```ウィンドウの配置``` 40 | * ```左上``` 41 | * ```右上``` 42 | * ```左下``` 43 | * ```右下``` 44 | * それぞれに ```AviUtlウィンドウ```、```拡張編集ウィンドウ```、```設定ダイアログ```、```ウィンドウなし``` を指定できます。同じウィンドウを重複して指定することはできません。 45 | 46 | * ```ボーダー位置 (垂直分割)``` 垂直分割モードのボーダーの位置を指定します。 47 | * ```中央``` 中央にある垂直ボーダーの X 座標を指定します。 48 | * ```左``` 左側にある水平ボーダーの Y 座標を指定します。 49 | * ```右``` 右側にある水平ボーダーの Y 座標を指定します。 50 | 51 | * ```ボーダー位置 (水平分割)``` 水平分割モードのボーダーの位置を指定します。 52 | * ```中央``` 中央にある水平ボーダーの Y 座標を指定します。 53 | * ```上``` 上側にある垂直ボーダーの X 座標を指定します。 54 | * ```下``` 下側にある垂直ボーダーの X 座標を指定します。 55 | * エディットボックスの下にあるコンボボックスで基点を指定します。例えばボーダーを右端で固定したい場合は基点を「右下」に設定します。 56 | 57 | * ```配色``` 背景色とボーダーの配色を指定します。 58 | * ```塗り潰し``` 背景色を指定します。 59 | * ```ボーダー``` ボーダーの色を指定します。 60 | * ```ホットボーダー``` ホットボーダーの色を指定します。 61 | 62 | * ```アクティブキャプションの配色``` アクティブキャプションの配色を指定します。 63 | * ```背景``` 背景色を指定します。 64 | * ```テキスト``` テキストの色を指定します。 65 | 66 | * ```非アクティブキャプションの配色``` 非アクティブキャプションの配色を指定します。 67 | * ```背景``` 背景色を指定します。 68 | * ```テキスト``` テキストの色を指定します。 69 | 70 | * ```配色ではなくテーマを使用する``` 71 | チェックを入れるとテーマを使用してボーダーとキャプションを描画するようになります。この場合「UniteWindow」の配色は無視されます。その代わりに「黒窓」のテーマカスタマイズ機能が反映されます。 72 | 73 | ### 設定ファイル 74 | 75 | UniteWindow.xml をテキストエディタで開いて編集します。 76 | 77 | * `````` 78 | * ```borderWidth``` ボーダーの幅を指定します。 79 | * ```captionHeight``` キャプションの高さを指定します。 80 | * ```borderSnapRange``` ボーダーのスナップ範囲を指定します。 81 | * ```fillColor``` 背景の塗りつぶし色を指定します。 82 | * ```borderColor``` ボーダーの色を指定します。 83 | * ```hotBorderColor``` ホット状態のボーダーの色を指定します。 84 | * ```activeCaptionColor``` アクティブキャプションの背景色を指定します。 85 | * ```activeCaptionTextColor``` アクティブキャプションのテキストの色を指定します。 86 | * ```inactiveCaptionColor``` 非アクティブキャプションの背景色を指定します。 87 | * ```inactiveCaptionTextColor``` 非アクティブキャプションのテキストの色を指定します。 88 | * ```useTheme``` ```YES``` を指定するとボーダーとキャプションの描画にテーマを使用するようになります。 89 | * `````` シングルウィンドウの位置を指定します。ウィンドウ位置がおかしくなった場合はこのタグを削除してください。 90 | * `````` レイアウトを指定します。レイアウトがおかしくなった場合はこのタグを削除してください。 91 | * ```layoutMode``` ```vertSplit```、```horzSplit``` のいずれかを指定します。 92 | * `````` 93 | * ```pos``` ```topLeft```、```topRight```、```bottomLeft```、```bottomRight``` のいずれかを指定します。 94 | * ```id``` ```aviutlWindow```、```exeditWindow```、```settingDialog```、空文字のいずれかを指定します。 95 | * `````` ```layoutMode``` が ```vertSplit``` のときのボーダーの位置を指定します。 96 | * ```center``` 中央にある垂直ボーダーの X 座標を指定します。 97 | * ```left``` 左側にある水平ボーダーの Y 座標を指定します。 98 | * ```right``` 右側にある水平ボーダーの Y 座標を指定します。 99 | * ```centerOrigin``` 中央にある垂直ボーダーの基点を指定します。 100 | * ```leftOrigin``` 左側にある水平ボーダーの基点を指定します。 101 | * ```rightOrigin``` 右側にある水平ボーダーの基点を指定します。 102 | * `````` ```layoutMode``` が ```horzSplit``` のときのボーダーの位置を指定します。 103 | * ```center``` 中央にある水平ボーダーの Y 座標を指定します。 104 | * ```top``` 上側にある垂直ボーダーの X 座標を指定します。 105 | * ```bottom``` 下側にある垂直ボーダーの X 座標を指定します。 106 | * ```centerOrigin``` 中央にある水平ボーダーの基点を指定します。 107 | * ```topOrigin``` 上側にある垂直ボーダーの基点を指定します。 108 | * ```bottomOrigin``` 下側にある垂直ボーダーの基点を指定します。 109 | 110 | ## 更新履歴 111 | 112 | * 3.5.0 - 2022/06/22 キャプションとボーダーの描画方式を選択できるように変更 113 | * 3.4.0 - 2022/06/09 設定ダイアログのホイール操作の既定動作抑制 114 | * 3.3.1 - 2022/06/06 「rikky_module」が正常に動作しない問題を修正 115 | * 3.3.0 - 2022/06/03 コンフィグダイアログでの配色の変更に対応 116 | * 3.2.0 - 2022/06/03 設定ダイアログの高さをコンテナの高さまで広げるように変更 117 | * 3.1.0 - 2022/06/03 タイトルの描画方式を変更 118 | * 3.0.6 - 2022/06/02 スポイトが正しく動作しない問題を修正 119 | * 3.0.5 - 2022/05/22 ポップアップウィンドウを最小化できない問題を修正 120 | * 3.0.4 - 2022/05/19 「スクリプト並べ替え管理」「シークバー+」が動作しない問題を修正 121 | * 3.0.3 - 2022/05/13 メニューが再描画されない問題を修正 122 | * 3.0.2 - 2022/05/13 設定ダイアログでエンターキーが効かない問題を修正 123 | * 3.0.1 - 2022/05/11 タイトルの色が読み込まれない問題を修正 124 | * 3.0.0 - 2022/05/08 子ウィンドウにフォーカスが当たっていない問題を修正 125 | * 2.0.0 - 2022/05/08 各ウィンドウを子ウィンドウに変更 126 | * 1.1.6 - 2022/05/07 ボーダーに基点を追加 127 | * 1.1.5 - 2022/05/06 シングルウィンドウのクラス名を "AviUtl" に変更 128 | * 1.1.4 - 2022/05/06 ボーダーのスナップ機能を追加 129 | * 1.1.3 - 2022/05/06 スポイトが動作しない問題を修正 130 | * 1.1.2 - 2022/05/06 各ウィンドウが操作不能になる問題を修正 131 | * 1.1.1 - 2022/05/05 ウィンドウをクリックしても最前面にならなかった問題を修正 132 | * 1.1.0 - 2022/05/05 Shift キードラッグでボーダーを十字にできるように修正 133 | * 1.0.7 - 2022/05/04 パフォーマンスの低下を改善 134 | * 1.0.6 - 2022/05/04 「拡張編集RAMプレビュー」が動作しない問題に対応 135 | * 1.0.5 - 2022/05/04 「イージング設定時短プラグイン」が動作しない問題に対応 136 | * 1.0.4 - 2022/05/04 スピンボタンで数値を変更できないバグを修正 137 | * 1.0.3 - 2022/05/04 「PSDToolKit」の「送る」に対応 138 | * 1.0.2 - 2022/05/04 マウスホイールでスクロールに対応 139 | * 1.0.1 - 2022/05/04 「テキスト編集補助プラグイン」が動作しない問題に対応 140 | * 1.0.0 - 2022/05/03 初版 141 | 142 | ## 動作確認 143 | 144 | * (必須) AviUtl 1.10 & 拡張編集 0.92 http://spring-fragrance.mints.ne.jp/aviutl/ 145 | * (共存確認) patch.aul r41 https://scrapbox.io/ePi5131/patch.aul 146 | 147 | ## クレジット 148 | 149 | * Microsoft Research Detours Package https://github.com/microsoft/Detours 150 | * aviutl_exedit_sdk https://github.com/ePi5131/aviutl_exedit_sdk 151 | * Common Library https://github.com/hebiiro/Common-Library 152 | 153 | ## 作成者情報 154 | 155 | * 作成者 - 蛇色 (へびいろ) 156 | * GitHub - https://github.com/hebiiro 157 | * Twitter - https://twitter.com/io_hebiiro 158 | 159 | ## 免責事項 160 | 161 | このプラグインおよび同梱物を使用したことによって生じたすべての障害・損害・不具合等に関しては、私と私の関係者および私の所属するいかなる団体・組織とも、一切の責任を負いません。各自の責任においてご使用ください。 162 | -------------------------------------------------------------------------------- /UniteWindow.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31515.178 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UniteWindow", "UniteWindow\UniteWindow.vcxproj", "{772BC0B9-7CA2-4EF5-9439-91D4F823156E}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{77E9C1D4-FC85-44BA-981A-77402A637511}" 9 | ProjectSection(SolutionItems) = preProject 10 | CREDITS.md = CREDITS.md 11 | LICENSE = LICENSE 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|x64 = Release|x64 20 | Release|x86 = Release|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Debug|x64.ActiveCfg = Debug|x64 24 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Debug|x64.Build.0 = Debug|x64 25 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Debug|x86.ActiveCfg = Debug|Win32 26 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Debug|x86.Build.0 = Debug|Win32 27 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Release|x64.ActiveCfg = Release|x64 28 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Release|x64.Build.0 = Release|x64 29 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Release|x86.ActiveCfg = Release|Win32 30 | {772BC0B9-7CA2-4EF5-9439-91D4F823156E}.Release|x86.Build.0 = Release|Win32 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | GlobalSection(ExtensibilityGlobals) = postSolution 36 | SolutionGuid = {04F73712-35B3-45DC-891D-A4ADC727C31E} 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /UniteWindow/ConfigDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ConfigDialog.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | int getComboBoxIndexFromWindow(Window* window) 7 | { 8 | if (window == &g_aviutlWindow) return 0; 9 | else if (window == &g_exeditWindow) return 1; 10 | else if (window == &g_settingDialog) return 2; 11 | 12 | return 3; 13 | } 14 | 15 | Window* getWindowFromComboBoxIndex(int i) 16 | { 17 | switch (i) 18 | { 19 | case 0: return &g_aviutlWindow; 20 | case 1: return &g_exeditWindow; 21 | case 2: return &g_settingDialog; 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | int showConfigDialog(HWND hwnd) 28 | { 29 | ConfigDialog dialog(hwnd); 30 | 31 | HWND hwndLayoutMode = ::GetDlgItem(dialog, IDC_LAYOUT_MODE); 32 | ComboBox_AddString(hwndLayoutMode, _T("垂直分割")); 33 | ComboBox_AddString(hwndLayoutMode, _T("水平分割")); 34 | ComboBox_SetCurSel(hwndLayoutMode, g_layoutMode); 35 | 36 | HWND hwndWindow[WindowPos::maxSize] = {}; 37 | hwndWindow[WindowPos::topLeft] = ::GetDlgItem(dialog, IDC_WINDOW_TOP_LEFT); 38 | hwndWindow[WindowPos::topRight] = ::GetDlgItem(dialog, IDC_WINDOW_TOP_RIGHT); 39 | hwndWindow[WindowPos::bottomLeft] = ::GetDlgItem(dialog, IDC_WINDOW_BOTTOM_LEFT); 40 | hwndWindow[WindowPos::bottomRight] = ::GetDlgItem(dialog, IDC_WINDOW_BOTTOM_RIGHT); 41 | for (int i = 0; i < WindowPos::maxSize; i++) 42 | { 43 | ComboBox_AddString(hwndWindow[i], _T("AviUtlウィンドウ")); 44 | ComboBox_AddString(hwndWindow[i], _T("拡張編集ウィンドウ")); 45 | ComboBox_AddString(hwndWindow[i], _T("設定ダイアログ")); 46 | ComboBox_AddString(hwndWindow[i], _T("ウィンドウなし")); 47 | ComboBox_SetCurSel(hwndWindow[i], getComboBoxIndexFromWindow(g_windowArray[i])); 48 | } 49 | ::SetDlgItemInt(dialog, IDC_BORDER_VERT_CENTER, g_borders.m_vertCenter, TRUE); 50 | ::SetDlgItemInt(dialog, IDC_BORDER_VERT_LEFT, g_borders.m_vertLeft, TRUE); 51 | ::SetDlgItemInt(dialog, IDC_BORDER_VERT_RIGHT, g_borders.m_vertRight, TRUE); 52 | ::SetDlgItemInt(dialog, IDC_BORDER_HORZ_CENTER, g_borders.m_horzCenter, TRUE); 53 | ::SetDlgItemInt(dialog, IDC_BORDER_HORZ_TOP, g_borders.m_horzTop, TRUE); 54 | ::SetDlgItemInt(dialog, IDC_BORDER_HORZ_BOTTOM, g_borders.m_horzBottom, TRUE); 55 | HWND hwndOrigin[6] = {}; 56 | hwndOrigin[0] = ::GetDlgItem(dialog, IDC_BORDER_VERT_CENTER_ORIGIN); 57 | hwndOrigin[1] = ::GetDlgItem(dialog, IDC_BORDER_VERT_LEFT_ORIGIN); 58 | hwndOrigin[2] = ::GetDlgItem(dialog, IDC_BORDER_VERT_RIGHT_ORIGIN); 59 | hwndOrigin[3] = ::GetDlgItem(dialog, IDC_BORDER_HORZ_CENTER_ORIGIN); 60 | hwndOrigin[4] = ::GetDlgItem(dialog, IDC_BORDER_HORZ_TOP_ORIGIN); 61 | hwndOrigin[5] = ::GetDlgItem(dialog, IDC_BORDER_HORZ_BOTTOM_ORIGIN); 62 | for (int i = 0; i < 6; i++) 63 | { 64 | ComboBox_AddString(hwndOrigin[i], _T("左上基点")); 65 | ComboBox_AddString(hwndOrigin[i], _T("右下基点")); 66 | } 67 | ComboBox_SetCurSel(hwndOrigin[0], g_borders.m_vertCenterOrigin); 68 | ComboBox_SetCurSel(hwndOrigin[1], g_borders.m_vertLeftOrigin); 69 | ComboBox_SetCurSel(hwndOrigin[2], g_borders.m_vertRightOrigin); 70 | ComboBox_SetCurSel(hwndOrigin[3], g_borders.m_horzCenterOrigin); 71 | ComboBox_SetCurSel(hwndOrigin[4], g_borders.m_horzTopOrigin); 72 | ComboBox_SetCurSel(hwndOrigin[5], g_borders.m_horzBottomOrigin); 73 | ::SetDlgItemInt(dialog, IDC_FILL_COLOR, g_fillColor, FALSE); 74 | ::SetDlgItemInt(dialog, IDC_BORDER_COLOR, g_borderColor, FALSE); 75 | ::SetDlgItemInt(dialog, IDC_HOT_BORDER_COLOR, g_hotBorderColor, FALSE); 76 | ::SetDlgItemInt(dialog, IDC_ACTIVE_CAPTION_COLOR, g_activeCaptionColor, FALSE); 77 | ::SetDlgItemInt(dialog, IDC_ACTIVE_CAPTION_TEXT_COLOR, g_activeCaptionTextColor, FALSE); 78 | ::SetDlgItemInt(dialog, IDC_INACTIVE_CAPTION_COLOR, g_inactiveCaptionColor, FALSE); 79 | ::SetDlgItemInt(dialog, IDC_INACTIVE_CAPTION_TEXT_COLOR, g_inactiveCaptionTextColor, FALSE); 80 | HWND hwndUseTheme = ::GetDlgItem(dialog, IDC_USE_THEME); 81 | Button_SetCheck(hwndUseTheme, g_useTheme); 82 | 83 | ::EnableWindow(hwnd, FALSE); 84 | int retValue = dialog.doModal(); 85 | ::EnableWindow(hwnd, TRUE); 86 | ::SetActiveWindow(hwnd); 87 | 88 | if (IDOK != retValue) 89 | return retValue; 90 | 91 | g_layoutMode = ComboBox_GetCurSel(hwndLayoutMode); 92 | for (int i = 0; i < WindowPos::maxSize; i++) 93 | g_windowArray[i] = getWindowFromComboBoxIndex(ComboBox_GetCurSel(hwndWindow[i])); 94 | g_borders.m_vertCenter = ::GetDlgItemInt(dialog, IDC_BORDER_VERT_CENTER, 0, TRUE); 95 | g_borders.m_vertLeft = ::GetDlgItemInt(dialog, IDC_BORDER_VERT_LEFT, 0, TRUE); 96 | g_borders.m_vertRight = ::GetDlgItemInt(dialog, IDC_BORDER_VERT_RIGHT, 0, TRUE); 97 | g_borders.m_horzCenter = ::GetDlgItemInt(dialog, IDC_BORDER_HORZ_CENTER, 0, TRUE); 98 | g_borders.m_horzTop = ::GetDlgItemInt(dialog, IDC_BORDER_HORZ_TOP, 0, TRUE); 99 | g_borders.m_horzBottom = ::GetDlgItemInt(dialog, IDC_BORDER_HORZ_BOTTOM, 0, TRUE); 100 | g_borders.m_vertCenterOrigin = ComboBox_GetCurSel(hwndOrigin[0]); 101 | g_borders.m_vertLeftOrigin = ComboBox_GetCurSel(hwndOrigin[1]); 102 | g_borders.m_vertRightOrigin = ComboBox_GetCurSel(hwndOrigin[2]); 103 | g_borders.m_horzCenterOrigin = ComboBox_GetCurSel(hwndOrigin[3]); 104 | g_borders.m_horzTopOrigin = ComboBox_GetCurSel(hwndOrigin[4]); 105 | g_borders.m_horzBottomOrigin = ComboBox_GetCurSel(hwndOrigin[5]); 106 | g_fillColor = ::GetDlgItemInt(dialog, IDC_FILL_COLOR, 0, FALSE); 107 | g_borderColor = ::GetDlgItemInt(dialog, IDC_BORDER_COLOR, 0, FALSE); 108 | g_hotBorderColor = ::GetDlgItemInt(dialog, IDC_HOT_BORDER_COLOR, 0, FALSE); 109 | g_activeCaptionColor = ::GetDlgItemInt(dialog, IDC_ACTIVE_CAPTION_COLOR, 0, FALSE); 110 | g_activeCaptionTextColor = ::GetDlgItemInt(dialog, IDC_ACTIVE_CAPTION_TEXT_COLOR, 0, FALSE); 111 | g_inactiveCaptionColor = ::GetDlgItemInt(dialog, IDC_INACTIVE_CAPTION_COLOR, 0, FALSE); 112 | g_inactiveCaptionTextColor = ::GetDlgItemInt(dialog, IDC_INACTIVE_CAPTION_TEXT_COLOR, 0, FALSE); 113 | g_useTheme = Button_GetCheck(hwndUseTheme); 114 | 115 | // レイアウトを再計算する。 116 | recalcLayout(); 117 | 118 | // 再描画する。 119 | ::InvalidateRect(hwnd, 0, FALSE); 120 | 121 | return retValue; 122 | } 123 | 124 | //--------------------------------------------------------------------- 125 | 126 | ConfigDialog::ConfigDialog(HWND hwnd) 127 | : Dialog(g_instance, MAKEINTRESOURCE(IDD_CONFIG), hwnd) 128 | { 129 | } 130 | 131 | void ConfigDialog::onOK() 132 | { 133 | Dialog::onOK(); 134 | } 135 | 136 | void ConfigDialog::onCancel() 137 | { 138 | Dialog::onCancel(); 139 | } 140 | 141 | INT_PTR ConfigDialog::onDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 142 | { 143 | switch (message) 144 | { 145 | case WM_COMMAND: 146 | { 147 | UINT id = LOWORD(wParam); 148 | 149 | switch (id) 150 | { 151 | case IDC_FILL_COLOR: 152 | case IDC_BORDER_COLOR: 153 | case IDC_HOT_BORDER_COLOR: 154 | case IDC_ACTIVE_CAPTION_COLOR: 155 | case IDC_ACTIVE_CAPTION_TEXT_COLOR: 156 | case IDC_INACTIVE_CAPTION_COLOR: 157 | case IDC_INACTIVE_CAPTION_TEXT_COLOR: 158 | { 159 | HWND control = (HWND)lParam; 160 | 161 | COLORREF color = ::GetDlgItemInt(hwnd, id, 0, FALSE); 162 | 163 | static COLORREF customColors[16] = {}; 164 | CHOOSECOLOR cc { sizeof(cc) }; 165 | cc.hwndOwner = hwnd; 166 | cc.lpCustColors = customColors; 167 | cc.rgbResult = color; 168 | cc.Flags = CC_RGBINIT | CC_FULLOPEN; 169 | if (!::ChooseColor(&cc)) return TRUE; 170 | 171 | color = cc.rgbResult; 172 | 173 | ::SetDlgItemInt(hwnd, id, color, FALSE); 174 | ::InvalidateRect(control, 0, FALSE); 175 | 176 | return TRUE; 177 | } 178 | } 179 | 180 | break; 181 | } 182 | case WM_DRAWITEM: 183 | { 184 | UINT id = wParam; 185 | 186 | switch (id) 187 | { 188 | case IDC_FILL_COLOR: 189 | case IDC_BORDER_COLOR: 190 | case IDC_HOT_BORDER_COLOR: 191 | case IDC_ACTIVE_CAPTION_COLOR: 192 | case IDC_ACTIVE_CAPTION_TEXT_COLOR: 193 | case IDC_INACTIVE_CAPTION_COLOR: 194 | case IDC_INACTIVE_CAPTION_TEXT_COLOR: 195 | { 196 | DRAWITEMSTRUCT* dis = (DRAWITEMSTRUCT*)lParam; 197 | 198 | COLORREF color = ::GetDlgItemInt(hwnd, id, 0, FALSE); 199 | 200 | HBRUSH brush = ::CreateSolidBrush(color); 201 | FillRect(dis->hDC, &dis->rcItem, brush); 202 | ::DeleteObject(brush); 203 | 204 | return TRUE; 205 | } 206 | } 207 | 208 | break; 209 | } 210 | } 211 | 212 | return Dialog::onDlgProc(hwnd, message, wParam, lParam); 213 | } 214 | 215 | //--------------------------------------------------------------------- 216 | -------------------------------------------------------------------------------- /UniteWindow/ConfigDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Resource.h" 4 | #include "UniteWindow.h" 5 | 6 | //--------------------------------------------------------------------- 7 | 8 | int showConfigDialog(HWND hwnd); 9 | 10 | //--------------------------------------------------------------------- 11 | 12 | class ConfigDialog : public Dialog 13 | { 14 | public: 15 | ConfigDialog(HWND hwnd); 16 | 17 | virtual void onOK(); 18 | virtual void onCancel(); 19 | virtual INT_PTR onDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 20 | }; 21 | 22 | //--------------------------------------------------------------------- 23 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | #include "ConfigDialog.h" 4 | 5 | //--------------------------------------------------------------------- 6 | 7 | // デバッグ用コールバック関数。デバッグメッセージを出力する 8 | void ___outputLog(LPCTSTR text, LPCTSTR output) 9 | { 10 | ::OutputDebugString(output); 11 | } 12 | 13 | //--------------------------------------------------------------------- 14 | 15 | AviUtlInternal g_auin; 16 | HINSTANCE g_instance = 0; 17 | HWND g_singleWindow = 0; 18 | HTHEME g_theme = 0; 19 | WNDPROC g_aviutlWindowProc = 0; 20 | WNDPROC g_exeditWindowProc = 0; 21 | 22 | AviUtlWindow g_aviutlWindow; 23 | ExEditWindow g_exeditWindow; 24 | SettingDialog g_settingDialog; 25 | 26 | Window* g_windowArray[WindowPos::maxSize] = 27 | { 28 | &g_aviutlWindow, 29 | &g_settingDialog, 30 | &g_exeditWindow, 31 | 0, 32 | }; 33 | 34 | int g_layoutMode = LayoutMode::horzSplit; 35 | Borders g_borders = {}; 36 | int g_hotBorder = HotBorder::none; 37 | 38 | int g_borderWidth = 8; 39 | int g_captionHeight = 24; 40 | int g_borderSnapRange = 8; 41 | COLORREF g_fillColor = RGB(0x99, 0x99, 0x99); 42 | COLORREF g_borderColor = RGB(0xcc, 0xcc, 0xcc); 43 | COLORREF g_hotBorderColor = RGB(0x00, 0x00, 0x00); 44 | COLORREF g_activeCaptionColor = ::GetSysColor(COLOR_HIGHLIGHT); 45 | COLORREF g_activeCaptionTextColor = RGB(0xff, 0xff, 0xff); 46 | COLORREF g_inactiveCaptionColor = ::GetSysColor(COLOR_HIGHLIGHTTEXT); 47 | COLORREF g_inactiveCaptionTextColor = RGB(0x00, 0x00, 0x00); 48 | BOOL g_useTheme = FALSE; 49 | 50 | RECT g_captionRect[WindowPos::maxSize]; 51 | 52 | int g_offset = 0; // ドラッグ処理に使う。 53 | 54 | //--------------------------------------------------------------------- 55 | 56 | void initHook() 57 | { 58 | MY_TRACE(_T("initHook()\n")); 59 | 60 | HMODULE user32 = ::GetModuleHandle(_T("user32.dll")); 61 | true_CreateWindowExA = (Type_CreateWindowExA)::GetProcAddress(user32, "CreateWindowExA"); 62 | 63 | DetourTransactionBegin(); 64 | DetourUpdateThread(::GetCurrentThread()); 65 | 66 | ATTACH_HOOK_PROC(CreateWindowExA); 67 | ATTACH_HOOK_PROC(GetMenu); 68 | ATTACH_HOOK_PROC(SetMenu); 69 | ATTACH_HOOK_PROC(DrawMenuBar); 70 | ATTACH_HOOK_PROC(FindWindowExA); 71 | ATTACH_HOOK_PROC(FindWindowW); 72 | ATTACH_HOOK_PROC(GetWindow); 73 | ATTACH_HOOK_PROC(EnumThreadWindows); 74 | ATTACH_HOOK_PROC(EnumWindows); 75 | 76 | if (DetourTransactionCommit() == NO_ERROR) 77 | { 78 | MY_TRACE(_T("API フックに成功しました\n")); 79 | } 80 | else 81 | { 82 | MY_TRACE(_T("API フックに失敗しました\n")); 83 | } 84 | } 85 | 86 | void termHook() 87 | { 88 | MY_TRACE(_T("termHook()\n")); 89 | } 90 | 91 | //--------------------------------------------------------------------- 92 | 93 | HWND createSingleWindow() 94 | { 95 | MY_TRACE(_T("createSingleWindow()\n")); 96 | 97 | // 土台となるシングルウィンドウを作成する。 98 | 99 | WNDCLASS wc = {}; 100 | wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; 101 | wc.hCursor = ::LoadCursor(0, IDC_ARROW); 102 | wc.lpfnWndProc = singleWindowProc; 103 | wc.hInstance = g_instance; 104 | wc.lpszClassName = _T("AviUtl"); // クラス名を AviUtl に偽装する。「AoiSupport」用。 105 | ::RegisterClass(&wc); 106 | 107 | HWND hwnd = ::CreateWindowEx( 108 | 0, 109 | _T("AviUtl"), 110 | _T("UniteWindow"), 111 | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | 112 | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 113 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 114 | 0, 0, g_instance, 0); 115 | 116 | // ここでレイアウトの初期値を算出しておく。 117 | 118 | RECT rc; ::GetClientRect(hwnd, &rc); 119 | int cx = (rc.left + rc.right) / 2; 120 | int cy = (rc.top + rc.bottom) / 2; 121 | 122 | g_layoutMode = LayoutMode::horzSplit; 123 | 124 | g_borders.m_vertCenter = cx; 125 | g_borders.m_vertLeft = cy; 126 | g_borders.m_vertRight = cy; 127 | g_borders.m_vertCenterOrigin = Origin::bottomRight; 128 | g_borders.m_vertLeftOrigin = Origin::bottomRight; 129 | g_borders.m_vertRightOrigin = Origin::bottomRight; 130 | 131 | g_borders.m_horzCenter = cy; 132 | g_borders.m_horzTop = cx; 133 | g_borders.m_horzBottom = cx; 134 | g_borders.m_horzCenterOrigin = Origin::bottomRight; 135 | g_borders.m_horzTopOrigin = Origin::bottomRight; 136 | g_borders.m_horzBottomOrigin = Origin::bottomRight; 137 | 138 | return hwnd; 139 | } 140 | 141 | void normalizeLayoutVertSplit() 142 | { 143 | MY_TRACE(_T("normalizeLayoutVertSplit()\n")); 144 | 145 | RECT rc; ::GetClientRect(g_singleWindow, &rc); 146 | 147 | g_borders.m_vertCenter = max(g_borders.m_vertCenter, rc.left); 148 | g_borders.m_vertCenter = min(g_borders.m_vertCenter, rc.right - g_borderWidth); 149 | 150 | g_borders.m_vertLeft = max(g_borders.m_vertLeft, rc.top); 151 | g_borders.m_vertLeft = min(g_borders.m_vertLeft, rc.bottom - g_borderWidth); 152 | 153 | g_borders.m_vertRight = max(g_borders.m_vertRight, rc.top); 154 | g_borders.m_vertRight = min(g_borders.m_vertRight, rc.bottom - g_borderWidth); 155 | } 156 | 157 | void normalizeLayoutHorzSplit() 158 | { 159 | MY_TRACE(_T("normalizeLayoutHorzSplit()\n")); 160 | 161 | RECT rc; ::GetClientRect(g_singleWindow, &rc); 162 | 163 | g_borders.m_horzCenter = max(g_borders.m_horzCenter, rc.top); 164 | g_borders.m_horzCenter = min(g_borders.m_horzCenter, rc.bottom - g_borderWidth); 165 | 166 | g_borders.m_horzTop = max(g_borders.m_horzTop, rc.left); 167 | g_borders.m_horzTop = min(g_borders.m_horzTop, rc.right - g_borderWidth); 168 | 169 | g_borders.m_horzBottom = max(g_borders.m_horzBottom, rc.left); 170 | g_borders.m_horzBottom = min(g_borders.m_horzBottom, rc.right - g_borderWidth); 171 | } 172 | 173 | void normalizeLayout() 174 | { 175 | MY_TRACE(_T("normalizeLayout()\n")); 176 | 177 | switch (g_layoutMode) 178 | { 179 | case LayoutMode::vertSplit: 180 | { 181 | normalizeLayoutVertSplit(); 182 | 183 | break; 184 | } 185 | case LayoutMode::horzSplit: 186 | { 187 | normalizeLayoutHorzSplit(); 188 | 189 | break; 190 | } 191 | } 192 | } 193 | 194 | int borderToX(LPCRECT rcClient, int border, int borderOrigin) 195 | { 196 | switch (borderOrigin) 197 | { 198 | case Origin::topLeft: 199 | { 200 | return border; 201 | } 202 | case Origin::bottomRight: 203 | { 204 | return rcClient->right - border - g_borderWidth; 205 | } 206 | } 207 | 208 | return 0; 209 | } 210 | 211 | int borderToY(LPCRECT rcClient, int border, int borderOrigin) 212 | { 213 | switch (borderOrigin) 214 | { 215 | case Origin::topLeft: 216 | { 217 | return border; 218 | } 219 | case Origin::bottomRight: 220 | { 221 | return rcClient->bottom - border - g_borderWidth; 222 | } 223 | } 224 | 225 | return 0; 226 | } 227 | 228 | int xToBorder(LPCRECT rcClient, int x, int borderOrigin) 229 | { 230 | switch (borderOrigin) 231 | { 232 | case Origin::topLeft: 233 | { 234 | return x; 235 | } 236 | case Origin::bottomRight: 237 | { 238 | return rcClient->right - x - g_borderWidth; 239 | } 240 | } 241 | 242 | return 0; 243 | } 244 | 245 | int yToBorder(LPCRECT rcClient, int y, int borderOrigin) 246 | { 247 | switch (borderOrigin) 248 | { 249 | case Origin::topLeft: 250 | { 251 | return y; 252 | } 253 | case Origin::bottomRight: 254 | { 255 | return rcClient->bottom - y - g_borderWidth; 256 | } 257 | } 258 | 259 | return 0; 260 | } 261 | 262 | inline RECT getCaptionRectFromContainerRect(const RECT& rcContainer) { 263 | return RECT 264 | { 265 | rcContainer.left, 266 | rcContainer.top - g_captionHeight, 267 | rcContainer.right, 268 | rcContainer.top, 269 | }; 270 | } 271 | 272 | void recalcLayoutVertSplit() 273 | { 274 | MY_TRACE(_T("recalcLayoutVertSplit()\n")); 275 | 276 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 277 | int borderVertCenter = borderToX(&rcClient, g_borders.m_vertCenter, g_borders.m_vertCenterOrigin); 278 | int borderVertLeft = borderToY(&rcClient, g_borders.m_vertLeft, g_borders.m_vertLeftOrigin); 279 | int borderVertRight = borderToY(&rcClient, g_borders.m_vertRight, g_borders.m_vertRightOrigin); 280 | 281 | if (g_windowArray[WindowPos::topLeft]) 282 | { 283 | RECT rcContainer = 284 | { 285 | rcClient.left, 286 | rcClient.top + g_captionHeight, 287 | borderVertCenter, 288 | borderVertLeft, 289 | }; 290 | 291 | g_windowArray[WindowPos::topLeft]->resize(&rcContainer); 292 | g_captionRect[WindowPos::topLeft] = getCaptionRectFromContainerRect(rcContainer); 293 | } 294 | 295 | if (g_windowArray[WindowPos::topRight]) 296 | { 297 | RECT rcContainer = 298 | { 299 | borderVertCenter + g_borderWidth, 300 | rcClient.top + g_captionHeight, 301 | rcClient.right, 302 | borderVertRight, 303 | }; 304 | 305 | g_windowArray[WindowPos::topRight]->resize(&rcContainer); 306 | g_captionRect[WindowPos::topRight] = getCaptionRectFromContainerRect(rcContainer); 307 | } 308 | 309 | if (g_windowArray[WindowPos::bottomLeft]) 310 | { 311 | RECT rcContainer = 312 | { 313 | rcClient.left, 314 | borderVertLeft + g_borderWidth + g_captionHeight, 315 | borderVertCenter, 316 | rcClient.bottom, 317 | }; 318 | 319 | g_windowArray[WindowPos::bottomLeft]->resize(&rcContainer); 320 | g_captionRect[WindowPos::bottomLeft] = getCaptionRectFromContainerRect(rcContainer); 321 | } 322 | 323 | if (g_windowArray[WindowPos::bottomRight]) 324 | { 325 | RECT rcContainer = 326 | { 327 | borderVertCenter + g_borderWidth, 328 | borderVertRight + g_borderWidth + g_captionHeight, 329 | rcClient.right, 330 | rcClient.bottom, 331 | }; 332 | 333 | g_windowArray[WindowPos::bottomRight]->resize(&rcContainer); 334 | g_captionRect[WindowPos::bottomRight] = getCaptionRectFromContainerRect(rcContainer); 335 | } 336 | } 337 | 338 | void recalcLayoutHorzSplit() 339 | { 340 | MY_TRACE(_T("recalcLayoutHorzSplit()\n")); 341 | 342 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 343 | int borderHorzCenter = borderToY(&rcClient, g_borders.m_horzCenter, g_borders.m_horzCenterOrigin); 344 | int borderHorzTop = borderToX(&rcClient, g_borders.m_horzTop, g_borders.m_horzTopOrigin); 345 | int borderHorzBottom = borderToX(&rcClient, g_borders.m_horzBottom, g_borders.m_horzBottomOrigin); 346 | 347 | if (g_windowArray[WindowPos::topLeft]) 348 | { 349 | RECT rcContainer = 350 | { 351 | rcClient.left, 352 | rcClient.top + g_captionHeight, 353 | borderHorzTop, 354 | borderHorzCenter, 355 | }; 356 | 357 | g_windowArray[WindowPos::topLeft]->resize(&rcContainer); 358 | g_captionRect[WindowPos::topLeft] = getCaptionRectFromContainerRect(rcContainer); 359 | } 360 | 361 | if (g_windowArray[WindowPos::topRight]) 362 | { 363 | RECT rcContainer = 364 | { 365 | borderHorzTop + g_borderWidth, 366 | rcClient.top + g_captionHeight, 367 | rcClient.right, 368 | borderHorzCenter, 369 | }; 370 | 371 | g_windowArray[WindowPos::topRight]->resize(&rcContainer); 372 | g_captionRect[WindowPos::topRight] = getCaptionRectFromContainerRect(rcContainer); 373 | } 374 | 375 | if (g_windowArray[WindowPos::bottomLeft]) 376 | { 377 | RECT rcContainer = 378 | { 379 | rcClient.left, 380 | borderHorzCenter + g_borderWidth + g_captionHeight, 381 | borderHorzBottom, 382 | rcClient.bottom, 383 | }; 384 | 385 | g_windowArray[WindowPos::bottomLeft]->resize(&rcContainer); 386 | g_captionRect[WindowPos::bottomLeft] = getCaptionRectFromContainerRect(rcContainer); 387 | } 388 | 389 | if (g_windowArray[WindowPos::bottomRight]) 390 | { 391 | RECT rcContainer = 392 | { 393 | borderHorzBottom + g_borderWidth, 394 | borderHorzCenter + g_borderWidth + g_captionHeight, 395 | rcClient.right, 396 | rcClient.bottom, 397 | }; 398 | 399 | g_windowArray[WindowPos::bottomRight]->resize(&rcContainer); 400 | g_captionRect[WindowPos::bottomRight] = getCaptionRectFromContainerRect(rcContainer); 401 | } 402 | } 403 | 404 | void recalcLayout() 405 | { 406 | MY_TRACE(_T("recalcLayout()\n")); 407 | 408 | if (::IsIconic(g_singleWindow)) 409 | return; 410 | 411 | switch (g_layoutMode) 412 | { 413 | case LayoutMode::vertSplit: 414 | { 415 | normalizeLayoutVertSplit(); 416 | recalcLayoutVertSplit(); 417 | 418 | break; 419 | } 420 | case LayoutMode::horzSplit: 421 | { 422 | normalizeLayoutHorzSplit(); 423 | recalcLayoutHorzSplit(); 424 | 425 | break; 426 | } 427 | } 428 | } 429 | 430 | int hitTestVertSplit(POINT point) 431 | { 432 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 433 | int borderVertCenter = borderToX(&rcClient, g_borders.m_vertCenter, g_borders.m_vertCenterOrigin); 434 | int borderVertLeft = borderToY(&rcClient, g_borders.m_vertLeft, g_borders.m_vertLeftOrigin); 435 | int borderVertRight = borderToY(&rcClient, g_borders.m_vertRight, g_borders.m_vertRightOrigin); 436 | 437 | if (point.x < borderVertCenter) 438 | { 439 | if (point.y >= borderVertLeft && point.y < borderVertLeft + g_borderWidth) 440 | return HotBorder::vertLeft; 441 | } 442 | else if (point.x < borderVertCenter + g_borderWidth) 443 | { 444 | return HotBorder::vertCenter; 445 | } 446 | else 447 | { 448 | if (point.y >= borderVertRight && point.y < borderVertRight + g_borderWidth) 449 | return HotBorder::vertRight; 450 | } 451 | 452 | return HotBorder::none; 453 | } 454 | 455 | int hitTestHorzSplit(POINT point) 456 | { 457 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 458 | int borderHorzCenter = borderToY(&rcClient, g_borders.m_horzCenter, g_borders.m_horzCenterOrigin); 459 | int borderHorzTop = borderToX(&rcClient, g_borders.m_horzTop, g_borders.m_horzTopOrigin); 460 | int borderHorzBottom = borderToX(&rcClient, g_borders.m_horzBottom, g_borders.m_horzBottomOrigin); 461 | 462 | if (point.y < borderHorzCenter) 463 | { 464 | if (point.x >= borderHorzTop && point.x < borderHorzTop + g_borderWidth) 465 | return HotBorder::horzTop; 466 | } 467 | else if (point.y < borderHorzCenter + g_borderWidth) 468 | { 469 | return HotBorder::horzCenter; 470 | } 471 | else 472 | { 473 | if (point.x >= borderHorzBottom && point.x < borderHorzBottom + g_borderWidth) 474 | return HotBorder::horzBottom; 475 | } 476 | 477 | return HotBorder::none; 478 | } 479 | 480 | int hitTest(POINT point) 481 | { 482 | switch (g_layoutMode) 483 | { 484 | case LayoutMode::vertSplit: return hitTestVertSplit(point); 485 | case LayoutMode::horzSplit: return hitTestHorzSplit(point); 486 | } 487 | 488 | return HotBorder::none; 489 | } 490 | 491 | int getOffset(POINT point) 492 | { 493 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 494 | 495 | switch (g_hotBorder) 496 | { 497 | case HotBorder::horzCenter: return g_borders.m_horzCenter - yToBorder(&rcClient, point.y, g_borders.m_horzCenterOrigin); 498 | case HotBorder::horzTop: return g_borders.m_horzTop - xToBorder(&rcClient, point.x, g_borders.m_horzTopOrigin); 499 | case HotBorder::horzBottom: return g_borders.m_horzBottom - xToBorder(&rcClient, point.x, g_borders.m_horzBottomOrigin); 500 | case HotBorder::vertCenter: return g_borders.m_vertCenter - xToBorder(&rcClient, point.x, g_borders.m_vertCenterOrigin); 501 | case HotBorder::vertLeft: return g_borders.m_vertLeft - yToBorder(&rcClient, point.y, g_borders.m_vertLeftOrigin); 502 | case HotBorder::vertRight: return g_borders.m_vertRight - yToBorder(&rcClient, point.y, g_borders.m_vertRightOrigin); 503 | } 504 | 505 | return 0; 506 | } 507 | 508 | void dragBorder(POINT point) 509 | { 510 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 511 | 512 | switch (g_hotBorder) 513 | { 514 | case HotBorder::horzCenter: 515 | { 516 | g_borders.m_horzCenter = yToBorder(&rcClient, point.y, g_borders.m_horzCenterOrigin) + g_offset; 517 | break; 518 | } 519 | case HotBorder::horzTop: 520 | { 521 | g_borders.m_horzTop = xToBorder(&rcClient, point.x, g_borders.m_horzTopOrigin) + g_offset; 522 | if (abs(g_borders.m_horzTop - g_borders.m_horzBottom) < g_borderSnapRange) 523 | g_borders.m_horzTop = g_borders.m_horzBottom; 524 | break; 525 | } 526 | case HotBorder::horzBottom: 527 | { 528 | g_borders.m_horzBottom = xToBorder(&rcClient, point.x, g_borders.m_horzBottomOrigin) + g_offset; 529 | if (abs(g_borders.m_horzBottom - g_borders.m_horzTop) < g_borderSnapRange) 530 | g_borders.m_horzBottom = g_borders.m_horzTop; 531 | break; 532 | } 533 | case HotBorder::vertCenter: 534 | { 535 | g_borders.m_vertCenter = xToBorder(&rcClient, point.x, g_borders.m_vertCenterOrigin) + g_offset; 536 | break; 537 | } 538 | case HotBorder::vertLeft: 539 | { 540 | g_borders.m_vertLeft = yToBorder(&rcClient, point.y, g_borders.m_vertLeftOrigin) + g_offset; 541 | if (abs(g_borders.m_vertLeft - g_borders.m_vertRight) < g_borderSnapRange) 542 | g_borders.m_vertLeft = g_borders.m_vertRight; 543 | break; 544 | } 545 | case HotBorder::vertRight: 546 | { 547 | g_borders.m_vertRight = yToBorder(&rcClient, point.y, g_borders.m_vertRightOrigin) + g_offset; 548 | if (abs(g_borders.m_vertRight - g_borders.m_vertLeft) < g_borderSnapRange) 549 | g_borders.m_vertRight = g_borders.m_vertLeft; 550 | break; 551 | } 552 | } 553 | 554 | if (::GetKeyState(VK_SHIFT) < 0) 555 | { 556 | switch (g_hotBorder) 557 | { 558 | case HotBorder::horzTop: g_borders.m_horzBottom = g_borders.m_horzTop; break; 559 | case HotBorder::horzBottom: g_borders.m_horzTop = g_borders.m_horzBottom; break; 560 | case HotBorder::vertLeft: g_borders.m_vertRight = g_borders.m_vertLeft; break; 561 | case HotBorder::vertRight: g_borders.m_vertLeft = g_borders.m_vertRight; break; 562 | } 563 | } 564 | } 565 | 566 | BOOL getBorderRect(LPRECT rc, int border) 567 | { 568 | RECT rcClient; ::GetClientRect(g_singleWindow, &rcClient); 569 | int borderVertCenter = borderToX(&rcClient, g_borders.m_vertCenter, g_borders.m_vertCenterOrigin); 570 | int borderVertLeft = borderToY(&rcClient, g_borders.m_vertLeft, g_borders.m_vertLeftOrigin); 571 | int borderVertRight = borderToY(&rcClient, g_borders.m_vertRight, g_borders.m_vertRightOrigin); 572 | int borderHorzCenter = borderToY(&rcClient, g_borders.m_horzCenter, g_borders.m_horzCenterOrigin); 573 | int borderHorzTop = borderToX(&rcClient, g_borders.m_horzTop, g_borders.m_horzTopOrigin); 574 | int borderHorzBottom = borderToX(&rcClient, g_borders.m_horzBottom, g_borders.m_horzBottomOrigin); 575 | 576 | switch (border) 577 | { 578 | case HotBorder::vertCenter: 579 | { 580 | rc->left = borderVertCenter; 581 | rc->top = rcClient.top; 582 | rc->right = borderVertCenter + g_borderWidth; 583 | rc->bottom = rcClient.bottom; 584 | 585 | return TRUE; 586 | } 587 | case HotBorder::vertLeft: 588 | { 589 | rc->left = rcClient.left; 590 | rc->top = borderVertLeft; 591 | rc->right = borderVertCenter; 592 | rc->bottom = borderVertLeft + g_borderWidth; 593 | 594 | return TRUE; 595 | } 596 | case HotBorder::vertRight: 597 | { 598 | rc->left = borderVertCenter + g_borderWidth; 599 | rc->top = borderVertRight; 600 | rc->right = rcClient.right; 601 | rc->bottom = borderVertRight + g_borderWidth; 602 | 603 | return TRUE; 604 | } 605 | case HotBorder::horzCenter: 606 | { 607 | rc->left = rcClient.left; 608 | rc->top = borderHorzCenter; 609 | rc->right = rcClient.right; 610 | rc->bottom = borderHorzCenter + g_borderWidth; 611 | 612 | return TRUE; 613 | } 614 | case HotBorder::horzTop: 615 | { 616 | rc->left = borderHorzTop; 617 | rc->top = rcClient.top; 618 | rc->right = borderHorzTop + g_borderWidth; 619 | rc->bottom = borderHorzCenter; 620 | 621 | return TRUE; 622 | } 623 | case HotBorder::horzBottom: 624 | { 625 | rc->left = borderHorzBottom; 626 | rc->top = borderHorzCenter + g_borderWidth; 627 | rc->right = borderHorzBottom + g_borderWidth; 628 | rc->bottom = rcClient.bottom; 629 | 630 | return TRUE; 631 | } 632 | } 633 | 634 | return FALSE; 635 | } 636 | 637 | void drawCaption(HDC dc, HWND hwnd, Window* window) 638 | { 639 | // コンテナウィンドウの矩形を取得する。 640 | RECT rc; ::GetWindowRect(window->m_hwndContainer, &rc); 641 | 642 | if ((rc.bottom - rc.top) <= 0) 643 | return; // ウィンドウの高さが小さすぎる場合は何もしない。 644 | 645 | // コンテナウィンドウの上隣にあるキャプション矩形を取得する。 646 | ::MapWindowPoints(0, hwnd, (POINT*)&rc, 2); 647 | rc.bottom = rc.top; 648 | rc.top = rc.top - g_captionHeight; 649 | 650 | // ウィンドウテキストを取得する。 651 | WCHAR text[MAX_PATH] = {}; 652 | ::GetWindowTextW(window->m_hwnd, text, MAX_PATH); 653 | 654 | if (g_useTheme) 655 | { 656 | // ウィンドウの状態から stateId を取得する。 657 | int stateId = CS_ACTIVE; 658 | if (::GetFocus() != window->m_hwnd) stateId = CS_INACTIVE; 659 | if (!::IsWindowEnabled(window->m_hwnd)) stateId = CS_DISABLED; 660 | 661 | // テーマ API を使用してタイトルを描画する。 662 | ::DrawThemeBackground(g_theme, dc, WP_CAPTION, stateId, &rc, 0); 663 | ::DrawThemeText(g_theme, dc, WP_CAPTION, stateId, 664 | text, ::lstrlenW(text), DT_CENTER | DT_VCENTER | DT_SINGLELINE, 0, &rc); 665 | } 666 | else 667 | { 668 | COLORREF captionColor = g_activeCaptionColor; 669 | COLORREF captionTextColor = g_activeCaptionTextColor; 670 | 671 | if (::GetFocus() != window->m_hwnd) 672 | { 673 | captionColor = g_inactiveCaptionColor; 674 | captionTextColor = g_inactiveCaptionTextColor; 675 | } 676 | 677 | HBRUSH brush = ::CreateSolidBrush(captionColor); 678 | ::FillRect(dc, &rc, brush); 679 | ::DeleteObject(brush); 680 | 681 | int bkMode = ::SetBkMode(dc, TRANSPARENT); 682 | COLORREF textColor = ::SetTextColor(dc, captionTextColor); 683 | ::DrawTextW(dc, text, ::lstrlenW(text), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 684 | ::SetTextColor(dc, textColor); 685 | ::SetBkMode(dc, bkMode); 686 | } 687 | } 688 | 689 | //--------------------------------------------------------------------- 690 | 691 | BOOL importLayout(HWND hwnd) 692 | { 693 | // ファイル選択ダイアログを表示してファイル名を取得する。 694 | 695 | WCHAR fileName[MAX_PATH] = {}; 696 | 697 | WCHAR folderName[MAX_PATH] = {}; 698 | ::GetModuleFileNameW(g_instance, folderName, MAX_PATH); 699 | ::PathRemoveExtensionW(folderName); 700 | 701 | OPENFILENAMEW ofn = { sizeof(ofn) }; 702 | ofn.hwndOwner = hwnd; 703 | ofn.Flags = OFN_FILEMUSTEXIST; 704 | ofn.lpstrTitle = L"レイアウトのインポート"; 705 | ofn.lpstrInitialDir = folderName; 706 | ofn.lpstrFile = fileName; 707 | ofn.nMaxFile = MAX_PATH; 708 | ofn.lpstrFilter = L"レイアウトファイル (*.xml)\0*.xml\0" "すべてのファイル (*.*)\0*.*\0"; 709 | ofn.lpstrDefExt = L"xml"; 710 | 711 | if (!::GetOpenFileNameW(&ofn)) 712 | return FALSE; 713 | 714 | // レイアウトファイルをインポートする。 715 | loadConfig(fileName, TRUE); 716 | 717 | // レイアウトを再計算する。 718 | recalcLayout(); 719 | 720 | // 再描画する。 721 | ::InvalidateRect(hwnd, 0, FALSE); 722 | 723 | return TRUE; 724 | } 725 | 726 | BOOL exportLayout(HWND hwnd) 727 | { 728 | // ファイル選択ダイアログを表示してファイル名を取得する。 729 | 730 | WCHAR fileName[MAX_PATH] = {}; 731 | 732 | WCHAR folderName[MAX_PATH] = {}; 733 | ::GetModuleFileNameW(g_instance, folderName, MAX_PATH); 734 | ::PathRemoveExtensionW(folderName); 735 | 736 | OPENFILENAMEW ofn = { sizeof(ofn) }; 737 | ofn.hwndOwner = hwnd; 738 | ofn.Flags = OFN_OVERWRITEPROMPT; 739 | ofn.lpstrTitle = L"レイアウトのエクスポート"; 740 | ofn.lpstrInitialDir = folderName; 741 | ofn.lpstrFile = fileName; 742 | ofn.nMaxFile = MAX_PATH; 743 | ofn.lpstrFilter = L"レイアウトファイル (*.xml)\0*.xml\0" "すべてのファイル (*.*)\0*.*\0"; 744 | ofn.lpstrDefExt = L"xml"; 745 | 746 | if (!::GetSaveFileNameW(&ofn)) 747 | return FALSE; 748 | 749 | // レイアウトファイルをエクスポートする。 750 | saveConfig(fileName, TRUE); 751 | 752 | return TRUE; 753 | } 754 | 755 | LRESULT CALLBACK singleWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 756 | { 757 | switch (message) 758 | { 759 | case WM_COMMAND: 760 | { 761 | MY_TRACE(_T("singleWindowProc(WM_COMMAND)\n")); 762 | 763 | return ::SendMessage(g_aviutlWindow.m_hwnd, message, wParam, lParam); 764 | } 765 | case WM_SYSCOMMAND: 766 | { 767 | MY_TRACE(_T("singleWindowProc(WM_SYSCOMMAND)\n")); 768 | 769 | switch (wParam) 770 | { 771 | case CommandID::ShowConfigDialog: 772 | { 773 | // UniteWindow の設定ダイアログを開く。 774 | showConfigDialog(hwnd); 775 | 776 | break; 777 | } 778 | case CommandID::ImportLayout: 779 | { 780 | // レイアウトファイルをインポートする。 781 | importLayout(hwnd); 782 | 783 | break; 784 | } 785 | case CommandID::ExportLayout: 786 | { 787 | // レイアウトファイルをエクスポートする。 788 | exportLayout(hwnd); 789 | 790 | break; 791 | } 792 | } 793 | 794 | break; 795 | } 796 | case WM_CREATE: 797 | { 798 | MY_TRACE(_T("singleWindowProc(WM_CREATE)\n")); 799 | 800 | g_theme = ::OpenThemeData(hwnd, VSCLASS_WINDOW); 801 | MY_TRACE_HEX(g_theme); 802 | 803 | HMENU menu = ::GetSystemMenu(hwnd, FALSE); 804 | ::InsertMenu(menu, 0, MF_BYPOSITION | MF_STRING, CommandID::ImportLayout, _T("レイアウトのインポート")); 805 | ::InsertMenu(menu, 1, MF_BYPOSITION | MF_STRING, CommandID::ExportLayout, _T("レイアウトのエクスポート")); 806 | ::InsertMenu(menu, 2, MF_BYPOSITION | MF_STRING, CommandID::ShowConfigDialog, _T("UniteWindowの設定")); 807 | ::InsertMenu(menu, 3, MF_BYPOSITION | MF_SEPARATOR, 0, 0); 808 | 809 | break; 810 | } 811 | case WM_DESTROY: 812 | { 813 | MY_TRACE(_T("singleWindowProc(WM_DESTROY)\n")); 814 | 815 | ::CloseThemeData(g_theme), g_theme = 0; 816 | 817 | break; 818 | } 819 | case WM_CLOSE: 820 | { 821 | MY_TRACE(_T("singleWindowProc(WM_CLOSE)\n")); 822 | 823 | return ::SendMessage(g_aviutlWindow.m_hwnd, message, wParam, lParam); 824 | } 825 | case WM_SETFOCUS: 826 | { 827 | MY_TRACE(_T("singleWindowProc(WM_SETFOCUS)\n")); 828 | 829 | ::SetFocus(g_aviutlWindow.m_hwnd); 830 | 831 | break; 832 | } 833 | case WM_PAINT: 834 | { 835 | PAINTSTRUCT ps; 836 | HDC dc = ::BeginPaint(hwnd, &ps); 837 | RECT rc = ps.rcPaint; 838 | 839 | BP_PAINTPARAMS pp = { sizeof(pp) }; 840 | HDC mdc = 0; 841 | HPAINTBUFFER pb = ::BeginBufferedPaint(dc, &rc, BPBF_COMPATIBLEBITMAP, &pp, &mdc); 842 | 843 | if (pb) 844 | { 845 | HDC dc = mdc; 846 | 847 | { 848 | // 背景を塗りつぶす。 849 | 850 | HBRUSH brush = ::CreateSolidBrush(g_fillColor); 851 | FillRect(dc, &rc, brush); 852 | ::DeleteObject(brush); 853 | } 854 | 855 | if (g_useTheme) 856 | { 857 | // ボーダーを描画する。 858 | 859 | int partId = WP_BORDER; 860 | int stateId = CS_INACTIVE; 861 | 862 | int firstBorder = (g_layoutMode == LayoutMode::vertSplit) ? HotBorder::vertCenter : HotBorder::horzCenter; 863 | for (int i = 0; i < 3; i++) 864 | { 865 | int border = firstBorder + i; 866 | if (border == g_hotBorder) continue; 867 | RECT rcBorder; 868 | if (getBorderRect(&rcBorder, border)) 869 | { 870 | // テーマ API を使用してボーダーを描画する。 871 | ::DrawThemeBackground(g_theme, dc, partId, stateId, &rcBorder, 0); 872 | } 873 | } 874 | } 875 | else 876 | { 877 | // ボーダーを描画する。 878 | 879 | HBRUSH brush = ::CreateSolidBrush(g_borderColor); 880 | 881 | int firstBorder = (g_layoutMode == LayoutMode::vertSplit) ? HotBorder::vertCenter : HotBorder::horzCenter; 882 | for (int i = 0; i < 3; i++) 883 | { 884 | int border = firstBorder + i; 885 | if (border == g_hotBorder) continue; 886 | RECT rcBorder; 887 | if (getBorderRect(&rcBorder, border)) 888 | ::FillRect(dc, &rcBorder, brush); 889 | } 890 | 891 | ::DeleteObject(brush); 892 | } 893 | 894 | if (g_useTheme) 895 | { 896 | // ホットボーダーを描画する。 897 | 898 | int partId = WP_BORDER; 899 | int stateId = CS_ACTIVE; 900 | 901 | RECT rcHotBorder; 902 | if (getBorderRect(&rcHotBorder, g_hotBorder)) 903 | { 904 | // テーマ API を使用してボーダーを描画する。 905 | ::DrawThemeBackground(g_theme, dc, partId, stateId, &rcHotBorder, 0); 906 | } 907 | } 908 | else 909 | { 910 | // ホットボーダーを描画する。 911 | 912 | RECT rcHotBorder; 913 | if (getBorderRect(&rcHotBorder, g_hotBorder)) 914 | { 915 | HBRUSH brush = ::CreateSolidBrush(g_hotBorderColor); 916 | ::FillRect(dc, &rcHotBorder, brush); 917 | ::DeleteObject(brush); 918 | } 919 | } 920 | 921 | { 922 | // 各ウィンドウのキャプションを描画する。 923 | 924 | LOGFONTW lf = {}; 925 | ::GetThemeSysFont(g_theme, TMT_CAPTIONFONT, &lf); 926 | HFONT font = ::CreateFontIndirectW(&lf); 927 | HFONT oldFont = (HFONT)::SelectObject(dc, font); 928 | 929 | drawCaption(dc, hwnd, &g_aviutlWindow); 930 | drawCaption(dc, hwnd, &g_exeditWindow); 931 | drawCaption(dc, hwnd, &g_settingDialog); 932 | 933 | ::SelectObject(dc, oldFont); 934 | ::DeleteObject(font); 935 | } 936 | 937 | ::EndBufferedPaint(pb, TRUE); 938 | } 939 | 940 | EndPaint(hwnd, &ps); 941 | return 0; 942 | } 943 | case WM_SIZE: 944 | { 945 | recalcLayout(); 946 | 947 | break; 948 | } 949 | case WM_SETCURSOR: 950 | { 951 | if (hwnd == (HWND)wParam) 952 | { 953 | POINT point; ::GetCursorPos(&point); 954 | ::ScreenToClient(hwnd, &point); 955 | 956 | int hotBorder = hitTest(point); 957 | 958 | switch (hotBorder) 959 | { 960 | case HotBorder::vertCenter: 961 | case HotBorder::horzTop: 962 | case HotBorder::horzBottom: 963 | { 964 | ::SetCursor(::LoadCursor(0, IDC_SIZEWE)); 965 | 966 | return TRUE; 967 | } 968 | case HotBorder::horzCenter: 969 | case HotBorder::vertLeft: 970 | case HotBorder::vertRight: 971 | { 972 | ::SetCursor(::LoadCursor(0, IDC_SIZENS)); 973 | 974 | return TRUE; 975 | } 976 | } 977 | } 978 | 979 | break; 980 | } 981 | case WM_LBUTTONDOWN: 982 | { 983 | MY_TRACE(_T("singleWindowProc(WM_LBUTTONDOWN)\n")); 984 | 985 | // マウス座標を取得する。 986 | POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 987 | 988 | // マウス座標にあるボーダーを取得する。 989 | g_hotBorder = hitTest(point); 990 | 991 | // ボーダーが有効かチェックする。 992 | if (g_hotBorder != HotBorder::none) 993 | { 994 | // オフセットを取得する。 995 | g_offset = getOffset(point); 996 | 997 | // マウスキャプチャを開始する。 998 | ::SetCapture(hwnd); 999 | 1000 | // 再描画する。 1001 | ::InvalidateRect(hwnd, 0, FALSE); 1002 | } 1003 | 1004 | // キャプションクリック時にウィンドウをアクティブにする 1005 | for (int i = 0; i < WindowPos::maxSize; i++) 1006 | { 1007 | if (g_windowArray[i] != NULL && ::PtInRect(&g_captionRect[i], point)) 1008 | { 1009 | ::SetFocus(g_windowArray[i]->m_hwnd); 1010 | } 1011 | } 1012 | 1013 | break; 1014 | } 1015 | case WM_RBUTTONDOWN: 1016 | { 1017 | MY_TRACE(_T("singleWindowProc(WM_RBUTTONDOWN)\n")); 1018 | 1019 | // マウス座標を取得する。 1020 | POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 1021 | 1022 | // キャプションクリック時にウィンドウをアクティブにする 1023 | for (int i = 0; i < WindowPos::maxSize; i++) 1024 | { 1025 | if (g_windowArray[i] != NULL && ::PtInRect(&g_captionRect[i], point)) 1026 | { 1027 | ::SetFocus(g_windowArray[i]->m_hwnd); 1028 | } 1029 | } 1030 | 1031 | break; 1032 | } 1033 | case WM_LBUTTONUP: 1034 | { 1035 | MY_TRACE(_T("singleWindowProc(WM_LBUTTONUP)\n")); 1036 | 1037 | // マウス座標を取得する。 1038 | POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 1039 | 1040 | // マウスをキャプチャ中かチェックする。 1041 | if (::GetCapture() == hwnd) 1042 | { 1043 | // マウスキャプチャを終了する。 1044 | ::ReleaseCapture(); 1045 | 1046 | // ボーダーを動かす。 1047 | dragBorder(point); 1048 | 1049 | // レイアウトを再計算する。 1050 | recalcLayout(); 1051 | 1052 | // 再描画する。 1053 | ::InvalidateRect(hwnd, 0, FALSE); 1054 | } 1055 | 1056 | break; 1057 | } 1058 | case WM_MOUSEMOVE: 1059 | { 1060 | // マウス座標を取得する。 1061 | POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 1062 | 1063 | // マウスをキャプチャ中かチェックする。 1064 | if (::GetCapture() == hwnd) 1065 | { 1066 | // ボーダーを動かす。 1067 | dragBorder(point); 1068 | 1069 | // レイアウトを再計算する。 1070 | recalcLayout(); 1071 | 1072 | // 再描画する。 1073 | ::InvalidateRect(hwnd, 0, FALSE); 1074 | } 1075 | else 1076 | { 1077 | // マウス座標にあるボーダーを取得する。 1078 | int hotBorder = hitTest(point); 1079 | 1080 | // ホットボーダーと別のボーダーかチェックする。 1081 | if (g_hotBorder != hotBorder) 1082 | { 1083 | // ホットボーダーを更新する。 1084 | g_hotBorder = hotBorder; 1085 | 1086 | // 再描画する。 1087 | ::InvalidateRect(hwnd, 0, FALSE); 1088 | } 1089 | 1090 | // マウスリーブイベントをトラックする。 1091 | TRACKMOUSEEVENT tme = { sizeof(tme) }; 1092 | tme.dwFlags = TME_LEAVE; 1093 | tme.hwndTrack = hwnd; 1094 | ::TrackMouseEvent(&tme); 1095 | } 1096 | 1097 | break; 1098 | } 1099 | case WM_MOUSELEAVE: 1100 | { 1101 | MY_TRACE(_T("singleWindowProc(WM_MOUSELEAVE)\n")); 1102 | 1103 | // 無効なボーダーを取得する。 1104 | int hotBorder = HotBorder::none; 1105 | 1106 | // ホットボーダーと別のボーダーかチェックする。 1107 | if (g_hotBorder != hotBorder) 1108 | { 1109 | // ホットボーダーを更新する。 1110 | g_hotBorder = hotBorder; 1111 | 1112 | // 再描画する。 1113 | ::InvalidateRect(hwnd, 0, FALSE); 1114 | } 1115 | 1116 | break; 1117 | } 1118 | case WindowMessage::WM_POST_INIT: // 最後の初期化処理。 1119 | { 1120 | // 最初のレイアウト計算。 1121 | recalcLayout(); 1122 | ::SetForegroundWindow(hwnd); 1123 | ::SetActiveWindow(hwnd); 1124 | 1125 | break; 1126 | } 1127 | } 1128 | 1129 | return ::DefWindowProc(hwnd, message, wParam, lParam); 1130 | } 1131 | 1132 | //--------------------------------------------------------------------- 1133 | 1134 | IMPLEMENT_HOOK_PROC_NULL(HWND, WINAPI, CreateWindowExA, (DWORD exStyle, LPCSTR className, LPCSTR windowName, DWORD style, int x, int y, int w, int h, HWND parent, HMENU menu, HINSTANCE instance, LPVOID param)) 1135 | { 1136 | if (!((DWORD)className & 0xFFFF0000UL)) 1137 | { 1138 | // className が ATOM の場合は何もしない。 1139 | return true_CreateWindowExA(exStyle, className, windowName, style, x, y, w, h, parent, menu, instance, param); 1140 | } 1141 | 1142 | // デバッグ用出力。 1143 | MY_TRACE(_T("CreateWindowExA(%hs, %hs)\n"), className, windowName); 1144 | 1145 | if (::lstrcmpiA(windowName, "AviUtl") == 0) 1146 | { 1147 | // AviUtl ウィンドウが作成される直前のタイミング。 1148 | 1149 | // 土台となるシングルウィンドウを作成する。 1150 | g_singleWindow = createSingleWindow(); 1151 | 1152 | // 設定をファイルから読み込む。 1153 | loadConfig(); 1154 | 1155 | // シングルウィンドウが非表示なら表示する。 1156 | if (!::IsWindowVisible(g_singleWindow)) 1157 | ::ShowWindow(g_singleWindow, SW_SHOW); 1158 | } 1159 | else if (::lstrcmpiA(className, "AviUtl") == 0 && parent == g_aviutlWindow.m_hwnd) 1160 | { 1161 | // AviUtl のポップアップウィンドウの親をシングルウィンドウに変更する。 1162 | parent = g_singleWindow; 1163 | } 1164 | 1165 | HWND hwnd = true_CreateWindowExA(exStyle, className, windowName, style, x, y, w, h, parent, menu, instance, param); 1166 | 1167 | if (::lstrcmpiA(windowName, "AviUtl") == 0) 1168 | { 1169 | // AviUtl ウィンドウに関する初期化処理を行う。 1170 | g_aviutlWindow.init(hwnd); 1171 | } 1172 | else if (::lstrcmpiA(windowName, "拡張編集") == 0) 1173 | { 1174 | // 拡張編集が読み込まれたのでアドレスを取得する。 1175 | g_auin.initExEditAddress(); 1176 | 1177 | // 設定ダイアログのフックを仕掛ける。 1178 | true_SettingDialogProc = g_auin.HookSettingDialogProc(hook_SettingDialogProc); 1179 | MY_TRACE_HEX(true_SettingDialogProc); 1180 | MY_TRACE_HEX(&hook_SettingDialogProc); 1181 | 1182 | DWORD exedit = g_auin.GetExEdit(); 1183 | 1184 | // rikky_memory.auf + rikky_module.dll 用のフック。 1185 | true_ScriptParamDlgProc = writeAbsoluteAddress(exedit + 0x3454 + 1, hook_ScriptParamDlgProc); 1186 | 1187 | // 拡張編集ウィンドウに関する初期化処理を行う。 1188 | g_exeditWindow.init(hwnd); 1189 | } 1190 | else if (::lstrcmpiA(windowName, "ExtendedFilter") == 0) 1191 | { 1192 | // 設定ダイアログに関する初期化処理を行う。 1193 | g_settingDialog.init(hwnd); 1194 | 1195 | // すべてのウィンドウの初期化処理が終わったので 1196 | // ポストメッセージ先で最初のレイアウト計算を行う。 1197 | ::PostMessage(g_singleWindow, WindowMessage::WM_POST_INIT, 0, 0); 1198 | } 1199 | #if 0 1200 | else if (::lstrcmpiA(className, "AviUtl") == 0 && parent == g_aviutlWindow.m_hwnd) 1201 | { 1202 | // 「スクリプト並べ替え管理」「シークバー+」用。 1203 | // ::GetWindow(fp->hwnd, GW_OWNER) が AviUtl ウィンドウを返すようにする。 1204 | ::SetWindowLong(hwnd, GWL_HWNDPARENT, (LONG)g_aviutlWindow.m_hwnd); 1205 | } 1206 | #endif 1207 | return hwnd; 1208 | } 1209 | 1210 | /* 1211 | GetMenu、SetMenu、DrawMenuBar では 1212 | AviUtl ウィンドウのハンドルが渡されたとき、シングルウィンドウのハンドルに取り替えて偽装する。 1213 | これによって、AviUtl ウィンドウのメニュー処理がシングルウィンドウに対して行われるようになる。 1214 | */ 1215 | IMPLEMENT_HOOK_PROC(HMENU, WINAPI, GetMenu, (HWND hwnd)) 1216 | { 1217 | // MY_TRACE(_T("GetMenu(0x%08X)\n"), hwnd); 1218 | 1219 | if (hwnd == g_aviutlWindow.m_hwnd) 1220 | { 1221 | // MY_TRACE(_T("ウィンドウを偽装します\n")); 1222 | 1223 | hwnd = g_singleWindow; 1224 | } 1225 | 1226 | return true_GetMenu(hwnd); 1227 | } 1228 | 1229 | IMPLEMENT_HOOK_PROC(BOOL, WINAPI, SetMenu, (HWND hwnd, HMENU menu)) 1230 | { 1231 | // MY_TRACE(_T("SetMenu(0x%08X, 0x%08X)\n"), hwnd, menu); 1232 | 1233 | if (hwnd == g_aviutlWindow.m_hwnd) 1234 | { 1235 | // MY_TRACE(_T("ウィンドウを偽装します\n")); 1236 | 1237 | hwnd = g_singleWindow; 1238 | } 1239 | 1240 | return true_SetMenu(hwnd, menu); 1241 | } 1242 | 1243 | IMPLEMENT_HOOK_PROC(BOOL, WINAPI, DrawMenuBar, (HWND hwnd)) 1244 | { 1245 | // MY_TRACE(_T("DrawMenuBar(0x%08X)\n"), hwnd); 1246 | 1247 | if (hwnd == g_aviutlWindow.m_hwnd) 1248 | { 1249 | // MY_TRACE(_T("ウィンドウを偽装します\n")); 1250 | 1251 | hwnd = g_singleWindow; 1252 | } 1253 | 1254 | return true_DrawMenuBar(hwnd); 1255 | } 1256 | 1257 | IMPLEMENT_HOOK_PROC(HWND, WINAPI, FindWindowExA, (HWND parent, HWND childAfter, LPCSTR className, LPCSTR windowName)) 1258 | { 1259 | MY_TRACE(_T("FindWindowExA(0x%08X, 0x%08X, %hs, %hs)\n"), parent, childAfter, className, windowName); 1260 | 1261 | // 「テキスト編集補助プラグイン」用。 1262 | if (!parent && className && ::lstrcmpiA(className, "ExtendedFilterClass") == 0) 1263 | return g_settingDialog.m_hwnd; 1264 | 1265 | return true_FindWindowExA(parent, childAfter, className, windowName); 1266 | } 1267 | 1268 | IMPLEMENT_HOOK_PROC(HWND, WINAPI, FindWindowW, (LPCWSTR className, LPCWSTR windowName)) 1269 | { 1270 | MY_TRACE(_T("FindWindowW(%ws, %ws)\n"), className, windowName); 1271 | 1272 | // 「PSDToolKit」の「送る」用。 1273 | if (className && ::lstrcmpiW(className, L"ExtendedFilterClass") == 0) 1274 | return g_settingDialog.m_hwnd; 1275 | 1276 | return true_FindWindowW(className, windowName); 1277 | } 1278 | 1279 | IMPLEMENT_HOOK_PROC(HWND, WINAPI, GetWindow, (HWND hwnd, UINT cmd)) 1280 | { 1281 | // MY_TRACE(_T("GetWindow(0x%08X, %d)\n"), hwnd, cmd); 1282 | // MY_TRACE_HWND(hwnd); 1283 | 1284 | if (cmd == GW_OWNER) 1285 | { 1286 | if (hwnd == g_exeditWindow.m_hwnd) 1287 | { 1288 | // 拡張編集ウィンドウのオーナーウィンドウは AviUtl ウィンドウ。 1289 | return g_aviutlWindow.m_hwnd; 1290 | } 1291 | else if (hwnd == g_settingDialog.m_hwnd) 1292 | { 1293 | // 設定ダイアログのオーナーウィンドウは拡張編集ウィンドウ。 1294 | return g_exeditWindow.m_hwnd; 1295 | } 1296 | #if 1 1297 | HWND retValue = true_GetWindow(hwnd, cmd); 1298 | 1299 | if (retValue == g_singleWindow) 1300 | { 1301 | // 「スクリプト並べ替え管理」「シークバー+」などの一般的なプラグイン用。 1302 | // シングルウィンドウがオーナーになっている場合は AviUtl ウィンドウを返すようにする。 1303 | return g_aviutlWindow.m_hwnd; 1304 | } 1305 | 1306 | return retValue; 1307 | #endif 1308 | } 1309 | 1310 | return true_GetWindow(hwnd, cmd); 1311 | } 1312 | 1313 | IMPLEMENT_HOOK_PROC(BOOL, WINAPI, EnumThreadWindows, (DWORD threadId, WNDENUMPROC enumProc, LPARAM lParam)) 1314 | { 1315 | MY_TRACE(_T("EnumThreadWindows(%d, 0x%08X, 0x%08X)\n"), threadId, enumProc, lParam); 1316 | 1317 | // 「イージング設定時短プラグイン」用。 1318 | if (threadId == ::GetCurrentThreadId() && enumProc && lParam) 1319 | { 1320 | // enumProc() の中で ::GetWindow() が呼ばれる。 1321 | if (!enumProc(g_settingDialog.m_hwnd, lParam)) 1322 | return FALSE; 1323 | } 1324 | 1325 | return true_EnumThreadWindows(threadId, enumProc, lParam); 1326 | } 1327 | 1328 | IMPLEMENT_HOOK_PROC(BOOL, WINAPI, EnumWindows, (WNDENUMPROC enumProc, LPARAM lParam)) 1329 | { 1330 | MY_TRACE(_T("EnumWindows(0x%08X, 0x%08X)\n"), enumProc, lParam); 1331 | 1332 | // 「拡張編集RAMプレビュー」用。 1333 | if (enumProc && lParam) 1334 | { 1335 | if (!enumProc(g_aviutlWindow.m_hwnd, lParam)) 1336 | return FALSE; 1337 | } 1338 | 1339 | return true_EnumWindows(enumProc, lParam); 1340 | } 1341 | 1342 | IMPLEMENT_HOOK_PROC_NULL(INT_PTR, CALLBACK, ScriptParamDlgProc, (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)) 1343 | { 1344 | switch (message) 1345 | { 1346 | case WM_INITDIALOG: 1347 | { 1348 | MY_TRACE(_T("ScriptParamDlgProc(WM_INITDIALOG)\n")); 1349 | 1350 | // rikky_memory.auf + rikky_module.dll 用。 1351 | ::PostMessage(g_settingDialog.m_hwnd, WM_NCACTIVATE, FALSE, (LPARAM)hwnd); 1352 | 1353 | break; 1354 | } 1355 | } 1356 | 1357 | return true_ScriptParamDlgProc(hwnd, message, wParam, lParam); 1358 | } 1359 | 1360 | COLORREF WINAPI Dropper_GetPixel(HDC _dc, int x, int y) 1361 | { 1362 | MY_TRACE(_T("Dropper_GetPixel(0x%08X, %d, %d)\n"), _dc, x, y); 1363 | 1364 | // すべてのモニタのすべての場所から色を抽出できるようにする。 1365 | 1366 | POINT point; ::GetCursorPos(&point); 1367 | ::LogicalToPhysicalPointForPerMonitorDPI(0, &point); 1368 | HDC dc = ::GetDC(0); 1369 | COLORREF color = ::GetPixel(dc, point.x, point.y); 1370 | ::ReleaseDC(0, dc); 1371 | return color; 1372 | } 1373 | 1374 | BOOL isAncestor(HWND hwnd, HWND child) 1375 | { 1376 | while (child) 1377 | { 1378 | if (child == hwnd) 1379 | return TRUE; 1380 | 1381 | child = ::GetParent(child); 1382 | } 1383 | 1384 | return FALSE; 1385 | } 1386 | 1387 | HWND WINAPI KeyboardHook_GetActiveWindow() 1388 | { 1389 | MY_TRACE(_T("KeyboardHook_GetActiveWindow()\n")); 1390 | 1391 | HWND focus = ::GetFocus(); 1392 | 1393 | if (isAncestor(g_settingDialog.m_hwnd, focus)) 1394 | { 1395 | MY_TRACE(_T("設定ダイアログを返します\n")); 1396 | return g_settingDialog.m_hwnd; 1397 | } 1398 | 1399 | if (isAncestor(g_exeditWindow.m_hwnd, focus)) 1400 | { 1401 | MY_TRACE(_T("拡張編集ウィンドウを返します\n")); 1402 | return g_exeditWindow.m_hwnd; 1403 | } 1404 | 1405 | return ::GetActiveWindow(); 1406 | } 1407 | 1408 | //--------------------------------------------------------------------- 1409 | 1410 | EXTERN_C BOOL APIENTRY DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) 1411 | { 1412 | switch (reason) 1413 | { 1414 | case DLL_PROCESS_ATTACH: 1415 | { 1416 | // ロケールを設定する。 1417 | // これをやらないと日本語テキストが文字化けするので最初に実行する。 1418 | _tsetlocale(LC_ALL, _T("")); 1419 | 1420 | MY_TRACE(_T("DLL_PROCESS_ATTACH\n")); 1421 | 1422 | // この DLL のハンドルをグローバル変数に保存しておく。 1423 | g_instance = instance; 1424 | MY_TRACE_HEX(g_instance); 1425 | 1426 | // この DLL の参照カウンタを増やしておく。 1427 | WCHAR moduleFileName[MAX_PATH] = {}; 1428 | ::GetModuleFileNameW(g_instance, moduleFileName, MAX_PATH); 1429 | ::LoadLibraryW(moduleFileName); 1430 | 1431 | initHook(); 1432 | 1433 | break; 1434 | } 1435 | case DLL_PROCESS_DETACH: 1436 | { 1437 | MY_TRACE(_T("DLL_PROCESS_DETACH\n")); 1438 | 1439 | termHook(); 1440 | 1441 | break; 1442 | } 1443 | } 1444 | 1445 | return TRUE; 1446 | } 1447 | 1448 | //--------------------------------------------------------------------- 1449 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //--------------------------------------------------------------------- 4 | 5 | class Window 6 | { 7 | public: 8 | HWND m_hwnd = 0; 9 | HWND m_hwndContainer = 0; 10 | public: 11 | virtual void init(HWND hwnd) = 0; 12 | static HWND getWindow(HWND hwndContainer); 13 | static void setWindow(HWND hwndContainer, HWND hwnd); 14 | static HWND createContainerWindow(HWND child, WNDPROC wndProc, LPCTSTR className); 15 | void resize(LPCRECT rc); 16 | }; 17 | 18 | class AviUtlWindow : public Window 19 | { 20 | public: 21 | virtual void init(HWND hwnd); 22 | static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 23 | }; 24 | 25 | class ExEditWindow : public Window 26 | { 27 | public: 28 | virtual void init(HWND hwnd); 29 | static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 30 | }; 31 | 32 | class SettingDialog : public Window 33 | { 34 | public: 35 | 36 | BOOL m_blockSizeHandler = FALSE; 37 | SIZE m_rawWindowSize = {}; 38 | 39 | virtual void init(HWND hwnd); 40 | void updateScrollBar(); 41 | void scroll(int bar, WPARAM wParam); 42 | void recalcLayout(); 43 | void extend(); 44 | static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 45 | }; 46 | 47 | struct WindowPos 48 | { 49 | static const int topLeft = 0; 50 | static const int topRight = 1; 51 | static const int bottomLeft = 2; 52 | static const int bottomRight = 3; 53 | 54 | static const int maxSize = 4; 55 | }; 56 | 57 | struct 58 | { 59 | int value; 60 | LPCWSTR label; 61 | 62 | } const g_windowPosLabel[] = 63 | { 64 | { WindowPos::topLeft, L"topLeft" }, 65 | { WindowPos::topRight, L"topRight" }, 66 | { WindowPos::bottomLeft, L"bottomLeft" }, 67 | { WindowPos::bottomRight, L"bottomRight" }, 68 | }; 69 | 70 | struct LayoutMode 71 | { 72 | static const int vertSplit = 0; 73 | static const int horzSplit = 1; 74 | 75 | static const int maxSize = 2; 76 | }; 77 | 78 | struct 79 | { 80 | int value; 81 | LPCWSTR label; 82 | 83 | } const g_layoutModeLabel[] = 84 | { 85 | { LayoutMode::vertSplit, L"vertSplit" }, 86 | { LayoutMode::horzSplit, L"horzSplit" }, 87 | }; 88 | 89 | struct Origin 90 | { 91 | static const int topLeft = 0; 92 | static const int bottomRight = 1; 93 | }; 94 | 95 | struct 96 | { 97 | int value; 98 | LPCWSTR label; 99 | 100 | } const g_originLabel[] = 101 | { 102 | { Origin::topLeft, L"topLeft" }, 103 | { Origin::bottomRight, L"bottomRight" }, 104 | }; 105 | 106 | struct Borders 107 | { 108 | int m_vertCenter; 109 | int m_vertLeft; 110 | int m_vertRight; 111 | 112 | int m_vertCenterOrigin; 113 | int m_vertLeftOrigin; 114 | int m_vertRightOrigin; 115 | 116 | int m_horzCenter; 117 | int m_horzTop; 118 | int m_horzBottom; 119 | 120 | int m_horzCenterOrigin; 121 | int m_horzTopOrigin; 122 | int m_horzBottomOrigin; 123 | }; 124 | 125 | struct HotBorder 126 | { 127 | static const int none = 0; 128 | 129 | static const int vertCenter = 1; 130 | static const int vertLeft = 2; 131 | static const int vertRight = 3; 132 | 133 | static const int horzCenter = 4; 134 | static const int horzTop = 5; 135 | static const int horzBottom = 6; 136 | }; 137 | 138 | struct CommandID 139 | { 140 | static const int ShowConfigDialog = 1000; 141 | static const int ImportLayout = 1001; 142 | static const int ExportLayout = 1002; 143 | }; 144 | 145 | struct WindowMessage 146 | { 147 | static const UINT WM_POST_INIT = WM_APP + 1; 148 | }; 149 | 150 | //--------------------------------------------------------------------- 151 | 152 | extern AviUtlInternal g_auin; 153 | extern HINSTANCE g_instance; 154 | extern HWND g_singleWindow; 155 | extern HTHEME g_theme; 156 | extern WNDPROC g_aviutlWindowProc; 157 | extern WNDPROC g_exeditWindowProc; 158 | 159 | extern AviUtlWindow g_aviutlWindow; 160 | extern ExEditWindow g_exeditWindow; 161 | extern SettingDialog g_settingDialog; 162 | 163 | extern Window* g_windowArray[WindowPos::maxSize]; 164 | extern int g_layoutMode; 165 | extern Borders g_borders; 166 | extern int g_hotBorder; 167 | 168 | extern int g_borderWidth; 169 | extern int g_captionHeight; 170 | extern int g_borderSnapRange; 171 | extern COLORREF g_fillColor; 172 | extern COLORREF g_borderColor; 173 | extern COLORREF g_hotBorderColor; 174 | extern COLORREF g_activeCaptionColor; 175 | extern COLORREF g_activeCaptionTextColor; 176 | extern COLORREF g_inactiveCaptionColor; 177 | extern COLORREF g_inactiveCaptionTextColor; 178 | extern BOOL g_useTheme; 179 | 180 | //--------------------------------------------------------------------- 181 | 182 | struct 183 | { 184 | Window* value; 185 | LPCWSTR label; 186 | 187 | } const g_windowIdLabel[] = 188 | { 189 | { &g_aviutlWindow, L"aviutlWindow" }, 190 | { &g_exeditWindow, L"exeditWindow" }, 191 | { &g_settingDialog, L"settingDialog" }, 192 | { 0, L"" }, 193 | }; 194 | 195 | //--------------------------------------------------------------------- 196 | 197 | HWND createSingleWindow(); 198 | void normalizeLayoutHorzSplit(); 199 | void normalizeLayoutVertSplit(); 200 | void recalcLayoutHorzSplit(); 201 | void recalcLayoutVertSplit(); 202 | void recalcLayout(); 203 | LRESULT CALLBACK singleWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 204 | LRESULT CALLBACK aviutlWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 205 | LRESULT CALLBACK exeditWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 206 | 207 | HRESULT loadConfig(); 208 | HRESULT loadConfig(LPCWSTR fileName, BOOL _import); 209 | HRESULT loadLayout(const MSXML2::IXMLDOMElementPtr& element); 210 | 211 | HRESULT saveConfig(); 212 | HRESULT saveConfig(LPCWSTR fileName, BOOL _export); 213 | HRESULT saveLayout(const MSXML2::IXMLDOMElementPtr& element); 214 | 215 | //--------------------------------------------------------------------- 216 | 217 | DECLARE_HOOK_PROC(LRESULT, WINAPI, SettingDialogProc, (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); 218 | DECLARE_HOOK_PROC(HWND, WINAPI, CreateWindowExA, (DWORD exStyle, LPCSTR className, LPCSTR windowName, DWORD style, int x, int y, int w, int h, HWND parent, HMENU menu, HINSTANCE instance, LPVOID param)); 219 | DECLARE_HOOK_PROC(HMENU, WINAPI, GetMenu, (HWND hwnd)); 220 | DECLARE_HOOK_PROC(BOOL, WINAPI, SetMenu, (HWND hwnd, HMENU menu)); 221 | DECLARE_HOOK_PROC(BOOL, WINAPI, DrawMenuBar, (HWND hwnd)); 222 | DECLARE_HOOK_PROC(HWND, WINAPI, FindWindowExA, (HWND parent, HWND childAfter, LPCSTR className, LPCSTR windowName)); 223 | DECLARE_HOOK_PROC(HWND, WINAPI, FindWindowW, (LPCWSTR className, LPCWSTR windowName)); 224 | DECLARE_HOOK_PROC(HWND, WINAPI, GetWindow, (HWND hwnd, UINT cmd)); 225 | DECLARE_HOOK_PROC(BOOL, WINAPI, EnumThreadWindows, (DWORD threadId, WNDENUMPROC enumProc, LPARAM lParam)); 226 | DECLARE_HOOK_PROC(BOOL, WINAPI, EnumWindows, (WNDENUMPROC enumProc, LPARAM lParam)); 227 | DECLARE_HOOK_PROC(INT_PTR, CALLBACK, ScriptParamDlgProc, (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); 228 | 229 | COLORREF WINAPI Dropper_GetPixel(HDC dc, int x, int y); 230 | HWND WINAPI KeyboardHook_GetActiveWindow(); 231 | 232 | //--------------------------------------------------------------------- 233 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hebiiro/AviUtl-Plugin-UniteWindow/db5ad9837eb88479afbea34fc84eb3bafd73d607/UniteWindow/UniteWindow.rc -------------------------------------------------------------------------------- /UniteWindow/UniteWindow.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {772bc0b9-7ca2-4ef5-9439-91d4f823156e} 25 | UniteWindow 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | MultiByte 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | MultiByte 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | MultiByte 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 94 | true 95 | Use 96 | pch.h 97 | ../../;../../AviUtl/aviutl_exedit_sdk/ 98 | stdcpplatest 99 | 100 | 101 | Windows 102 | true 103 | false 104 | $(TargetName).def 105 | ../../ 106 | 107 | 108 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test_psd\Plugins\$(TargetName).aul" 109 | 110 | 111 | 112 | 113 | Level3 114 | true 115 | true 116 | true 117 | WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 118 | true 119 | Use 120 | pch.h 121 | ../../;../../AviUtl/aviutl_exedit_sdk/ 122 | stdcpplatest 123 | 124 | 125 | Windows 126 | true 127 | true 128 | true 129 | false 130 | $(TargetName).def 131 | ../../ 132 | 133 | 134 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test_psd\Plugins\$(TargetName).aul" 135 | 136 | 137 | 138 | 139 | Level3 140 | true 141 | _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 142 | true 143 | Use 144 | pch.h 145 | ../../;../../AviUtl/aviutl_exedit_sdk/ 146 | stdcpplatest 147 | 148 | 149 | Windows 150 | true 151 | false 152 | $(TargetName).def 153 | ../../ 154 | 155 | 156 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test_psd\Plugins\$(TargetName).aul" 157 | 158 | 159 | 160 | 161 | Level3 162 | true 163 | true 164 | true 165 | NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 166 | true 167 | Use 168 | pch.h 169 | ../../;../../AviUtl/aviutl_exedit_sdk/ 170 | stdcpplatest 171 | 172 | 173 | Windows 174 | true 175 | true 176 | true 177 | false 178 | $(TargetName).def 179 | ../../ 180 | 181 | 182 | copy /B /Y "$(TargetDir)$(TargetFileName)" "C:\AviUtl110_test_psd\Plugins\$(TargetName).aul" 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | Create 202 | Create 203 | Create 204 | Create 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Common 8 | 9 | 10 | Common 11 | 12 | 13 | Common 14 | 15 | 16 | Common 17 | 18 | 19 | Common 20 | 21 | 22 | 23 | Common 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | {177f322b-85e3-40d8-98e7-bca29a16eb22} 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow_Config_Load.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | HRESULT loadConfig() 7 | { 8 | MY_TRACE(_T("loadConfig()\n")); 9 | 10 | WCHAR fileName[MAX_PATH] = {}; 11 | ::GetModuleFileNameW(g_instance, fileName, MAX_PATH); 12 | ::PathRenameExtensionW(fileName, L".xml"); 13 | 14 | return loadConfig(fileName, FALSE); 15 | } 16 | 17 | HRESULT loadConfig(LPCWSTR fileName, BOOL _import) 18 | { 19 | MY_TRACE(_T("loadConfig(%ws, %d)\n"), fileName, _import); 20 | 21 | try 22 | { 23 | // MSXML を使用する。 24 | MSXML2::IXMLDOMDocumentPtr document(__uuidof(MSXML2::DOMDocument)); 25 | 26 | // 設定ファイルを開く。 27 | if (document->load(fileName) == VARIANT_FALSE) 28 | { 29 | MY_TRACE(_T("%s を開けませんでした\n"), fileName); 30 | 31 | return S_FALSE; 32 | } 33 | 34 | MSXML2::IXMLDOMElementPtr element = document->documentElement; 35 | 36 | if (!_import) // インポートのときはこれらの変数は取得しない。 37 | { 38 | getPrivateProfileInt(element, L"borderWidth", g_borderWidth); 39 | getPrivateProfileInt(element, L"captionHeight", g_captionHeight); 40 | getPrivateProfileInt(element, L"borderSnapRange", g_borderSnapRange); 41 | getPrivateProfileColor(element, L"fillColor", g_fillColor); 42 | getPrivateProfileColor(element, L"borderColor", g_borderColor); 43 | getPrivateProfileColor(element, L"hotBorderColor", g_hotBorderColor); 44 | getPrivateProfileColor(element, L"activeCaptionColor", g_activeCaptionColor); 45 | getPrivateProfileColor(element, L"activeCaptionTextColor", g_activeCaptionTextColor); 46 | getPrivateProfileColor(element, L"inactiveCaptionColor", g_inactiveCaptionColor); 47 | getPrivateProfileColor(element, L"inactiveCaptionTextColor", g_inactiveCaptionTextColor); 48 | getPrivateProfileBool(element, L"useTheme", g_useTheme); 49 | } 50 | 51 | // ウィンドウ位置を取得する。 52 | getPrivateProfileWindow(element, L"singleWindow", g_singleWindow); 53 | 54 | // を読み込む。 55 | loadLayout(element); 56 | 57 | MY_TRACE(_T("設定ファイルの読み込みに成功しました\n")); 58 | 59 | return S_OK; 60 | } 61 | catch (_com_error& e) 62 | { 63 | MY_TRACE(_T("設定ファイルの読み込みに失敗しました\n")); 64 | MY_TRACE(_T("%s\n"), e.ErrorMessage()); 65 | return e.Error(); 66 | } 67 | } 68 | 69 | // を読み込む。 70 | HRESULT loadLayout(const MSXML2::IXMLDOMElementPtr& element) 71 | { 72 | MY_TRACE(_T("loadLayout()\n")); 73 | 74 | // を読み込む。 75 | MSXML2::IXMLDOMNodeListPtr nodeList = element->selectNodes(L"layout"); 76 | int c = nodeList->length; 77 | for (int i = 0; i < c; i++) 78 | { 79 | MSXML2::IXMLDOMElementPtr layoutElement = nodeList->item[i]; 80 | 81 | // のアトリビュートを読み込む。 82 | 83 | // layoutMode を取得する。 84 | getPrivateProfileLabel(layoutElement, L"layoutMode", g_layoutMode, g_layoutModeLabel); 85 | 86 | { 87 | // を読み込む。 88 | MSXML2::IXMLDOMNodeListPtr nodeList = layoutElement->selectNodes(L"window"); 89 | int c = nodeList->length; 90 | for (int i = 0; i < c; i++) 91 | { 92 | MSXML2::IXMLDOMElementPtr windowElement = nodeList->item[i]; 93 | 94 | // pos を取得する。 95 | int pos = WindowPos::maxSize; 96 | getPrivateProfileLabel(windowElement, L"pos", pos, g_windowPosLabel); 97 | if (pos == WindowPos::maxSize) continue; 98 | 99 | // id を取得する。 100 | getPrivateProfileLabel(windowElement, L"id", g_windowArray[pos], g_windowIdLabel); 101 | } 102 | } 103 | 104 | { 105 | // を読み込む。 106 | MSXML2::IXMLDOMNodeListPtr nodeList = layoutElement->selectNodes(L"vertSplit"); 107 | int c = nodeList->length; 108 | for (int i = 0; i < c; i++) 109 | { 110 | MSXML2::IXMLDOMElementPtr vertSplitElement = nodeList->item[i]; 111 | 112 | // のアトリビュートを読み込む。 113 | 114 | getPrivateProfileInt(vertSplitElement, L"center", g_borders.m_vertCenter); 115 | getPrivateProfileInt(vertSplitElement, L"left", g_borders.m_vertLeft); 116 | getPrivateProfileInt(vertSplitElement, L"right", g_borders.m_vertRight); 117 | 118 | getPrivateProfileLabel(vertSplitElement, L"centerOrigin", g_borders.m_vertCenterOrigin, g_originLabel); 119 | getPrivateProfileLabel(vertSplitElement, L"leftOrigin", g_borders.m_vertLeftOrigin, g_originLabel); 120 | getPrivateProfileLabel(vertSplitElement, L"rightOrigin", g_borders.m_vertRightOrigin, g_originLabel); 121 | } 122 | } 123 | 124 | { 125 | // を読み込む。 126 | MSXML2::IXMLDOMNodeListPtr nodeList = layoutElement->selectNodes(L"horzSplit"); 127 | int c = nodeList->length; 128 | for (int i = 0; i < c; i++) 129 | { 130 | MSXML2::IXMLDOMElementPtr horzSplitElement = nodeList->item[i]; 131 | 132 | // のアトリビュートを読み込む。 133 | 134 | getPrivateProfileInt(horzSplitElement, L"center", g_borders.m_horzCenter); 135 | getPrivateProfileInt(horzSplitElement, L"top", g_borders.m_horzTop); 136 | getPrivateProfileInt(horzSplitElement, L"bottom", g_borders.m_horzBottom); 137 | 138 | getPrivateProfileLabel(horzSplitElement, L"centerOrigin", g_borders.m_horzCenterOrigin, g_originLabel); 139 | getPrivateProfileLabel(horzSplitElement, L"topOrigin", g_borders.m_horzTopOrigin, g_originLabel); 140 | getPrivateProfileLabel(horzSplitElement, L"bottomOrigin", g_borders.m_horzBottomOrigin, g_originLabel); 141 | } 142 | } 143 | } 144 | 145 | return S_OK; 146 | } 147 | 148 | //--------------------------------------------------------------------- 149 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow_Config_Save.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | HRESULT saveConfig() 7 | { 8 | MY_TRACE(_T("saveConfig()\n")); 9 | 10 | WCHAR fileName[MAX_PATH] = {}; 11 | ::GetModuleFileNameW(g_instance, fileName, MAX_PATH); 12 | ::PathRenameExtensionW(fileName, L".xml"); 13 | 14 | return saveConfig(fileName, FALSE); 15 | } 16 | 17 | HRESULT saveConfig(LPCWSTR fileName, BOOL _export) 18 | { 19 | MY_TRACE(_T("saveConfig(%ws, %d)\n"), fileName, _export); 20 | 21 | try 22 | { 23 | // ドキュメントを作成する。 24 | MSXML2::IXMLDOMDocumentPtr document(__uuidof(MSXML2::DOMDocument)); 25 | 26 | // ドキュメントエレメントを作成する。 27 | MSXML2::IXMLDOMElementPtr element = appendElement(document, document, L"config"); 28 | 29 | if (!_export) // エクスポートのときはこれらの変数は保存しない。 30 | { 31 | setPrivateProfileInt(element, L"borderWidth", g_borderWidth); 32 | setPrivateProfileInt(element, L"captionHeight", g_captionHeight); 33 | setPrivateProfileInt(element, L"borderSnapRange", g_borderSnapRange); 34 | setPrivateProfileColor(element, L"fillColor", g_fillColor); 35 | setPrivateProfileColor(element, L"borderColor", g_borderColor); 36 | setPrivateProfileColor(element, L"hotBorderColor", g_hotBorderColor); 37 | setPrivateProfileColor(element, L"activeCaptionColor", g_activeCaptionColor); 38 | setPrivateProfileColor(element, L"activeCaptionTextColor", g_activeCaptionTextColor); 39 | setPrivateProfileColor(element, L"inactiveCaptionColor", g_inactiveCaptionColor); 40 | setPrivateProfileColor(element, L"inactiveCaptionTextColor", g_inactiveCaptionTextColor); 41 | setPrivateProfileBool(element, L"useTheme", g_useTheme); 42 | } 43 | 44 | // ウィンドウ位置を保存する。 45 | setPrivateProfileWindow(element, L"singleWindow", g_singleWindow); 46 | 47 | // を作成する。 48 | saveLayout(element); 49 | 50 | return saveXMLDocument(document, fileName, L"UTF-16"); 51 | } 52 | catch (_com_error& e) 53 | { 54 | MY_TRACE(_T("%s\n"), e.ErrorMessage()); 55 | return e.Error(); 56 | } 57 | } 58 | 59 | // を作成する。 60 | HRESULT saveLayout(const MSXML2::IXMLDOMElementPtr& element) 61 | { 62 | MY_TRACE(_T("saveLayout()\n")); 63 | 64 | // を作成する。 65 | MSXML2::IXMLDOMElementPtr layoutElement = appendElement(element, L"layout"); 66 | 67 | setPrivateProfileLabel(layoutElement, L"layoutMode", g_layoutMode, g_layoutModeLabel); 68 | 69 | for (int i = 0; i < WindowPos::maxSize; i++) 70 | { 71 | // を作成する。 72 | MSXML2::IXMLDOMElementPtr windowElement = appendElement(layoutElement, L"window"); 73 | setPrivateProfileLabel(windowElement, L"pos", i, g_windowPosLabel); 74 | setPrivateProfileLabel(windowElement, L"id", g_windowArray[i], g_windowIdLabel); 75 | } 76 | 77 | // を作成する。 78 | MSXML2::IXMLDOMElementPtr vertSplitElement = appendElement(layoutElement, L"vertSplit"); 79 | setPrivateProfileInt(vertSplitElement, L"center", g_borders.m_vertCenter); 80 | setPrivateProfileInt(vertSplitElement, L"left", g_borders.m_vertLeft); 81 | setPrivateProfileInt(vertSplitElement, L"right", g_borders.m_vertRight); 82 | setPrivateProfileLabel(vertSplitElement, L"centerOrigin", g_borders.m_vertCenterOrigin, g_originLabel); 83 | setPrivateProfileLabel(vertSplitElement, L"leftOrigin", g_borders.m_vertLeftOrigin, g_originLabel); 84 | setPrivateProfileLabel(vertSplitElement, L"rightOrigin", g_borders.m_vertRightOrigin, g_originLabel); 85 | 86 | // を作成する。 87 | MSXML2::IXMLDOMElementPtr horzSplitElement = appendElement(layoutElement, L"horzSplit"); 88 | setPrivateProfileInt(horzSplitElement, L"center", g_borders.m_horzCenter); 89 | setPrivateProfileInt(horzSplitElement, L"top", g_borders.m_horzTop); 90 | setPrivateProfileInt(horzSplitElement, L"bottom", g_borders.m_horzBottom); 91 | setPrivateProfileLabel(horzSplitElement, L"centerOrigin", g_borders.m_horzCenterOrigin, g_originLabel); 92 | setPrivateProfileLabel(horzSplitElement, L"topOrigin", g_borders.m_horzTopOrigin, g_originLabel); 93 | setPrivateProfileLabel(horzSplitElement, L"bottomOrigin", g_borders.m_horzBottomOrigin, g_originLabel); 94 | 95 | return S_OK; 96 | } 97 | 98 | //--------------------------------------------------------------------- 99 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow_Window.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | HWND Window::getWindow(HWND hwndContainer) 7 | { 8 | return (HWND)::GetProp(hwndContainer, _T("UniteWindow.Window")); 9 | } 10 | 11 | void Window::setWindow(HWND hwndContainer, HWND hwnd) 12 | { 13 | ::SetProp(hwndContainer, _T("UniteWindow.Window"), hwnd); 14 | } 15 | 16 | HWND Window::createContainerWindow(HWND hwnd, WNDPROC wndProc, LPCTSTR className) 17 | { 18 | MY_TRACE(_T("createContainerWindow(0x%08X, %s)\n"), hwnd, className); 19 | 20 | WNDCLASS wc = {}; 21 | wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; 22 | wc.hCursor = ::LoadCursor(0, IDC_ARROW); 23 | wc.lpfnWndProc = wndProc; 24 | wc.hInstance = g_instance; 25 | wc.lpszClassName = className; 26 | ::RegisterClass(&wc); 27 | 28 | HWND hwndContainer = ::CreateWindowEx( 29 | 0, 30 | className, 31 | className, 32 | WS_VISIBLE | WS_CHILD | 33 | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 34 | 0, 0, 0, 0, 35 | g_singleWindow, 0, g_instance, 0); 36 | 37 | setWindow(hwndContainer, hwnd); 38 | 39 | return hwndContainer; 40 | } 41 | 42 | void Window::resize(LPCRECT rc) 43 | { 44 | int x = rc->left; 45 | int y = rc->top; 46 | int w = rc->right - rc->left; 47 | int h = rc->bottom - rc->top; 48 | 49 | x = min(rc->left, rc->right); 50 | y = min(rc->top, rc->bottom); 51 | w = max(w, 0); 52 | h = max(h, 0); 53 | 54 | ::MoveWindow(m_hwndContainer, x, y, w, h, TRUE); 55 | } 56 | 57 | //--------------------------------------------------------------------- 58 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow_Window_AviUtlWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | void AviUtlWindow::init(HWND hwnd) 7 | { 8 | m_hwnd = hwnd; 9 | m_hwndContainer = createContainerWindow( 10 | hwnd, containerWndProc, _T("UniteWindow.AviUtlWindow")); 11 | 12 | ::SetParent(m_hwnd, m_hwndContainer); 13 | 14 | DWORD style = ::GetWindowLong(m_hwnd, GWL_STYLE); 15 | style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU); 16 | style |= WS_CHILD; 17 | ::SetWindowLong(m_hwnd, GWL_STYLE, style); 18 | #if 0 19 | DWORD exStyle = ::GetWindowLong(m_hwnd, GWL_EXSTYLE); 20 | exStyle |= WS_EX_NOACTIVATE; 21 | ::SetWindowLong(m_hwnd, GWL_EXSTYLE, exStyle); 22 | #endif 23 | ::SetWindowPos(m_hwnd, 0, 0, 0, 0, 0, 24 | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED); 25 | 26 | g_aviutlWindowProc = (WNDPROC)::SetWindowLongPtr( 27 | m_hwnd, GWLP_WNDPROC, (LONG_PTR)aviutlWindowProc); 28 | 29 | HICON icon = (HICON)::GetClassLong(m_hwnd, GCL_HICON); 30 | ::SetClassLong(g_singleWindow, GCL_HICON, (LONG)icon); 31 | ::SetClassLong(g_singleWindow, GCL_HICONSM, (LONG)icon); 32 | } 33 | 34 | LRESULT CALLBACK AviUtlWindow::containerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 35 | { 36 | switch (message) 37 | { 38 | case WM_PAINT: 39 | { 40 | PAINTSTRUCT ps = {}; 41 | HDC dc = ::BeginPaint(hwnd, &ps); 42 | HBRUSH brush = (HBRUSH)::SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)dc, (LPARAM)hwnd); 43 | if (brush) ::FillRect(dc, &ps.rcPaint, brush); 44 | ::EndPaint(hwnd, &ps); 45 | return 0; 46 | } 47 | case WM_SIZE: 48 | { 49 | RECT rc; ::GetClientRect(hwnd, &rc); 50 | 51 | HWND child = getWindow(hwnd); 52 | RECT rcClient; ::GetClientRect(child, &rcClient); 53 | RECT rcWindow; ::GetWindowRect(child, &rcWindow); 54 | ::MapWindowPoints(child, 0, (POINT*)&rcClient, 2); 55 | 56 | rc.left += rcWindow.left - rcClient.left; 57 | rc.top += rcWindow.top - rcClient.top; 58 | rc.right += rcWindow.right - rcClient.right; 59 | rc.bottom += rcWindow.bottom - rcClient.bottom; 60 | 61 | int x = rc.left; 62 | int y = rc.top; 63 | int w = rc.right - rc.left; 64 | int h = rc.bottom - rc.top; 65 | 66 | ::MoveWindow(child, x, y, w, h, TRUE); 67 | 68 | break; 69 | } 70 | case WM_SETFOCUS: 71 | case WM_LBUTTONDOWN: 72 | case WM_RBUTTONDOWN: 73 | { 74 | ::SetFocus(g_aviutlWindow.m_hwnd); 75 | 76 | break; 77 | } 78 | } 79 | 80 | return ::DefWindowProc(hwnd, message, wParam, lParam); 81 | } 82 | 83 | LRESULT CALLBACK aviutlWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 84 | { 85 | switch (message) 86 | { 87 | case WM_DESTROY: 88 | { 89 | MY_TRACE(_T("aviutlWindowProc(WM_DESTROY)\n")); 90 | 91 | saveConfig(); 92 | 93 | break; 94 | } 95 | case WM_SETTEXT: 96 | { 97 | // MY_TRACE(_T("aviutlWindowProc(WM_SETTEXT)\n")); 98 | 99 | ::InvalidateRect(g_singleWindow, 0, FALSE); 100 | 101 | AviUtl::EditHandle* editp = (AviUtl::EditHandle*)g_auin.GetEditp(); 102 | 103 | char fileName[MAX_PATH] = {}; 104 | if (editp->frame_n) 105 | { 106 | ::StringCbCopyA(fileName, sizeof(fileName), editp->project_filename); 107 | ::PathStripPathA(fileName); 108 | 109 | if (::lstrlenA(fileName) == 0) 110 | ::StringCbCopyA(fileName, sizeof(fileName), (LPCSTR)lParam); 111 | } 112 | else 113 | { 114 | ::StringCbCopyA(fileName, sizeof(fileName), "無題"); 115 | } 116 | ::StringCbCatA(fileName, sizeof(fileName), " - AviUtl"); 117 | ::SetWindowTextA(g_singleWindow, fileName); 118 | 119 | break; 120 | } 121 | case WM_SETFOCUS: 122 | case WM_KILLFOCUS: 123 | { 124 | ::InvalidateRect(g_singleWindow, 0, FALSE); 125 | 126 | break; 127 | } 128 | case WM_LBUTTONDOWN: 129 | case WM_RBUTTONDOWN: 130 | { 131 | ::SetFocus(hwnd); 132 | 133 | break; 134 | } 135 | } 136 | 137 | return ::CallWindowProc(g_aviutlWindowProc, hwnd, message, wParam, lParam); 138 | } 139 | 140 | //--------------------------------------------------------------------- 141 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow_Window_ExeditWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | void ExEditWindow::init(HWND hwnd) 7 | { 8 | m_hwnd = hwnd; 9 | m_hwndContainer = createContainerWindow( 10 | hwnd, containerWndProc, _T("UniteWindow.ExEditWindow")); 11 | 12 | ::SetParent(m_hwnd, m_hwndContainer); 13 | 14 | DWORD style = ::GetWindowLong(m_hwnd, GWL_STYLE); 15 | style &= ~(WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU); 16 | style |= WS_CHILD; 17 | ::SetWindowLong(m_hwnd, GWL_STYLE, style); 18 | #if 0 19 | DWORD exStyle = ::GetWindowLong(m_hwnd, GWL_EXSTYLE); 20 | exStyle |= WS_EX_NOACTIVATE; 21 | ::SetWindowLong(m_hwnd, GWL_EXSTYLE, exStyle); 22 | #endif 23 | ::SetWindowPos(m_hwnd, 0, 0, 0, 0, 0, 24 | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED); 25 | 26 | g_exeditWindowProc = (WNDPROC)::SetWindowLongPtr( 27 | m_hwnd, GWLP_WNDPROC, (LONG_PTR)exeditWindowProc); 28 | 29 | DWORD exedit = (DWORD)::GetModuleHandle(_T("exedit.auf")); 30 | hookAbsoluteCall(exedit + 0x22128, Dropper_GetPixel); 31 | 32 | { 33 | BYTE code[6]; 34 | code[0] = (BYTE)0x90; // NOP 35 | code[1] = (BYTE)0xBD; // MOV EBP,DWORD 36 | *(DWORD*)&code[2] = (DWORD)KeyboardHook_GetActiveWindow; 37 | 38 | writeCode(exedit + 0x30D0E, code, sizeof(code)); 39 | } 40 | } 41 | 42 | LRESULT CALLBACK ExEditWindow::containerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 43 | { 44 | switch (message) 45 | { 46 | case WM_PAINT: 47 | { 48 | PAINTSTRUCT ps = {}; 49 | HDC dc = ::BeginPaint(hwnd, &ps); 50 | HBRUSH brush = (HBRUSH)::SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)dc, (LPARAM)hwnd); 51 | if (brush) ::FillRect(dc, &ps.rcPaint, brush); 52 | ::EndPaint(hwnd, &ps); 53 | return 0; 54 | } 55 | case WM_SIZE: 56 | { 57 | RECT rc; ::GetClientRect(hwnd, &rc); 58 | 59 | HWND child = getWindow(hwnd); 60 | RECT rcClient; ::GetClientRect(child, &rcClient); 61 | RECT rcWindow; ::GetWindowRect(child, &rcWindow); 62 | ::MapWindowPoints(child, 0, (POINT*)&rcClient, 2); 63 | 64 | rc.left += rcWindow.left - rcClient.left; 65 | rc.top += rcWindow.top - rcClient.top; 66 | rc.right += rcWindow.right - rcClient.right; 67 | rc.bottom += rcWindow.bottom - rcClient.bottom; 68 | 69 | rc.bottom -= g_auin.GetLayerHeight() / 2; 70 | ::SendMessage(child, WM_SIZING, WMSZ_BOTTOM, (LPARAM)&rc); 71 | 72 | int x = rc.left; 73 | int y = rc.top; 74 | int w = rc.right - rc.left; 75 | int h = rc.bottom - rc.top; 76 | 77 | ::MoveWindow(child, x, y, w, h, TRUE); 78 | 79 | break; 80 | } 81 | case WM_SETFOCUS: 82 | case WM_LBUTTONDOWN: 83 | case WM_RBUTTONDOWN: 84 | { 85 | ::SetFocus(g_exeditWindow.m_hwnd); 86 | 87 | break; 88 | } 89 | } 90 | 91 | return ::DefWindowProc(hwnd, message, wParam, lParam); 92 | } 93 | 94 | LRESULT CALLBACK exeditWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 95 | { 96 | switch (message) 97 | { 98 | case WM_NCPAINT: 99 | { 100 | HDC dc = ::GetWindowDC(hwnd); 101 | RECT rc; ::GetWindowRect(hwnd, &rc); 102 | ::OffsetRect(&rc, -rc.left, -rc.top); 103 | HBRUSH brush = (HBRUSH)::SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)dc, (LPARAM)hwnd); 104 | if (brush) ::FillRect(dc, &rc, brush); 105 | ::ReleaseDC(hwnd, dc); 106 | return 0; 107 | } 108 | case WM_SETFOCUS: 109 | case WM_KILLFOCUS: 110 | { 111 | ::InvalidateRect(g_singleWindow, 0, FALSE); 112 | 113 | break; 114 | } 115 | case WM_LBUTTONDOWN: 116 | case WM_RBUTTONDOWN: 117 | { 118 | ::SetFocus(hwnd); 119 | 120 | break; 121 | } 122 | } 123 | 124 | return ::CallWindowProc(g_exeditWindowProc, hwnd, message, wParam, lParam); 125 | } 126 | 127 | //--------------------------------------------------------------------- 128 | -------------------------------------------------------------------------------- /UniteWindow/UniteWindow_Window_SettingDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UniteWindow.h" 3 | 4 | //--------------------------------------------------------------------- 5 | 6 | void SettingDialog::init(HWND hwnd) 7 | { 8 | m_hwnd = hwnd; 9 | m_hwndContainer = createContainerWindow( 10 | hwnd, containerWndProc, _T("UniteWindow.SettingDialog")); 11 | 12 | ::SetParent(m_hwnd, m_hwndContainer); 13 | 14 | DWORD style = ::GetWindowLong(m_hwnd, GWL_STYLE); 15 | style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU); 16 | style |= WS_CHILD; 17 | ::SetWindowLong(m_hwnd, GWL_STYLE, style); 18 | #if 0 19 | DWORD exStyle = ::GetWindowLong(m_hwnd, GWL_EXSTYLE); 20 | exStyle |= WS_EX_NOACTIVATE; 21 | ::SetWindowLong(m_hwnd, GWL_EXSTYLE, exStyle); 22 | #endif 23 | ::SetWindowPos(m_hwnd, 0, 0, 0, 0, 0, 24 | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED); 25 | } 26 | 27 | void SettingDialog::updateScrollBar() 28 | { 29 | RECT rc; ::GetClientRect(m_hwnd, &rc); 30 | int w = rc.right - rc.left; 31 | int h = rc.bottom - rc.top; 32 | 33 | RECT rcContainer; ::GetClientRect(m_hwndContainer, &rcContainer); 34 | int cw = rcContainer.right - rcContainer.left; 35 | int ch = rcContainer.bottom - rcContainer.top; 36 | 37 | SCROLLINFO si = { sizeof(si) }; 38 | si.fMask = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL; 39 | si.nMin = 0; 40 | si.nMax = w - 1; 41 | si.nPage = cw; 42 | ::SetScrollInfo(m_hwndContainer, SB_HORZ, &si, TRUE); 43 | si.nMin = 0; 44 | si.nMax = h - 1; 45 | si.nPage = ch; 46 | ::SetScrollInfo(m_hwndContainer, SB_VERT, &si, TRUE); 47 | } 48 | 49 | void SettingDialog::scroll(int bar, WPARAM wParam) 50 | { 51 | SCROLLINFO si = { sizeof(si) }; 52 | si.fMask = SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL; 53 | ::GetScrollInfo(m_hwndContainer, bar, &si); 54 | 55 | switch (LOWORD(wParam)) 56 | { 57 | case SB_LEFT: si.nPos = si.nMin; break; 58 | case SB_RIGHT: si.nPos = si.nMax; break; 59 | case SB_LINELEFT: si.nPos += -10; break; 60 | case SB_LINERIGHT: si.nPos += 10; break; 61 | case SB_PAGELEFT: si.nPos += -60; break; 62 | case SB_PAGERIGHT: si.nPos += 60; break; 63 | case SB_THUMBTRACK: 64 | case SB_THUMBPOSITION: si.nPos = HIWORD(wParam); break; 65 | } 66 | 67 | ::SetScrollInfo(m_hwndContainer, bar, &si, TRUE); 68 | } 69 | 70 | void SettingDialog::recalcLayout() 71 | { 72 | RECT rc; ::GetClientRect(m_hwndContainer, &rc); 73 | 74 | RECT rcClient; ::GetClientRect(m_hwnd, &rcClient); 75 | RECT rcWindow; ::GetWindowRect(m_hwnd, &rcWindow); 76 | ::MapWindowPoints(m_hwnd, 0, (POINT*)&rcClient, 2); 77 | 78 | rc.left += rcWindow.left - rcClient.left; 79 | rc.top += rcWindow.top - rcClient.top; 80 | rc.right += rcWindow.right - rcClient.right; 81 | rc.bottom += rcWindow.bottom - rcClient.bottom; 82 | 83 | int x = rc.left; 84 | int y = rc.top; 85 | int w = rc.right - rc.left; 86 | int h = rc.bottom - rc.top; 87 | 88 | x -= ::GetScrollPos(m_hwndContainer, SB_HORZ); 89 | y -= ::GetScrollPos(m_hwndContainer, SB_VERT); 90 | 91 | ::SetWindowPos(m_hwnd, 0, x, y, 0, 0, 92 | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); 93 | } 94 | 95 | // 設定ダイアログのサイズをコンテナウィンドウのサイズまで広げる。 96 | void SettingDialog::extend() 97 | { 98 | RECT rc; ::GetWindowRect(m_hwnd, &rc); 99 | RECT rcContainer; ::GetWindowRect(m_hwndContainer, &rcContainer); 100 | 101 | int w = rc.right - rc.left; 102 | int h = m_rawWindowSize.cy; 103 | int cw = rcContainer.right - rcContainer.left; 104 | int ch = rcContainer.bottom - rcContainer.top; 105 | 106 | // 初期化が完全に終わっていないときは何もしない。 107 | if (w == 0 || h == 0 || cw == 0 || ch == 0) return; 108 | 109 | // WM_SIZE ハンドラをブロック状態にしてからサイズを変更する。 110 | m_blockSizeHandler = TRUE; 111 | ::SetWindowPos(m_hwnd, 0, 0, 0, w, max(h, ch), 112 | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); 113 | m_blockSizeHandler = FALSE; 114 | } 115 | 116 | LRESULT CALLBACK SettingDialog::containerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 117 | { 118 | switch (message) 119 | { 120 | case WM_SETFOCUS: 121 | case WM_LBUTTONDOWN: 122 | case WM_RBUTTONDOWN: 123 | { 124 | ::SetFocus(g_settingDialog.m_hwnd); 125 | 126 | break; 127 | } 128 | } 129 | 130 | switch (message) 131 | { 132 | case WM_PAINT: 133 | { 134 | PAINTSTRUCT ps = {}; 135 | HDC dc = ::BeginPaint(hwnd, &ps); 136 | HBRUSH brush = ::CreateSolidBrush(g_fillColor); 137 | FillRect(dc, &ps.rcPaint, brush); 138 | ::DeleteObject(brush); 139 | ::EndPaint(hwnd, &ps); 140 | return 0; 141 | } 142 | case WM_SIZE: 143 | { 144 | g_settingDialog.updateScrollBar(); 145 | g_settingDialog.recalcLayout(); 146 | 147 | g_settingDialog.extend(); 148 | 149 | break; 150 | } 151 | case WM_VSCROLL: 152 | { 153 | g_settingDialog.scroll(SB_VERT, wParam); 154 | g_settingDialog.recalcLayout(); 155 | 156 | break; 157 | } 158 | case WM_HSCROLL: 159 | { 160 | g_settingDialog.scroll(SB_HORZ, wParam); 161 | g_settingDialog.recalcLayout(); 162 | 163 | break; 164 | } 165 | case WM_RBUTTONDOWN: 166 | case WM_RBUTTONUP: 167 | { 168 | // マウス座標を取得する。 169 | POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; 170 | 171 | // マウス座標を変換する。 172 | ::MapWindowPoints(hwnd, g_settingDialog.m_hwnd, &point, 1); 173 | 174 | // 設定ダイアログにメッセージを転送する。 175 | return ::SendMessage(g_settingDialog.m_hwnd, message, wParam, MAKELPARAM(point.x, point.y)); 176 | } 177 | case WM_MOUSEWHEEL: 178 | { 179 | MY_TRACE(_T("SettingDialog::containerWndProc(WM_MOUSEWHEEL, %d)\n"), wParam); 180 | 181 | g_settingDialog.scroll(SB_VERT, ((int)wParam > 0) ? SB_PAGEUP : SB_PAGEDOWN); 182 | g_settingDialog.recalcLayout(); 183 | 184 | break; 185 | } 186 | } 187 | 188 | return ::DefWindowProc(hwnd, message, wParam, lParam); 189 | } 190 | 191 | IMPLEMENT_HOOK_PROC_NULL(LRESULT, WINAPI, SettingDialogProc, (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)) 192 | { 193 | switch (message) 194 | { 195 | case WM_GETMINMAXINFO: 196 | { 197 | MY_TRACE(_T("SettingDialogProc(WM_GETMINMAXINFO)\n")); 198 | 199 | MINMAXINFO* mmi = (MINMAXINFO*)lParam; 200 | mmi->ptMaxTrackSize.y *= 3; 201 | 202 | break; 203 | } 204 | case WM_SIZE: 205 | { 206 | MY_TRACE(_T("SettingDialogProc(WM_SIZE)\n")); 207 | 208 | // WM_SIZE ハンドラがブロックされているときは何もしない。 209 | if (g_settingDialog.m_blockSizeHandler) break; 210 | 211 | // 元のウィンドウ矩形のサイズを取得しておく。 212 | RECT rc; ::GetWindowRect(g_settingDialog.m_hwnd, &rc); 213 | g_settingDialog.m_rawWindowSize.cx = rc.right - rc.left; 214 | g_settingDialog.m_rawWindowSize.cy = rc.bottom - rc.top; 215 | 216 | g_settingDialog.updateScrollBar(); 217 | g_settingDialog.recalcLayout(); 218 | ::InvalidateRect(g_settingDialog.m_hwndContainer, 0, FALSE); 219 | 220 | g_settingDialog.extend(); 221 | 222 | break; 223 | } 224 | case WM_SETFOCUS: 225 | case WM_KILLFOCUS: 226 | { 227 | ::InvalidateRect(g_singleWindow, 0, FALSE); 228 | 229 | break; 230 | } 231 | case WM_LBUTTONDOWN: 232 | case WM_RBUTTONDOWN: 233 | { 234 | ::SetFocus(hwnd); 235 | 236 | break; 237 | } 238 | case WM_MOUSEWHEEL: 239 | { 240 | // 既定の処理をブロックし、コンテナウィンドウへバイパス 241 | ::SendMessage(g_settingDialog.m_hwndContainer, message, wParam, lParam); 242 | return 0; 243 | } 244 | } 245 | 246 | return true_SettingDialogProc(hwnd, message, wParam, lParam); 247 | } 248 | 249 | //--------------------------------------------------------------------- 250 | -------------------------------------------------------------------------------- /UniteWindow/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /UniteWindow/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define ISOLATION_AWARE_ENABLED 1 4 | #define WIN32_LEAN_AND_MEAN 5 | #include 6 | #include 7 | #include 8 | #pragma comment(lib, "shlwapi.lib") 9 | #include 10 | #pragma comment(lib, "comctl32.lib") 11 | #include 12 | #pragma comment(lib, "comdlg32.lib") 13 | #include 14 | #include 15 | #include 16 | #pragma comment(lib, "uxtheme.lib") 17 | #include 18 | #pragma comment(lib, "winmm.lib") 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #import 26 | 27 | #include "AviUtl/aviutl_plugin_sdk/filter.h" 28 | #include "AviUtl/aviutl_exedit_sdk/aviutl.hpp" 29 | #include "AviUtl/aviutl_exedit_sdk/exedit.hpp" 30 | #include "Common/Tracer.h" 31 | #include "Common/Dialog.h" 32 | #include "Common/MSXML.h" 33 | #include "Common/Hook.h" 34 | #include "Common/AviUtlInternal.h" 35 | #include "Detours.4.0.1/detours.h" 36 | #pragma comment(lib, "Detours.4.0.1/detours.lib") 37 | 38 | #pragma comment(linker,"\"/manifestdependency:type='win32' \ 39 | name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ 40 | processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 41 | -------------------------------------------------------------------------------- /UniteWindow/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hebiiro/AviUtl-Plugin-UniteWindow/db5ad9837eb88479afbea34fc84eb3bafd73d607/UniteWindow/resource.h --------------------------------------------------------------------------------