簡體   English   中英

CefSharp中的可拖動無邊界窗口

[英]Draggable borderless window in CefSharp

我想在一些HTML元素上使用拖動邏輯實現無邊界窗口。 我找到了一些可行的示例(例如Chrome的無框窗口 ),這就是我嘗試過的示例:

.title-area 
{
   -webkit-app-region: drag;
}

<div class='title-area'>
    A draggable area
</div>

然后,在C#代碼中,我實現了IDragHandler類:

internal class PromtDragHandler : IDragHandler
{
    bool IDragHandler.OnDragEnter(IWebBrowser browserControl, IBrowser browser, IDragData dragData, DragOperationsMask mask)
    {
        return false;
    }

    void IDragHandler.OnDraggableRegionsChanged(IWebBrowser browserControl, IBrowser browser, IList<DraggableRegion> regions)
    {

    }
}

方法OnDraggableRegionsChanged在啟動時會觸發一次,當我拖動元素“ title-area”的某些文本時會觸發OnDragEnter。 但是我不確定下一步該怎么做才能移動窗口?

更新。 如評論中所述, CefTestApp支持此拖動功能。 在源代碼中,我們有方法OnSetDraggableRegions,該方法從DragHandler調用:

void RootWindowWin::OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) {
REQUIRE_MAIN_THREAD();

// Reset draggable region.
  ::SetRectRgn(draggable_region_, 0, 0, 0, 0);

  // Determine new draggable region.
  std::vector<CefDraggableRegion>::const_iterator it = regions.begin();
  for (;it != regions.end(); ++it) {
    HRGN region = ::CreateRectRgn(
        it->bounds.x, it->bounds.y,
        it->bounds.x + it->bounds.width,
        it->bounds.y + it->bounds.height);
    ::CombineRgn(
        draggable_region_, draggable_region_, region,
        it->draggable ? RGN_OR : RGN_DIFF);
    ::DeleteObject(region);
  }

  // Subclass child window procedures in order to do hit-testing.
  // This will be a no-op, if it is already subclassed.
  if (hwnd_) {
    WNDENUMPROC proc = !regions.empty() ?
        SubclassWindowsProc : UnSubclassWindowsProc;
    ::EnumChildWindows(
        hwnd_, proc, reinterpret_cast<LPARAM>(draggable_region_));
  }
}

我仍然不太了解,有關可拖動區域(開始時僅觸發一次)的確切信息如何幫助移動窗口? 有人可以向我解釋這種邏輯或提供等效於C#的代碼嗎?

看看: https//github.com/qwqcode/CefSharpDraggableRegion

GIF

您可以指定-webkit-app-region: drag在CSS中-webkit-app-region: drag以告訴CefSharp哪些區域是可拖動的(如操作系統的標准標題欄)。

UPDATE2。 我做的。 這是我添加到表單代碼中的內容:

IntPtr DragableRegionNative = Native.CreateRectRgn(0, 0, 0, 0);

    void RegionsChangedCallback(DraggableRegion[] Regions)
    {

        Native.SetRectRgn(DragableRegionNative, 0, 0, 0, 0);

        if (Regions == null)
            return;

        foreach (var Region in Regions)
        {
            var RegionNative = Native.CreateRectRgn(
                Region.X, Region.Y,
                Region.X + Region.Width,
                Region.Y + Region.Height);

            Native.CombineRgn(DragableRegionNative, DragableRegionNative, RegionNative,
                Region.Draggable ? (int)Native.CombineRgnStyles.RGN_OR : (int)Native.CombineRgnStyles.RGN_DIFF);

            Native.DeleteObject(RegionNative);
        }
    }


    Point dragOffset = new Point();

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);

        if (e.Button == MouseButtons.Left)
        {
            dragOffset = this.PointToScreen(e.Location);
            dragOffset.X -= Location.X;
            dragOffset.Y -= Location.Y;
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        if (e.Button == MouseButtons.Left)
        {
            Point newLocation = this.PointToScreen(e.Location);

            newLocation.X -= dragOffset.X;
            newLocation.Y -= dragOffset.Y;

            Location = newLocation;
        }
    }

    void chromewb_IsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs e)
    {
        if (chromewb.IsBrowserInitialized)
        {
            ChromeWidgetMessageInterceptor.SetupLoop(chromewb, (m) =>
            {
                if (m.Msg == (int)Native.WM.WM_LBUTTONDOWN)
                {
                    var point = Native.ParsePoint(m.LParam.ToInt32());

                    if (Native.PtInRegion(DragableRegionNative, point.X, point.Y))
                        this.InvokeEx(() => Native.PostMessage(this.Handle, (uint)m.Msg, m.WParam, m.LParam));

                }
            });
        }
    }

如您所見,足以從chrome瀏覽器中攔截WM_LBUTTONDOWN事件,然后檢查鼠標指針是否屬於標題區域,如果是,則將此消息發送到主窗體。 窗體一旦收到WM_LBUTTONDOWN事件,內置窗體方法OnMouseDown和OnMouseMove就會完成其他工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM