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

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

【C#】在winform中如何實現嵌入第三方軟件窗體

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

相關win32api的學習

SetParent

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

語法:

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

參數:

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

相關解釋:

什么是句柄?

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

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

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

句柄的使用可以提高程序的安全性和效率。它們允許程序通過句柄而不是直接訪問資源,從而隱藏底層實現細節(jié)并提供一種統(tǒng)一的接口。此外,句柄還可以用于實現資源的共享和保護,通過對句柄的權限管理來控制對資源的訪問。

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

FindWindow

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

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

若要從指定的子窗口開始搜索子窗口,請使用 FindWindowEx 函數。

語法:

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

參數:

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

ShowWindow

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

語法:

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

參數:

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

nCmdShow不同值與含義:



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

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

為了便于進行相關的操作,創(chuàng)建一個靜態(tài)類:

  public static class WindowManager
  {
      
public static IntPtr intPtr;         //第三方應用窗口的句柄

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

      
/// <summary>
      
/// 循環(huán)查找第三方窗體
      
/// </summary>
      
/// <returns></returns>
      
public static bool FindWindow(string formName)
      {
          
for (int i = 0; i < 100; i++)
          {
              
//按照窗口標題查找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>
      
/// 將第三方窗體嵌入到容器內
      
/// </summary>
      
/// <param name="hWndNewParent">父容器句柄</param>
      
/// <param name="windowName">窗體名</param>
      
public static void SetParent(IntPtr hWndNewParent, string windowName)
      {
          ShowWindow(intPtr, 
0);                 //先將窗體隱藏,防止出現閃爍
          SetParent(intPtr, hWndNewParent);      
//將第三方窗體嵌入父容器                    
          Thread.Sleep(
100);                      //略加延時
          ShowWindow(intPtr, 
3);                 //讓第三方窗體在容器中最大化顯示
          RemoveWindowTitle(intPtr);             
// 去除窗體標題
      }


      
/// <summary>
      
/// 去除窗體標題
      
/// </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);      //按照窗體類名或窗體標題查找窗體

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

      [
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
  }

首先查看最下方的內容,以:

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

為例進行說明。

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

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

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

在C#中,extern關鍵字用于聲明一個方法,該方法在外部實現,通常是在一個DLL中。

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

IntPtr類型介紹

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

IntPtr類型提供了一種安全的方式來處理指針,因為它是托管代碼中的數據類型,受到.NET運行時的管理和保護。通過IntPtr,可以在托管代碼中安全地表示非托管資源的地址或句柄,而無需擔心內存泄漏或其他不安全的操作。

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

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

創(chuàng)建一個winform

winform的設計如下所示:

啟動軟件按鈕點擊事件處理程序:

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

嵌入窗體按鈕點擊事件處理程序:

  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(
"未能查找到窗體");
          }
      });
  }

在這里就會遇到一個問題就是如何確定窗體的標題是什么?

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

什么是Spy++

Spy++(Spy++)是Microsoft Visual Studio套件中的一個實用工具,用于Windows平臺的應用程序開發(fā)和調試。它允許開發(fā)人員查看和分析正在運行的Windows應用程序的窗口層次結構、消息流和屬性。

Spy++的主要功能包括:

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

總之,Spy++是一個強大的工具,可用于Windows平臺的應用程序開發(fā)和調試,它提供了豐富的功能來幫助開發(fā)人員理解和調試復雜的窗口應用程序。

打開之后,如下所示:

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

查找窗體名

得到了關于這個窗體的一些信息,其中紅框部分就是窗體標題,如下所示:

找到窗體標題之后,看看WindowManager.FindWindow方法:

 public static bool FindWindow(string formName)
 {
     
for (int i = 0; i < 100; i++)
     {
         
//按照窗體標題查找窗體
         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);                 //先將窗體隱藏,防止出現閃爍
      SetParent(intPtr, hWndNewParent);      
//將第三方窗體嵌入父容器                    
      Thread.Sleep(
100);                      //略加延時
      ShowWindow(intPtr, 
3);                 //讓第三方窗體在容器中最大化顯示
      RemoveWindowTitle(intPtr);             
// 去除窗體標題
  }

現在查看一下效果:

查看效果1

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

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

注冊窗體的Resize事件。

事件處理程序:

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

現在再來看一下效果:

查看效果2

總結

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

參考

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

2、技術文檔 | Microsoft Learn


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