//=================================================================== // コンストラクタ //=================================================================== /// コンストラクタ public SnapGuide(Profile profile) { foreach (var layoutElement in profile.LayoutElements) { // currentにSnapさせる必要はない if (layoutElement == profile.Current) continue; // Top/Leftは先に、Right/Bottomは後に verticalSnapGuides.AddFirst(layoutElement.BoundRelativeTop); verticalSnapGuides.AddLast(layoutElement.BoundRelativeBottom); horizontalSnapGuides.AddFirst(layoutElement.BoundRelativeLeft); horizontalSnapGuides.AddLast(layoutElement.BoundRelativeRight); } }
//=================================================================== // ヒットテスト //=================================================================== /// ヒットテスト public static bool TryHitTest(Profile profile, RelativePoint mousePoint, out LayoutElement hitElement, out HitModes hitMode) { // 計算途中の結果をまとめるスタック var moveStack = new Stack<LayoutElement>(); var sizeStack = new Stack<LayoutElement>(); // レイアウト要素を線形探索 foreach (var layoutElement in profile.LayoutElements) { // ヒットテスト対象外判定 var maximumBoundRect = HitTest.GetMaximumBoundRect(layoutElement); if (!maximumBoundRect.Contains(mousePoint)) continue; var moveRect = HitTest.GetMoveRect(layoutElement); if (moveRect.Contains(mousePoint)) { // 移動用領域 moveStack.Push(layoutElement); } else { // 移動用領域でない=サイズ変更用領域 sizeStack.Push(layoutElement); } } // sizeStack優先 foreach (var layoutElement in sizeStack) { // 見つかり次第終了 hitMode = HitTest.GetHitMode(layoutElement, mousePoint); hitElement = layoutElement; return true; } // moveStack foreach (var layoutElement in moveStack) { // 見つかり次第終了 hitMode = HitModes.Move; hitElement = layoutElement; return true; } hitElement = null; hitMode = HitModes.Neutral; return false; }
//------------------------------------------------------------------- // リクエストの設定とキャプチャされたビットマップの取得 //------------------------------------------------------------------- /// スクリーンキャプチャをこのマネージャに依頼 /// @param profile プロファイル /// @attention UIスレッド上で実行されることを想定している public void UpdateRequest(Profile profile) { // ProfileからRequestを生成 var profileRequests = new HashSet<ScreenCaptureRequest>(); foreach (var layoutElement in profile.LayoutElements) { if (!layoutElement.IsWindowValid) continue; profileRequests.Add(new ScreenCaptureRequest(layoutElement)); } lock (this.sharedLock) { Debug.Assert(this.isRunning, "Must be running", "ScreenCaptureTimer"); // 三つの場合で処理がわかれる // 1. profileにもcacheにも含まれている = nop // 2. cacheにはあるがprofileにはない = メモリ解放 // 3. profileにはあるがcacheにはない = cacheに追加して即時更新 var onlycacheRequests = new HashSet<ScreenCaptureRequest>(this.cache.Keys); onlycacheRequests.ExceptWith(profileRequests); var onlyProfileRequests = profileRequests; // もう使わないのでCloneしない onlyProfileRequests.ExceptWith(this.cache.Keys); // 2. var needGC = false; foreach (var request in onlycacheRequests) { this.cache[request] = null; var result = this.cache.Remove(request); Debug.WriteLineIf(!result, "!"); needGC = true; } if (needGC) { Debug.Write("G"); GC.Collect(); //GC.WaitForPendingFinalizers(); //GC.Collect(); } // 3. foreach (var request in onlyProfileRequests) { // var bitmapSource = this.Capture(request); var bitmapSource = this.CaptureByGetDIBits(request); Debug.WriteIf(bitmapSource != null, "x"); this.cache[request] = bitmapSource; } } }