1. 程式人生 > >FastReport呼叫程序控制代碼,設定視窗置頂

FastReport呼叫程序控制代碼,設定視窗置頂

應用場景

在使用第三方列印外掛,FastReport時,選擇列印xps,點選列印,彈出檔案另存為對話方塊,但是此對話方塊不會出現在軟體的最前面,而且會一直佔用程序,點選軟體介面出現假死情況。

解決方案

思路
1.設定關閉列印進度視窗,此視窗會一直置頂,而且取消按鈕失效
2.列印前開啟執行緒進行輪詢獲取列印程序
3.根據程序獲取視窗控制代碼,設定視窗位置為最前
4.結束輪詢
實現
1.關閉列印進度視窗
設定ShowProgress為false,具體參考http://blog.csdn.net/yijunwanghaha/article/details/60761033
2.啟動輪詢
據觀察,當彈出檔案另存為視窗時,系統會多出名為splwow64的程序,我們可以通過此程序實現置頂功能,但是由於我們不知道使用者何時點選window系統的列印按鈕,所以需要在程式執行FastReport列印前啟動一個輪詢,獲取程序,實現視窗置頂功能




// 列印是否完成
static bool isPrintCompleted = false;
// 設定視窗置頂
private static void SetWindowTop()
{
	Task.Run(() =>
	{
		// 非同步輪詢實現視窗置頂
		while (!isPrintCompleted)
		{
			// 獲取視窗置頂
			isPrintCompleted = WindowClass.SetWindowTop();
			Thread.Sleep(100);
		}
	});
}
3.根據程序獲取視窗控制代碼,設定視窗位置為最前
首先我們需要獲取程式名為splwow64的程序控制代碼

string processName = "splwow64";
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
	if (process.ProcessName == processName)
	{
		// 根據程序Id獲取程序視窗控制代碼
		IntPtr intPtr = process.MainWindowHandle;
		while (intPtr == IntPtr.Zero) // 這裡要判斷控制代碼為0的情況,只有彈出另存為窗口才會有值
		{
			Thread.Sleep(100);
			// 重新獲取控制代碼
			intPtr = process.MainWindowHandle;
		}
	}
}
獲取到控制代碼後,通過user32.dll介面設定置頂
引用user32函式 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
public static extern IntPtr SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
// 恢復原來視窗,並觸發視窗
public const int SW_RESTORE = 9;
實現
// 顯示視窗
ShowWindow(intPtr, SW_RESTORE);
// 視窗置頂
SetWindowPos(intPtr, -1, 0, 0, 0, 0, 1 | 2);
SetForegroundWindow(intPtr);
整體程式碼
Internal calss PrintClass
{
	// 列印是否完成
	static bool isPrintCompleted = false;
	private static void SetWindowTop()
	{
		Task.Run(() =>
		{
		// 非同步輪詢獲取視窗置頂
		while (!isPrintCompleted)
		{
			// 獲取視窗置頂
			isPrintCompleted = WindowClass.WindowPos();
			Thread.Sleep(100);
		}
		});
	}

	public static void Print()
	{
		isPrintCompleted = false;
		SetWindowTop()
		r.PrintPrepared();
		r.Print();
		isPrintCompleted = true;
	}
}

