狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

【C#】在winform中如何實(shí)現(xiàn)嵌入第三方軟件窗體

admin
2024年3月8日 15:25 本文熱度 1647

相關(guān)win32api的學(xué)習(xí)

SetParent

[DllImport("user32.dll ", EntryPoint = "SetParent")]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);   //將外部窗體嵌入程序

語法:

HWND SetParent(
  [in]           HWND hWndChild,
  [in, optional] HWND hWndNewParent
)
;

參數(shù):

參數(shù)名類型含義
hWndChildHWND子窗口的句柄
hWndNewParentHWND新父窗口的句柄。如果此參數(shù)為 NULL,桌面窗口將成為新的父窗口。如果此參數(shù) HWND_MESSAGE,則子窗口將成為 僅消息窗口。

相關(guān)解釋:

什么是句柄?

在計(jì)算機(jī)編程和操作系統(tǒng)中,句柄(Handle)是一個(gè)用于標(biāo)識(shí)和引用對(duì)象或資源的抽象概念。它通常是一個(gè)整數(shù)值或指針,充當(dāng)對(duì)特定資源的引用或訪問標(biāo)識(shí)符。句柄用于管理內(nèi)存、設(shè)備、文件、窗口等各種資源。

句柄在操作系統(tǒng)中被廣泛使用,特別是在圖形用戶界面(GUI)應(yīng)用程序中。例如,在Windows操作系統(tǒng)中,窗口句柄(Window Handle)用于標(biāo)識(shí)和操作窗口對(duì)象。每個(gè)窗口都有一個(gè)唯一的句柄,通過該句柄可以執(zhí)行諸如移動(dòng)、調(diào)整大小、關(guān)閉等操作。

另一個(gè)常見的例子是文件句柄(File Handle),它用于標(biāo)識(shí)和操作打開的文件。通過文件句柄,程序可以讀取、寫入或關(guān)閉文件。

句柄的使用可以提高程序的安全性和效率。它們?cè)试S程序通過句柄而不是直接訪問資源,從而隱藏底層實(shí)現(xiàn)細(xì)節(jié)并提供一種統(tǒng)一的接口。此外,句柄還可以用于實(shí)現(xiàn)資源的共享和保護(hù),通過對(duì)句柄的權(quán)限管理來控制對(duì)資源的訪問。

總的來說,句柄是一種重要的編程概念,用于標(biāo)識(shí)和管理各種資源,從而使程序能夠有效地操作系統(tǒng)資源,并提供安全和統(tǒng)一的訪問接口。

FindWindow

 [DllImport("user32.dll")]
 
public static extern IntPtr FindWindow(string lpszClass, string lpszWindow);      //按照窗體類名或窗體標(biāo)題查找窗體

作用:檢索其類名和窗口名稱與指定字符串匹配的頂級(jí)窗口的句柄。此函數(shù)不搜索子窗口。此函數(shù)不執(zhí)行區(qū)分大小寫的搜索。

若要從指定的子窗口開始搜索子窗口,請(qǐng)使用 FindWindowEx 函數(shù)。

語法:

HWND FindWindowA(
  [in, optional] LPCSTR lpClassName,
  [in, optional] LPCSTR lpWindowName
)
;

參數(shù):

參數(shù)名類型含義
lpClassNameLPCTSTR如果 lpClassName 指向字符串,則指定窗口類名。
lpWindowNameLPCTSTR窗口名稱 (窗口標(biāo)題) 。如果此參數(shù)為 NULL,則所有窗口名稱都匹配。

ShowWindow

作用:設(shè)置指定窗口的顯示狀態(tài)。

語法:

HWND FindWindowA(
  [in, optional] LPCSTR lpClassName,
  [in, optional] LPCSTR lpWindowName
)
;

參數(shù):

參數(shù)名類型含義
hWndHWND窗口的句柄。
nCmdShowint控制窗口的顯示方式。

nCmdShow不同值與含義:



