亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#?WPF調(diào)用QT窗口的方法

 更新時(shí)間:2023年02月09日 10:58:01   作者:路遙芝麻力  
本文主要介紹了C#?WPF調(diào)用QT窗口的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

WPF 程序內(nèi)嵌 QT 窗體

1、目標(biāo):將QT控件(Qwiget)(或則基于QWiget的控件)(或則任何第三方C++控件)封裝為WPF可調(diào)用的用戶控件。簡(jiǎn)單來(lái)說(shuō)就是WPF程序調(diào)用QT窗體控件。

本人需要使用3D控件顯示一些3D點(diǎn)云等功能。但是又找不到好的兼容WPF的控件(大點(diǎn)云和效率原因)。最后選用CloudConpare作為點(diǎn)云顯示控件(該控件基于QT的QWiget)。
目前網(wǎng)絡(luò)上這方面的內(nèi)容并不是太多,而且多數(shù)還都是雷同。
個(gè)人感覺(jué) C# 跨平臺(tái)并不是太友好(或則我水平不夠),特別是3D方面。

本人對(duì)QT不是很熟悉,但是CloudCompare是基于QT寫的界面,所以沒(méi)辦法只能慢慢摸索,好在以前有MFC編程經(jīng)驗(yàn),對(duì)C++還有點(diǎn)積累,過(guò)程中關(guān)于配置方面的問(wèn)題我盡量詳細(xì)說(shuō)明(對(duì)于C#編程者來(lái)說(shuō)還是挺惡心的,QT的配置和CloudCompare的配置挺麻煩的)。

實(shí)現(xiàn)過(guò)程如下(可能需要稍微有點(diǎn)基礎(chǔ)才能看懂,我認(rèn)為有意思的會(huì)寫多點(diǎn) ,寫的不是太系統(tǒng)),可能有點(diǎn)亂,有點(diǎn)啰嗦,想到哪里寫到哪,見(jiàn)諒。

心路:
一開(kāi)始查詢資料想通過(guò)中間庫(kù) CLR鏈接C#和C++,簡(jiǎn)單demo也測(cè)試OK,后期碰到控件句柄傳遞問(wèn)題調(diào)試也比較麻煩,遂放棄(現(xiàn)在想來(lái)應(yīng)該也是可以實(shí)現(xiàn)的)。
最終直接使用 C形式函數(shù)導(dǎo)出 的形式來(lái)創(chuàng)建DLL,也挺方便的。專業(yè)點(diǎn)叫P/Invoke(推薦大家一本書(shū)《精通.NET互操作:P/Invoke,C++Interop和COM Interop》)。

大概邏輯:WPF控件句柄–>傳遞給C++生成的QT庫(kù)–>動(dòng)態(tài)庫(kù)根據(jù)傳遞過(guò)來(lái)的句柄創(chuàng)建一個(gè)QWiget–>根據(jù)這個(gè)QWiget生成一個(gè)GLWindow(真實(shí)的3D顯示窗體)–>C#保存這個(gè)指針?lè)奖阆麓卧L問(wèn)。
數(shù)據(jù)傳邏輯:主要是C#這邊發(fā)給C++ Dll數(shù)據(jù),主要涉及到托管和非托管資源的問(wèn)題、字節(jié)對(duì)齊等。

實(shí)現(xiàn)過(guò)程中可能有幾個(gè)主要問(wèn)題:
1、C#和C++混合編程;
2、QT程序(QT事件循環(huán)QApplication.exec())如何封裝為Dll;
3、QT的UI線程和WPF的UI線程沖突問(wèn)題(目前本人也沒(méi)完全弄懂,歡迎溝通);

工具:VS2019(Qt Visual Studio Tool 2.7.0)、QT5.14.2、CloudCompare2.6.12源碼。。。。

上代碼:

1、創(chuàng)建一個(gè)VS-QT的動(dòng)態(tài)庫(kù)。

選擇Qtwidgets application,然后修改配置生成為dll。網(wǎng)上資料很多,不詳細(xì)描述(大概流程:修改輸出類型為dll,將沒(méi)必要的文件刪除即可(Main)(所有文件都可以刪除,然后新增一個(gè)QtWidgets class也行))。如下:

我們這里界面就不需要設(shè)置(因?yàn)槲覀儾皇侵苯佑肣T界面),只需要一個(gè)空白的Qwidget。(同志們只需要用Qwiget就可以在這里繪制了)
右鍵 編譯這個(gè).ui文件。會(huì)生成一個(gè)ui_xxxx.h文件。添加這個(gè)文件到項(xiàng)目中,(可能在生成目錄的uic文件夾下,如有必要還需要將這個(gè)文件路徑加到包含目錄中。若是不添加可能會(huì)生成失敗)。
首次生成失敗很正常,各種QT環(huán)境問(wèn)題。不要心急。