internal class WindowClass
{
	private static readonly ILog Logger = LogManager.GetLogger(typeof(PrintHelper));
	// 該函式改變一個子視窗,彈出式視窗式頂層視窗的尺寸,位置和Z序
	[DllImport("user32.dll", CharSet = CharSet.Auto)]
	private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
	// 該函式將建立指定視窗的執行緒設定到前臺,並且啟用該視窗
	[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
	public static extern IntPtr SetForegroundWindow(IntPtr hwnd);
	[DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
	public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
	// 恢復原來視窗,並觸發視窗
	public const int SW_RESTORE = 9;
	/// <summary>
	/// 設定列印視窗置頂
	/// </summary>
	/// <returns></returns>
	public static bool SetWindowTop()
	{
	try
	{
		// 程序名稱
		string processName = "splwow64";
		Process[] processes = Process.GetProcesses();
		foreach (Process process in processes)
		{
			if (process.ProcessName == processName)
			{
				// 根據程序Id獲取程序視窗控制代碼
				IntPtr intPtr = process.MainWindowHandle;
				while (intPtr == IntPtr.Zero)
				{
					Thread.Sleep(100);
					// 重新獲取控制代碼
					intPtr = process.MainWindowHandle;
				}
				// 顯示視窗(有時視窗被最小化/隱藏)
				ShowWindow(intPtr, SW_RESTORE);
				// 更改視窗的Zorder,SetWindowPos使之最上
				SetWindowPos(intPtr, -1, 0, 0, 0, 0, 1 | 2);
				// 置頂啟用
				SetForegroundWindow(intPtr);
				return true;
			}
		}
	}
	catch (Exception ex) { Logger.Info(ex.ToString()); }
	return false;
	}
}

應用延伸

此方式可實現多種視窗呈現順序,排序等情況

相關技術資料


相關推薦

FastReport呼叫程序控制設定視窗

應用場景 在使用第三方列印外掛,FastReport時,選擇列印xps,點選列印,彈出檔案另存為對話方塊,但是此對話方塊不會出現在軟體的最前面,而且會一直佔用程序,點選軟體介面出現假死情況。 解決方案 思路1.設定關閉列印進度視窗,此視窗會一直置頂,而且取消按鈕失效2.列印

C# 呼叫win32API 獲取程序控制 有毛用???

private void button2_Click(object sender, EventArgs e) { Process[] ProceddingCon = Process.GetProcesses(); //獲得所有程序 Int

根據程序名取程序ID控制最前端顯示

#include <Psapi.h>(需連結Psapi.Lib) DWORD m_dwTstObjID;HWND m_lmshwnd = NULL; //回撥函式,根據程序ID獲得程序控制代碼 BOOL CALLBACK EnumWindowsProc(HW

MFC 獲取當前視窗控制或者父子視窗控制

父子視窗 在子視窗中,需要用到父視窗的控制代碼: AfxGetMainWnd()->m_hWnd 注:在父視窗中,也可以這麼用來呼叫自己視窗的控制代碼 在子視窗中,需要用到自己視窗的控制代碼 ChildDlg *pChildDlg ; pChildDlg->m_h

獲取ArcMap視窗控制通過WinAPI獲取工作空間中點選要素的系統桌面座標

這裡用了個“桌面座標”,是希望區分一下ArcGis的“螢幕座標”(與之對應的還有一個“地理座標”)。 什麼是“螢幕座標”呢?使用ITool介面的OnMouseDown方法獲取的“x,y”值即是,其原點值在“工作空間”窗體左上角。 什麼是我所稱謂的“工作空間”呢?它是資料編輯區域,用Spy++檢視一下其窗體

C# winform winApi 根據傳入handle 控制獲取 其它視窗如:使用中的子視窗、同級視窗等。

//根據傳入的視窗控制代碼,獲取到同級、頂級、低階的視窗,根據GetWindowCmd 傳入的不同獲取也不同,詳細看GetWindowCmd 類說明 [DllImport("user32.dll", SetLastError = true)] static exter

lsof-檢視程序控制

  [email protected]:~# lsof COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME systemd 1

【2018.05.11】python3.6+selenium 多視窗控制切換

#coding = utf-8 ''' 多視窗控制代碼 獲取 切換 ''' from selenium import webdriver import time driver = webdriver.Chrome() driver.get("http://home.zhiyoo.com/") d

建立執行緒後為什麼關閉了執行緒控制執行緒還是可以執行?

主執行緒只要擁有執行緒控制代碼,事後就可以對執行緒執行某些操作,比如查詢執行緒狀態等等,靠的就是控制代碼,如果沒有控制代碼,系統就無從知道要查的是那個執行緒的狀態。但保持這個控制代碼不關閉,並不是執行緒執行的條件。       &nbs

C++通過程序名獲取程序控制

記錄下一段,比較常用的程式碼。 // 強殺定期刪除程序 void CDogThread::Quit() { // 結束強殺定期刪除程序 HANDLE hProcess = GetProcessHa

程序控制HANDLE獲得程序視窗控制HWND

一個程序可以擁有很多主視窗,也可以不擁有主視窗,所以這樣的函式是不存在的,所幸的是,相反的函式是有的。所以我們可以呼叫EnumWindows來判斷所有的視窗是否屬於這個程序。  typedef struct tagWNDINFO  ​{  ​DWORD dwProc

如何查詢窗體獲取窗體的控制Hwnd FindWindow函式

/*CWnd::FindWindowstatic CWnd* PASCAL FindWindow( LPCTSTR lpszClassName, LPCTSTRlpszWindowNa- me );返回值:標識了具有指定的類名或視窗名的視窗。如果沒有找到這樣的視窗,則返回N

根據程序控制 獲得可執行檔案路徑 的幾種方法

通過程序控制代碼,獲得可執行檔案的路徑,主要有以下幾種方法: 第一種方法:也是最常用的方法,是通過GetModuleFileNameEx函式獲得可執行檔案的模組路徑,這個函式從Windows NT 4.0開始到現在的Vista系統都能使用,向後相容性比較好。 【函式

python得到qq控制並顯示在前臺

# 匯入模組 import win32gui win = win32gui.FindWindow(None, u'張三') # 將視窗調到前臺 win32gui.ShowWindow(win, w

Windows程序控制數限制

GDIProcessHandleQuota項設定GDI控制代碼數量,預設值為2710(16進位制)/10000(10進位制),該值的允許範圍為 256 ~ 16384 ,將其調整為大於預設的10000的值。如果您的系統配置了2G或更多內容,不妨將其設定為允許的最大值 16384(10進位制);USERProc

在java程式中如何能獲取到另一個程式的windows控制又如何使用這個控制向這個視窗傳送訊息

import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.platform.win32.W

[Delphi]如何通過程序控制判斷該程序是否已退出?

GetExitCodeProcess    看似可以,但是仔細看MSDN,有這麼一句話:“Warning  If a process happens to return STILL_ACTIVE (259) as an error code, applications th

模組控制程序控制的區別?

         在WINDOWS下,模組指的是EXE和DLL等資料載入到記憶體中的影像,模組控制代碼又是比較特殊的,它跟一般的控制代碼不一樣,模組控制代碼指向的就是EXE和DLL等的在記憶體的位置(就是指向它們的資料起始位置);程序控制代碼只是WINDOWS用來標識某個程

根據檔案控制獲取檔名(轉載)

#include <windows.h>#include <stdio.h>#include <tchar.h>#include <string.h>#include <psapi.h>#define BUFSIZE

通過程序名得到程序控制(tlhelp的方法)(ring3)

這個是因為我在網上搜只搜到列舉控制代碼的感覺很不方便,所以寫下這個僅供參考 HANDLE sub2(WCHAR* processname) {PROCESSENTRY32 pe32 = { 0 };// 在本程序中拍一個所有程序的快照HANDLE hModuleSnap