php可以调用windowsapi吗_2.如何调用WindowsApi
2.如何調用WindowsApi
在上一篇章節中 很不專業的介紹了一下WindowsApi 如果你本身就知道 那你也壓根不用看 如果你本身就不知道 就算我說的再多 估計你也覺得是多余 所以還是來點實際的
首先 在C#中想要調用那些Api(當然不一定是Windows提供的Api) 你得添加一個引用:
using System.Runtime.InteropServices;
有了這個命名空間 你才能做下一步 這用以MoveWindow函數為例來講解:
如上截圖 如果拉到底部可以看到 這個函數在user32.dll里面 而上一篇說過這個dll在Window的系統路徑下 而MoveWindow函數就在這個dll里面 在調用這個函數前先來看看這個函數的說明 我把chm里面的東西復制出來看:
函數功能:
該函數改變指定窗口的位置和尺寸。對于頂層窗口 位置和尺寸是相對于屏幕的左上角的:
對于子窗口 位置和尺寸是相對于父窗口客戶區的左上角坐標的。
函數原型:
BOOL MoveWindow(HWND hWnd.int x.int y,int nWidth,int nHeight,BOOL BRePaint);
參數:
hWnd:窗口句柄。//看不懂不用知道
x:指定窗口的新位置的左邊界。
Y:指定窗口的新位置的頂部邊界。
nWidth:指定窗口的新的寬度。
nHaight:指定窗口的新的高度。//下面這個看不懂不用看
bRepaint:確定窗口是否被刷新。如果該參數為TRUE 窗口接收一個WM_PAINT消息;
如果參數為FALSE 不發生任何刷新動作。它適用于客戶區 非客戶區(包括標題欄和滾動條)
及由于移動子窗口而露出的父窗口的區域。如果參數為FALSE
應用程序就必須明確地使窗口無效或重畫該窗口和需要刷新的父窗口。
返回值:
如果函數成功 返回值為非零;如果函數失敗 返回值為零。若想獲得更多錯誤信息
請調用GetLastError函數。//GetLastError()也是一個函數 在kernel32中
備注://看不懂不用看
如果bRepaint為TRUE 系統在窗口移動后立即給窗口過程發送WM_PAINT消息
(即由MoveWindow函數調用UPdateWindow函數)
如果bRepaint 為FALSE 系統將WM_PAINT消息放在該窗口的消息隊列中
消息循環只有在派遣完消息隊列中的其他消息時才派遣WM_PAINT消息
MoveWindow給窗口發送WM_WfNOWPOSCHANGING WM_WINDOWPOSCHANGED
WM_MOVE WM_SIZE和WM_NCCALCSIZE消息
速查:
Windows NT:3.1 以上版本:Windows:95 以上版本;Windows CE:1.0 以上版本:
頭文件:winuser.h;庫文件:user32.lib。
函數簽名形式是C++的 淡定習慣就好如果你會C++無所謂 如果不會 沒事如果你用多了之后自然什么意思 第一個參數可能有點看不懂HWND 這個是啥?其實全寫是HandleWindow 一個窗口的句柄 如果你不知道什么是句柄 那就暫時先別管 暫時先理解為是一個窗體的編號 下一篇來說 中間四個不用說 最后一個應該知道把bool 以后像這樣全大寫的東西多了去了C++的習慣 這個值簡單來說 就是當窗體被移動后 是否刷新窗體
現在知道這個函數要怎么用了 那么 現在怎么才能調用到他?平時寫代碼的時候 調用函數基本都是自己寫的 所以知道怎么調用 但是這個函數在一個系統的dll里面 如果平時用C#寫過dll的話你可能會很自然的這樣想?難道要引用dll?然后new一個對象 或者類名打點 那個方法就被點出來了?、、這里恐怕有那么一點不一樣 平時你用C#寫的dll是托管代碼是運行在.Net平臺受.Net平臺管理的 而系統的dll是非托管代碼 是不受.Net平臺約束的 不然一個沒有裝.Net平臺的電腦 那么那些系統的dll豈不是就運行不了了?、
那到這里估計就郁悶了 又不能添加引用 那要怎么調用到這個函數?話不多說 直接上全部代碼上來一看究竟再說
首先隨便你搞一個啥工程 然后添加一個button 就像下面這樣:
然后cs文件全部代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]//表示下面這個函數在user32.dll中
public static extern bool
MoveWindow(IntPtr hWnd, int x, int y, int width, int height, bool bRePaint);
//extern表示外部的 也就是說這個函數在其他地方 而上面的[DllImport(Path)]指定函數的位置
//還有 記得static關鍵字這個是必須的 沒有他 編譯都不通過 然后后面該怎么就怎么
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
MoveWindow(this.Handle/*當前窗體的句柄*/, 100, 100, 200, 200, true);
}
}
}
按照上面方式 就可以調用了 當程序運行的時候點擊button然后 窗體就會移動到你指定的坐標和大小 如果你最后一個參數是false的話可能會出現如下效果:
因為窗體在桌面上的位置信息發生了變化 但是有沒有刷新窗體的后果 當然他不可能一直都是黑的 你把窗體拖出屏幕外 再拖回來 被擋住的地方就會正常 或者最小化再最大化
看到上面的效果可能你不覺的有啥估計你覺得就這個東西 自己也能寫一個一樣功能的函數啊 干嘛搞的那么麻煩比如:
private void MyMoveWindow(
Form frm, int x, int y, int width, int height, bool bRePaint)
{
frm.Left = x;
frm.Top = y;
frm.Width = width;
frm.Height = height;
if (bRePaint) frm.Refresh();//在這里 其實多余了
}
或許你覺和上面的MoveWindow函數沒有區別 在本例中你確實看不到啥明顯的區別 不過我告訴你 區別大了你自己寫的這個 你能移動你自己程序的窗口 外界程序的 比如IE瀏覽器 QQ窗體 計算器窗體什么的 你能移動么?、、假設現在桌面上 有一個QQ聊天窗口 叫你寫個程序點擊button把那個QQ聊天窗體 給我移動到左上角去 這里的MyMoveWindow根本就辦不到 所以在MoveWindow中的第一個參數接收的是一個窗口的句柄 而不是.Net中的Form 如果你要移動那個窗體 只需要將指定窗體的句柄傳進去就是了 至于什么是句柄下一篇來說 這一篇只是演示一下 怎么調用
要注意的是上面[DllImport(...)]這里面不是只能一個string類型的參數 還有很多可選參數:
見得比較多的就是CharSet EntryPoint SetLastError
[DllImport("user32.dll", EntryPoint = "MoveWindow", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool AAA(IntPtr hWnd, int x, int y, int width, int height, bool bRePaint);
比如上面的 如果用了EntryPoint去指定入口的話 那么下面你聲明的函數 就可以用其他你喜歡的名字
CharSet表示這個函數中出現的字符串的編碼用什么形式 注意很多接收字符串參數的函數是有兩個版本的 比如MessageBox有MessageBoxA和messageBoxW兩個版本 MessageBox并不是函數的真正名字在C++中是一個宏定義 根據情況決定使用那個版本的函數 如果著這里你把CharSet設置成Unicode那么在調用函數的時候會自己在你定義的函數名上加上W如果是Ansi則會加上A 好像默認不寫是Auto來著 根據[Windows核心編程]一書說 Windows NT開始由Unicode構建的 所以就算你調用的是A版本的函數 那么系統內部也會將其轉換為Unicode然后進行處理
最后的SetLastError 表示是否設置錯誤號碼 意思就是 并不是每個函數你都能調用成功的有些函數可能因為你參數原因或者其他原因導致函數調用失敗 而失敗了會產生一個錯誤號碼 這個錯誤號碼可以通過GetLastError()函數獲取到 然后根據這個錯誤號 你可以得到一個錯誤信息比如:
[DllImport("kernel32.dll",SetLastError = true)]//MoveWindow略
public static extern int GetLastError();
private void button1_Click(object sender, EventArgs e) {
if (!MoveWindow((IntPtr)10086, 100, 100, 10086, 200, false)) {
//MessageBox.Show(new Win32Exception(Marshal.GetLastWin32Error()).Message);
MessageBox.Show(new Win32Exception(GetLastError()).Message);
}
}
句柄亂輸入一個參數(句柄其實就是一個數字) GetLastError被定義在kernel32中 .Net其實對它有封裝在Marshal類中可以直接調用這個函數Win32Exception也是.Net中自己封裝的 然后運行程序 你會看到如下效果:
一個無效的窗體句柄
有時候想知道為什么調用的函數失敗 就可以通過GetLastError來獲取 別天真的以為 try catch 來捕獲 - -!、、try catch 只會捕獲throw拋出來的異常 而MoveWindow這些函數都啥時候寫的了、、里面沒有throw這種前衛的東西的只有設置錯誤號的代碼、、
好吧這一篇就暫時先到這里、、、因為要怎么調用也確實沒啥要講的 引用命名空間 [DllImport(...)] 然后申明函數 然后調用 沒啥可以多說的、、、
總結
以上是生活随笔為你收集整理的php可以调用windowsapi吗_2.如何调用WindowsApi的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么都不买五年国债?瞬间明白了!
- 下一篇: php 区块链算法_PoW/BFT等5种