這里我們就獲得了一個(gè)帶QT的界面的C++庫(kù)。

2、WPF中引用它:

若是你們用的是Winform,那就比較方便了,直接拿到控件句柄(我這里使用的panel控件)傳遞給動(dòng)態(tài)庫(kù)就行了。
若是你用的是WPF,會(huì)麻煩一點(diǎn)(因?yàn)閃PF控件獲取不到“控件”句柄),這里在下試了很多,獲得的都是窗體句柄。所以只能使用WindowsFormsHost。上代碼

這里是本人在WPF創(chuàng)建了一個(gè)用戶控件的xaml文件。上代碼

public partial class Window3DControl : UserControl
    {
        public Window3DControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 3D顯示 窗口
        /// </summary>
        public Window3DControl_Net Control3D = new Window3DControl_Net();


        /// <summary>
        /// 創(chuàng)建真實(shí)的3D窗體,GlWindow
        /// </summary>
        /// <returns></returns>
        public bool Create3DWindow()
        {
            int res = Control3D.Creat3DWindow_Net((long)Panel3D.Handle, Panel3D.Width, Panel3D.Height);

            return res == 0;
        }

        /// <summary>
        /// 控件發(fā)生變化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window3DControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if(Control3D.IsInitWindow)
            {
                int width = (int)(WindowForm3D.ActualWidth * 1.25);
                int Heigth = (int)(WindowForm3D.ActualHeight * 1.25);
                int res = Control3D.WindowSizeChanged_Net(width, Heigth);
            }
        }

        /// <summary>
        /// 3D窗體切換
        /// </summary>
        public void ChangeWindowModel()
        {
            if(WindowForm3D.Visibility == Visibility.Visible)
            {
                WindowForm3D.Visibility = Visibility.Collapsed;
                Button2D.Visibility = Visibility.Visible;
            }
            else
            {
                WindowForm3D.Visibility = Visibility.Visible;
                Button2D.Visibility = Visibility.Collapsed;
            }
        }

    }

上面是用戶控件的代碼部分。也很簡(jiǎn)單只有幾個(gè)簡(jiǎn)單功能。其中Control3D對(duì)象是我封裝的一個(gè)調(diào)用動(dòng)態(tài)庫(kù)的接口類(只是封裝了一層),功能上直接調(diào)用C形式的函數(shù)接口也是可以的。上代碼

這里是封裝的3D對(duì)象的部分接口,C#這邊就很簡(jiǎn)單了,都封裝成用戶控件了,那不是想怎么玩怎么玩。(關(guān)于C#定義函數(shù)接口就不描述了,C++那邊導(dǎo)出函數(shù)接口也不描述了)。上代碼

還有一點(diǎn)很重要(我感覺(jué))如何顯示QT窗口正好覆蓋WPF中句柄對(duì)應(yīng)的控件(可能會(huì)碰到直接顯示QT窗口在主界面的左上角)。有兩步很重要,通過(guò)如上圖,可以看到我們將控件句柄和對(duì)應(yīng)的尺寸傳遞過(guò)去,并且將生成的QT窗口的實(shí)例對(duì)應(yīng)的指針傳回來(lái),為了下次能夠直接拿到這個(gè)QT窗口??梢钥聪挛业膭?chuàng)建窗口函數(shù)是如何實(shí)現(xiàn)的,上代碼

