欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解C# wpf如何嵌入外部程序

 更新時(shí)間:2024年04月09日 11:25:10   作者:CodeOfCC  
實(shí)現(xiàn)嵌入各種窗口控件后,其實(shí)還會(huì)有一種需求:嵌入外部程序,我們有時(shí)可能需要嵌入一個(gè)瀏覽器或者或者播放器等一些已有的程序,下面我們就來看看具體操作吧

前言

實(shí)現(xiàn)嵌入各種窗口控件后,其實(shí)還會(huì)有一種需求:嵌入外部程序,我們有時(shí)可能需要嵌入一個(gè)瀏覽器或者或者播放器等一些已有的程序,其嵌入原理也和前面差不多,只要能獲取進(jìn)程的主窗口句柄,然后將窗口嵌入。

一、如何實(shí)現(xiàn)

1、定義屬性

定義一個(gè)依賴屬性,提供給xaml設(shè)置進(jìn)程運(yùn)行的命令行

public class AppHost : HwndHost
{
    /// <summary>
    /// 進(jìn)程運(yùn)行的命令行
    /// </summary>
    public string Cmdline
    {
        get { return (string)GetValue(CmdlineProperty); }
        set { SetValue(CmdlineProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Cmdline.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CmdlineProperty =
        DependencyProperty.Register("Cmdline", typeof(string), typeof(AppHost), new PropertyMetadata(""));
}        

2、進(jìn)程嵌入

在下列方法中進(jìn)行進(jìn)程嵌入,具體操作如下列步驟。

protected override HandleRef BuildWindowCore(HandleRef hwndParent)

(1)啟動(dòng)進(jìn)程

var cmds = Cmdline.Split(" ", 2);
Process? _process;
_process.StartInfo.FileName = cmds.First();
_process.StartInfo.Arguments = cmds.Last();
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.CreateNoWindow = true;
_process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
_process.Start();

(2)進(jìn)程加入作業(yè)對(duì)象

這個(gè)步驟是用于管理進(jìn)程,確保《子進(jìn)程跟隨主進(jìn)程關(guān)閉》

static Job _job = new Job();
_job.AddProcess(_process.Handle);

(3)獲取主窗口句柄

下列提供的是簡單獲取主窗口句柄的方法。通過延時(shí)等待的方式獲取。需要精確時(shí)間獲取主窗口句柄則可以使用鉤子,在子進(jìn)程窗口創(chuàng)建事件中獲取句柄。

for (int i = 0; i < 200 && _process.MainWindowHandle == 0; i++) Thread.Sleep(5);
if (_process.MainWindowHandle == 0)
{
    throw new Exception("process no window");
}
return new HandleRef(this, Handle);

3、銷毀進(jìn)程

protected override void DestroyWindowCore(HandleRef hwnd)
{
    _process?.Kill();
    _process?.Dispose();
    _process = null;
}

二、完整代碼

其中Job對(duì)象在《子進(jìn)程跟隨主進(jìn)程關(guān)閉》中。

AppHost.cs

using JobManagement;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using Process = System.Diagnostics.Process;
using TextBox = System.Windows.Controls.TextBox;
using Thread = System.Threading.Thread;

namespace WpfHwndElement
{
    /// <summary>
    /// 需要手動(dòng)dispose此控件。
    /// </summary>
    public class AppHost : HwndHost
    {
        static Job _job = new Job();
        Process? _process;
        /// <summary>
        /// 進(jìn)程運(yùn)行的命令行
        /// </summary>
        public string Cmdline
        {
            get { return (string)GetValue(CmdlineProperty); }
            set { SetValue(CmdlineProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Cmdline.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CmdlineProperty =
            DependencyProperty.Register("Cmdline", typeof(string), typeof(AppHost), new PropertyMetadata(""));

        new public IntPtr Handle
        {
            get { return (IntPtr)GetValue(HandleProperty); }
            private set { SetValue(HandleProperty, value); }
        }
        // Using a DependencyProperty as the backing store for Hwnd.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HandleProperty =
            DependencyProperty.Register("Handle", typeof(IntPtr), typeof(NativeHost), new PropertyMetadata(IntPtr.Zero));
        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
            try
            {
                if (DesignerProperties.GetIsInDesignMode(this)) throw new Exception("design mode won't show app");
                var cmds = Cmdline.Split(" ", 2);
                _process = new Process();
                _process.StartInfo.FileName = cmds.First();
                _process.StartInfo.Arguments = cmds.Length > 1 ? cmds.Last() : "";
                _process.StartInfo.UseShellExecute = false;
                _process.StartInfo.CreateNoWindow = true;
                _process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
                _process.Start();
                _job.AddProcess(_process.Handle);
                for (int i = 0; i < 200 && _process.MainWindowHandle == 0; i++) Thread.Sleep(5);
                if (_process.MainWindowHandle == 0)
                {
                    throw new Exception("process no window");
                }
                Handle = _process.MainWindowHandle;
                var wndStyle = GetWindowLong(Handle, GWL_STYLE);
                wndStyle &= ~WS_THICKFRAME;
                wndStyle &= ~WS_CAPTION;
                SetWindowLong(Handle, GWL_STYLE, wndStyle | WS_CHILD);
                SetParent(Handle, hwndParent.Handle);
            }
            catch (Exception ex)
            {
                var window = new Window() { Width = 0, Height = 0, ResizeMode = ResizeMode.NoResize, WindowStyle = WindowStyle.None, Content = new TextBox() { IsReadOnly = true, Text = ex.Message + " " + ex.StackTrace, TextWrapping = TextWrapping.Wrap } };
                var hwnd = new WindowInteropHelper(window).EnsureHandle();
                window.Show();
                SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD);
                SetParent(hwnd, hwndParent.Handle);
                Handle = hwnd;
            }
            return new HandleRef(this, Handle);
        }
        protected override void DestroyWindowCore(HandleRef hwnd)
        {
            var window = HwndSource.FromHwnd(hwnd.Handle)?.RootVisual as Window;
            window?.Close();
            _process?.Kill();
            _process?.Dispose();
            _process = null;
        }
        const int WS_CAPTION = 0x00C00000;
        const int WS_THICKFRAME = 0x00040000;
        const int WS_CHILD = 0x40000000;
        const int GWL_STYLE = (-16);
        [DllImport("user32.dll", EntryPoint = "GetWindowLongW")]
        static extern int GetWindowLong(IntPtr hwnd, int nIndex);
        [DllImport("user32.dll", EntryPoint = "SetWindowLongW")]
        static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);
        [DllImport("user32.dll")]
        public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    }
}

三、使用示例

嵌入ffplay.exe

MainWindow.xaml

<Window x:Class="WpfHwndElement.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfHwndElement"
        mc:Ignorable="d"
        Title="MainWindow" Height="360" Width="640"       
        >
    <Grid>
        <local:AppHost Cmdline="ffplay" Width="200" Height="200"></local:AppHost>
    </Grid>
</Window>

效果預(yù)覽

在這里插入圖片描述

總結(jié)

嵌入外部程序還是相對(duì)比較容易實(shí)現(xiàn)的,而且也有一定的使用場(chǎng)景。創(chuàng)建進(jìn)程,并能獲取到進(jìn)程的主窗口句柄即可。另外要注意的是管理子進(jìn)程的退出,其他都問題不大。

以上就是詳解C# wpf如何嵌入外部程序的詳細(xì)內(nèi)容,更多關(guān)于C# wpf嵌入外部程序的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#窗體編程不顯示最小化、最大化、關(guān)閉按鈕的方法

    C#窗體編程不顯示最小化、最大化、關(guān)閉按鈕的方法

    這篇文章主要介紹了C#窗體編程不顯示最小化、最大化、關(guān)閉按鈕的方法,即windows forms編程中取消最小化、最大化、關(guān)閉按鈕,需要的朋友可以參考下
    2014-08-08
  • C#之HttpClient設(shè)置cookies的兩種方式

    C#之HttpClient設(shè)置cookies的兩種方式

    這篇文章主要介紹了C#之HttpClient設(shè)置cookies的兩種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Unity實(shí)現(xiàn)全屏截圖以及QQ截圖

    Unity實(shí)現(xiàn)全屏截圖以及QQ截圖

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)全屏截圖以及QQ截圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • 基于WPF實(shí)現(xiàn)裁剪圖像功能

    基于WPF實(shí)現(xiàn)裁剪圖像功能

    這篇文章主要為大家詳細(xì)介紹了如何基于WPF實(shí)現(xiàn)裁剪圖像功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下
    2023-06-06
  • C#實(shí)現(xiàn)TCP和UDP通信的示例詳解

    C#實(shí)現(xiàn)TCP和UDP通信的示例詳解

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)TCP和UDP通信的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下
    2023-03-03
  • Unity Shader實(shí)現(xiàn)素描風(fēng)格的渲染