0隱藏窗口并激活另一個(gè)窗口。
1激活并顯示窗口。如果窗口最小化、最大化或排列,系統(tǒng)會(huì)將其還原到其原始大小和位置。應(yīng)用程序應(yīng)在首次顯示窗口時(shí)指定此標(biāo)志。
2激活窗口并將其顯示為最小化窗口。
3激活窗口并顯示最大化的窗口。
4以最近的大小和位置顯示窗口。
5激活窗口并以當(dāng)前大小和位置顯示窗口。
6最小化指定的窗口,并按 Z 順序激活下一個(gè)頂級(jí)窗口。
7將窗口顯示為最小化窗口。
8以當(dāng)前大小和位置顯示窗口。
9激活并顯示窗口。如果窗口最小化、最大化或排列,系統(tǒng)會(huì)將其還原到其原始大小和位置。還原最小化窗口時(shí),應(yīng)用程序應(yīng)指定此標(biāo)志。
10根據(jù)啟動(dòng)應(yīng)用程序的程序傳遞給 CreateProcess 函數(shù)的 STARTUPINFO 結(jié)構(gòu)中指定的SW_值設(shè)置顯示狀態(tài)。
11最小化窗口,即使擁有窗口的線程沒有響應(yīng)。僅當(dāng)最小化不同線程的窗口時(shí),才應(yīng)使用此標(biāo)志。

創(chuàng)建一個(gè)靜態(tài)類

為了便于進(jìn)行相關(guān)的操作,創(chuàng)建一個(gè)靜態(tài)類:

  public static class WindowManager
  {
      
public static IntPtr intPtr;         //第三方應(yīng)用窗口的句柄

      
/// <summary>
      
/// 調(diào)整第三方應(yīng)用窗體大小
      
/// </summary>
      
public static void ResizeWindow()
      {
          ShowWindow(intPtr, 
0);  //先將窗口隱藏
          ShowWindow(intPtr, 
3);  //再將窗口最大化,可以讓第三方窗口自適應(yīng)容器的大小
      }

      
/// <summary>
      
/// 循環(huán)查找第三方窗體
      
/// </summary>
      
/// <returns></returns>
      
public static bool FindWindow(string formName)
      {
          
for (int i = 0; i < 100; i++)
          {
              
//按照窗口標(biāo)題查找Python窗口
              IntPtr vHandle = FindWindow(
null, formName);
              
if (vHandle == IntPtr.Zero)
              {
                  Thread.Sleep(
100);  //100ms查找一次,直到找到,最多查找10s
                  
continue;
              }
              
else      //找到返回True
              {
                  intPtr = vHandle;
                  
return true;
              }
          }
          intPtr = IntPtr.Zero;
          
return false;
      }


      
/// <summary>
      
/// 將第三方窗體嵌入到容器內(nèi)
      
/// </summary>
      
/// <param name="hWndNewParent">父容器句柄</param>
      
/// <param name="windowName">窗體名</param>
      
public static void SetParent(IntPtr hWndNewParent, string windowName)
      {
          ShowWindow(intPtr, 
0);                 //先將窗體隱藏,防止出現(xiàn)閃爍
          SetParent(intPtr, hWndNewParent);      
//將第三方窗體嵌入父容器                    
          Thread.Sleep(
100);                      //略加延時(shí)
          ShowWindow(intPtr, 
3);                 //讓第三方窗體在容器中最大化顯示
          RemoveWindowTitle(intPtr);             
// 去除窗體標(biāo)題
      }


      
/// <summary>
      
/// 去除窗體標(biāo)題
      
/// </summary>
      
/// <param name="vHandle">窗口句柄</param>
      
public static void RemoveWindowTitle(IntPtr vHandle)
      {
          
long style = GetWindowLong(vHandle, -16);
          style &= ~
0x00C00000;
          SetWindowLong(vHandle, 
-16, style);
      }


      
#region API 需要using System.Runtime.InteropServices;

      [
DllImport("user32.dll ", EntryPoint = "SetParent")]
      
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);   //將外部窗體嵌入程序

      [
DllImport("user32.dll")]
      
public static extern IntPtr FindWindow(string lpszClass, string lpszWindow);      //按照窗體類名或窗體標(biāo)題查找窗體

      [
DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
      
private static extern int ShowWindow(IntPtr hwnd, int nCmdShow);                  //設(shè)置窗體屬性

      [
DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
      
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, long dwNewLong);

      [
DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
      
public static extern long GetWindowLong(IntPtr hWnd, int nIndex);

      
#endregion
  }

首先查看最下方的內(nèi)容,以:

 [DllImport("user32.dll ", EntryPoint = "SetParent")]
 
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);  