圖中標(biāo)記部分,很重要 。(忘記從哪個(gè)大神哪里偷學(xué)來(lái)的)
另外為了C# 那邊能拿到C++這邊的對(duì)象指針。使用了二級(jí)指針概念(這個(gè)不太好解釋,要自己細(xì)細(xì)理解,這個(gè)不是偷學(xué)的,在下耗盡腦子想的)。
還有一個(gè)問(wèn)題QT事件循環(huán),(若是你調(diào)用過(guò)QT的dll,可能就會(huì)發(fā)現(xiàn)這個(gè)問(wèn)題),我這邊解決辦法就是,在程序開(kāi)始(你認(rèn)為的合適的地方)調(diào)用InitQTEnvironment接口,上代碼。

#include "qmfcapp.h"
int InitQtEnvironment()
{
	try
	{
		//if (QApplication::instance() == NULL)
		//{
		//	int argc = 0;
		//	g_app = new QApplication(argc, NULL);
		//	//QWidget* GroudWidget = new QWidget(NULL);
		//	//GroudWidget->setGeometry(0, 0,0, 1);//設(shè)置widget的大小
		//	//GroudWidget->showMinimized();
		//	//g_app->exec();
		//}
		if (QApplication::instance() == NULL)
		{
			return  QMfcApp::pluginInstance();
		}
		return 0;
	}
	catch(QException ex )
	{
		printf("Init Error");

		printf(ex.what());
		return -1;
	}
	
}

兩種方式都行,目的是創(chuàng)建出來(lái)QApplication這個(gè)靜態(tài)對(duì)象即可。(其中QMfcApp是偷學(xué)某個(gè)大佬)。
OK,其實(shí)到這里整個(gè)流程已經(jīng)基本打通了,路走通了,其余的都好辦了。
關(guān)于數(shù)據(jù)傳遞問(wèn)題,這里也說(shuō)一下。C#和C++的基礎(chǔ)數(shù)據(jù)類型在內(nèi)存中占位不盡相同,有興趣可以看下對(duì)照表(網(wǎng)上一大堆)。
若是使用CLR包裝C++dll,可以解決類型不一致問(wèn)題(個(gè)人感覺(jué)CLR就是一次形參類型轉(zhuǎn)換而已,可能是我太淺薄了)。
若是我們這種直接調(diào)用C形式的函數(shù)接口。需要傳遞參數(shù)需要注意幾點(diǎn)。
1、基礎(chǔ)類型也需要注意內(nèi)存占位是否一致。
2、結(jié)構(gòu)體類型,需要考慮字節(jié)對(duì)齊和托管資源問(wèn)題。思路:兩邊定義相同類型的結(jié)構(gòu)體。直接傳遞結(jié)構(gòu)體指針(首地址)本質(zhì)上還是內(nèi)存要一樣,不能亂。先上代碼(C++)

C#中數(shù)據(jù)結(jié)構(gòu)

![](https://img-blog.csdnimg.cn/62431497e42241c18b2f6bb4bd98f5a3.jpg

仔細(xì)對(duì)比(字節(jié)對(duì)齊,還要考慮編譯器可能優(yōu)化)。
數(shù)組必須確定傳遞長(zhǎng)度(內(nèi)存分配才能連續(xù)),并且C#這邊申請(qǐng)的內(nèi)存必須是非托管內(nèi)存(使用Marsh申請(qǐng))。關(guān)于C++傳遞數(shù)據(jù)到C#,上文也提到了二級(jí)指針,基礎(chǔ)類型或確定內(nèi)存長(zhǎng)度的可以直接傳遞,不確定的對(duì)象使用二級(jí)指針。關(guān)于內(nèi)存釋放問(wèn)題。大家可以網(wǎng)上找下,有幾種常用方法,此處不贅述。

按照慣例,上效果圖。

遺留問(wèn)題:
玩過(guò)WPF的都知道,WPF有一個(gè)隱藏的UI線程,我們的屬性綁定控件和刷線界面都是
這個(gè)線程來(lái)更新的。QT也有一個(gè)類似的界面線程。因?yàn)槲疫@邊主程序是WPF,QWiget只是作為一個(gè)控件來(lái)用的。
目前發(fā)現(xiàn)他們兩個(gè)界面線程會(huì)出現(xiàn)搶資源情況(我也是猜的,因?yàn)槌霈F(xiàn)WPF的源已經(jīng)改變了但是目標(biāo)控件上沒(méi)有刷新(及時(shí)刷新)的現(xiàn)象)。各位大佬若有這方面的見(jiàn)解,請(qǐng)一定聯(lián)系我。抱拳?。?!