    Unity Shader實(shí)現(xiàn)素描風(fēng)格的渲染

    這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)素描風(fēng)格的渲染,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C#?日歷類功能的實(shí)例

    C#?日歷類功能的實(shí)例

    本文通過實(shí)例代碼給大家介紹了C#日歷類的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2017-06-06
  • visio二次開發(fā)--判斷文檔是否已發(fā)生變化(變化就加星號(hào)*)

    visio二次開發(fā)--判斷文檔是否已發(fā)生變化(變化就加星號(hào)*)

    最近做一個(gè)故障樹診斷的項(xiàng)目,用visio二次開發(fā),可以同時(shí)打開多個(gè)繪制的故障樹圖形文檔。項(xiàng)目中需要實(shí)現(xiàn)判斷文檔是否發(fā)生變化,這是很多編輯軟件的基本功能,變化了就加個(gè)星號(hào)*
    2013-04-04
  • 編輯IL文件 修改DLL文件的方法

    編輯IL文件 修改DLL文件的方法

    下面小編就為大家?guī)硪黄庉婭L文件 修改DLL文件的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • C#啟動(dòng)和停止windows服務(wù)的實(shí)例代碼

    C#啟動(dòng)和停止windows服務(wù)的實(shí)例代碼

    這篇文章介紹了C#啟動(dòng)和停止windows服務(wù)的實(shí)例代碼,有需要的朋友可以參考一下
    2013-09-09

最新評(píng)論