為例進(jìn)行說明。

這段代碼是在C#中使用平臺(tái)調(diào)用(Platform Invoke,或P/Invoke)來調(diào)用Windows的user32.dll中的一個(gè)函數(shù),名為SetParent。這是一種在.NET中調(diào)用本地方法(通常是C或C++編寫的)的技術(shù)。

[DllImport("user32.dll ", EntryPoint = "SetParent")]:這是一個(gè)屬性,它告訴.NET運(yùn)行時(shí)你要調(diào)用的DLL的名稱(在這里是"user32.dll")和函數(shù)的入口點(diǎn)(在這里是"SetParent")。

private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent):這是函數(shù)的聲明。它告訴.NET運(yùn)行時(shí)函數(shù)的簽名。在這個(gè)例子中,函數(shù)名為SetParent,它接受兩個(gè)IntPtr類型的參數(shù)(hWndChild和hWndNewParent),并返回一個(gè)IntPtr類型的值。

在C#中,extern關(guān)鍵字用于聲明一個(gè)方法,該方法在外部實(shí)現(xiàn),通常是在一個(gè)DLL中。

在該靜態(tài)類中定義了一個(gè)類型為IntPtr的靜態(tài)成員intPtr表示第三方應(yīng)用窗口的句柄。

IntPtr類型介紹

在C#中,IntPtr是一個(gè)特殊的數(shù)據(jù)類型,用于表示指針或句柄。它的大小會(huì)根據(jù)當(dāng)前操作系統(tǒng)的位數(shù)而變化,32位系統(tǒng)下為4字節(jié),64位系統(tǒng)下為8字節(jié)。IntPtr主要用于在托管代碼和非托管代碼之間傳遞指針或句柄,以及處理不確定性大小的內(nèi)存操作。它通常用于與操作系統(tǒng)API進(jìn)行交互、處理內(nèi)存分配和操作句柄等場(chǎng)景。

IntPtr類型提供了一種安全的方式來處理指針,因?yàn)樗峭泄艽a中的數(shù)據(jù)類型,受到.NET運(yùn)行時(shí)的管理和保護(hù)。通過IntPtr,可以在托管代碼中安全地表示非托管資源的地址或句柄,而無需擔(dān)心內(nèi)存泄漏或其他不安全的操作。

使用IntPtr類型時(shí),需要謹(jǐn)慎處理,并遵循.NET平臺(tái)的內(nèi)存管理規(guī)則,以確保代碼的穩(wěn)定性和安全性。通常情況下,IntPtr主要用于與非托管代碼進(jìn)行交互,處理平臺(tái)特定的資源或操作系統(tǒng)API,同時(shí)盡量避免直接使用指針操作,以減少內(nèi)存管理和安全性方面的問題。

這個(gè)靜態(tài)類還有ResizeWindowFindWindowSetParentRemoveWindowTitle方法,等后面用到了再做解釋。

創(chuàng)建一個(gè)winform

winform的設(shè)計(jì)如下所示:

啟動(dòng)軟件按鈕點(diǎn)擊事件處理程序:

 private void button2_Click(object sender, EventArgs e)
 {
     Process.Start(
"程序路徑");
 }

嵌入窗體按鈕點(diǎn)擊事件處理程序:

  private void button1_Click(object sender, EventArgs e)
  {
      Task.Run(() =>
      {               
          
if (WindowManager.FindWindow("Sysplorer [演示版]"))
          {
              
this.Invoke(new Action(() =>
              {
                  WindowManager.SetParent(panel1.Handle, 
"Sysplorer [演示版]");  
              }));
          }
          
else
          {
              MessageBox.Show(
"未能查找到窗體");
          }
      });
  }

在這里就會(huì)遇到一個(gè)問題就是如何確定窗體的標(biāo)題是什么?

可以使用VS中的Spy++工具。

什么是Spy++