到此這篇關(guān)于C# WPF調(diào)用QT窗口的方法的文章就介紹到這了,更多相關(guān)C# WPF調(diào)用QT窗口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn)

    C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn)

    這篇文章主要介紹了C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 詳解C#中Helper類的使用

    詳解C#中Helper類的使用

    項(xiàng)目中用戶頻繁訪問(wèn)數(shù)據(jù)庫(kù)會(huì)導(dǎo)致程序的卡頓,甚至堵塞。使用緩存可以有效的降低用戶訪問(wèn)數(shù)據(jù)庫(kù)的頻次,有效的減少并發(fā)的壓力。而helper類對(duì)緩存有了封裝,本文展示了封裝的示例代碼,需要的可以參考一下
    2022-04-04
  • C#中的多線程小試牛刀

    C#中的多線程小試牛刀

    這篇文章主要給大家介紹了關(guān)于C#中多線程的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • C#中Byte[]和String之間轉(zhuǎn)換的方法

    C#中Byte[]和String之間轉(zhuǎn)換的方法

    很多朋友不清楚如何在Byte[]和String之間進(jìn)行轉(zhuǎn)換?下面小編給大家?guī)?lái)了byte與string轉(zhuǎn)換的方法,感興趣的朋友參考下吧
    2016-08-08
  • c# 插入數(shù)據(jù)效率測(cè)試(mongodb)

    c# 插入數(shù)據(jù)效率測(cè)試(mongodb)

    這篇文章主要介紹了c# 插入數(shù)據(jù)效率測(cè)試(mongodb),插入的速度要比Mysql和sqlserver都要快需要的朋友可以參考下
    2018-03-03
  • Unity實(shí)現(xiàn)截圖功能

    Unity實(shí)現(xiàn)截圖功能

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)截圖功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C#/VB.NET實(shí)現(xiàn)將Html轉(zhuǎn)為Word的示例詳解

    C#/VB.NET實(shí)現(xiàn)將Html轉(zhuǎn)為Word的示例詳解

    本文分享以C#程序代碼為例,實(shí)現(xiàn)將Html文件轉(zhuǎn)換Word文檔的方法(附VB.NET代碼)。在實(shí)際轉(zhuǎn)換場(chǎng)景中可參考本文的方法,感興趣的可以了解一下
    2022-07-07
  • 如何使用LinQ To Object把數(shù)組或DataTable中的數(shù)據(jù)進(jìn)行向上匯總

    如何使用LinQ To Object把數(shù)組或DataTable中的數(shù)據(jù)進(jìn)行向上匯總

    這篇文章主要介紹了如何使用LinQ To Object把數(shù)組或DataTable中的數(shù)據(jù)進(jìn)行向上匯總,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C#中的const和readonly關(guān)鍵字詳解

    C#中的const和readonly關(guān)鍵字詳解

    本文詳細(xì)講解了C#中的const和readonly關(guān)鍵字,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 使用C#連接SQL?Server的詳細(xì)圖文教程

    使用C#連接SQL?Server的詳細(xì)圖文教程

    初學(xué)者學(xué)習(xí)上位機(jī)開(kāi)發(fā)遇到數(shù)據(jù)庫(kù)連接不上,是很常見(jiàn)的情況,可能會(huì)以各種形式呈現(xiàn)出來(lái),下面這篇文章主要給大家介紹了關(guān)于使用C#連接SQL?Server的詳細(xì)圖文教程,需要的朋友可以參考下
    2023-02-02

最新評(píng)論