Spy++(Spy++)是Microsoft Visual Studio套件中的一個(gè)實(shí)用工具,用于Windows平臺(tái)的應(yīng)用程序開發(fā)和調(diào)試。它允許開發(fā)人員查看和分析正在運(yùn)行的Windows應(yīng)用程序的窗口層次結(jié)構(gòu)、消息流和屬性。

Spy++的主要功能包括:

  1. 窗口層次結(jié)構(gòu):Spy++可以顯示當(dāng)前系統(tǒng)上所有可見和隱藏的窗口,并以層次結(jié)構(gòu)的形式展示它們之間的父子關(guān)系。這使得開發(fā)人員可以快速了解應(yīng)用程序的界面組織和窗口之間的相互作用。
  2. 消息監(jiān)視:Spy++可以捕獲和顯示應(yīng)用程序之間發(fā)送和接收的Windows消息。這對(duì)于調(diào)試和分析應(yīng)用程序的行為非常有用,特別是在處理用戶輸入、事件處理和消息傳遞方面。
  3. 屬性查看:Spy++允許開發(fā)人員查看和修改窗口的屬性,如標(biāo)題、類名、位置、大小、樣式等。這對(duì)于調(diào)試和修改窗口屬性以及理解窗口如何與應(yīng)用程序交互非常有幫助。
  4. 窗口捕獲:Spy++可以捕獲特定窗口的消息,并將其導(dǎo)出為日志文件,以供進(jìn)一步分析和調(diào)試使用。

總之,Spy++是一個(gè)強(qiáng)大的工具,可用于Windows平臺(tái)的應(yīng)用程序開發(fā)和調(diào)試,它提供了豐富的功能來幫助開發(fā)人員理解和調(diào)試復(fù)雜的窗口應(yīng)用程序。

打開之后,如下所示:

可以通過這樣查看窗體名:

查找窗體名

得到了關(guān)于這個(gè)窗體的一些信息,其中紅框部分就是窗體標(biāo)題,如下所示:

找到窗體標(biāo)題之后,看看WindowManager.FindWindow方法:

 public static bool FindWindow(string formName)
 {
     
for (int i = 0; i < 100; i++)
     {
         
//按照窗體標(biāo)題查找窗體
         IntPtr vHandle = FindWindow(
null, formName);
         
if (vHandle == IntPtr.Zero)
         {
             Thread.Sleep(
100);  //100ms查找一次,直到找到,最多查找10s
             
continue;
         }
         
else      //找到返回True
         {
             intPtr = vHandle;
             
return true;
         }
     }
     intPtr = IntPtr.Zero;
     
return false;
 }

再看看 WindowManager.SetParent方法:

  public static void SetParent(IntPtr hWndNewParent, string windowName)
  {
      ShowWindow(intPtr, 
0);                 //先將窗體隱藏,防止出現(xiàn)閃爍
      SetParent(intPtr, hWndNewParent);      
//將第三方窗體嵌入父容器                    
      Thread.Sleep(
100);                      //略加延時(shí)
      ShowWindow(intPtr, 
3);                 //讓第三方窗體在容器中最大化顯示
      RemoveWindowTitle(intPtr);             
// 去除窗體標(biāo)題
  }

現(xiàn)在查看一下效果:

查看效果1

但是我們發(fā)現(xiàn)嵌入的效果不是很好,而且無法隨著窗體的變化而變化,需要再做下修改:

 public Form1()
 {
     InitializeComponent();
     
this.Resize += new EventHandler(Form1_Resize);
 }

注冊(cè)窗體的Resize事件。

事件處理程序:

  private void Form1_Resize(object sender, EventArgs e)
  {
      Task.Run(() =>
      {
          
//第三方窗體句柄不為空
          
if (WindowManager.intPtr != IntPtr.Zero)
          {
              WindowManager.ResizeWindow();
          }
      });
    
  }

現(xiàn)在再來看一下效果:

查看效果2

總結(jié)

以上就是在winform中嵌入第三方窗體的一次實(shí)踐,希望對(duì)你有所幫助。

參考

1、C#完美將第三方窗體嵌入Panel容器(WPF、Winform)_c#嵌入另一個(gè)exe文件到panel控件中,exe打開的子窗口也識(shí)別進(jìn)來-CSDN博客

2、技術(shù)文檔 | Microsoft Learn


該文章在 2024/3/8 15:29:03 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved