???? 我之前是一個(gè)只會(huì)編寫數(shù)值計(jì)算的程序的OIer,但我并不甘于這種現(xiàn)狀,于是 我 編寫了我 的第一個(gè)使用API函數(shù)的C++程序 , 開發(fā)平臺(tái)是VS2012 :

// ConsoleApplication.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。 // #include <stdio.h> #include " stdafx.h " #include <Windows.h> int _tmain( int argc, _TCHAR* argv[]) { HWND wnd; wnd =FindWindowA(NULL, " 無標(biāo)題 - 記事本 " ); SendMessage(wnd,WM_CLOSE, 0 , 0 ); system( " pause " ); return 0 ; }
????之前有在看谷夕寫的HACK編程實(shí)例精講,第一節(jié)有介紹API函數(shù),他的書上用的是hDesk=OpenDesktop(lpszDesktop,0,FALSE,DESKTOP_ENUMERATE);在這之前我連如何調(diào)用API函數(shù)都不知道,嘗試過#include<stdafx.h>等等亂七八糟的東西,結(jié)果都不行.后來百度了一下,才發(fā)現(xiàn)原來是要加#include<windows.h>
????明白如何才能可以調(diào)用API函數(shù)之后,嘗試使用書上介紹的OpenDesktop函數(shù),因?yàn)槲沂裁炊疾恢?于是程序我就這么寫了:

// ConsoleApplication.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。 // #include <stdio.h> #include " stdafx.h " #include <Windows.h> int _tmain( int argc, _TCHAR* argv[]) { int hDesk=OpenDesktop(lpszDesktop, 0 ,FALSE,DESKTOP_ENUMERATE); system( " pause " ); return 0 ; }
?結(jié)果是關(guān)于lpszDesktop發(fā)生了某種我理解不了的錯(cuò)誤.于是再次百度API函數(shù)應(yīng)用實(shí)例,就找到了第一個(gè)程序.
一開始仍然編譯不過,編譯器提示錯(cuò)誤.
我也不知道LPCWSTR是 什么 ,不過看網(wǎng)上關(guān)于FindWindow函數(shù)的介紹是這么說的: 函數(shù)的定義:HWND?WINAPI?FindWindow(LPCSTR?lpClassName?,LPCSTR?lpWindowName); 這上邊居然是LPCSTR,于是我試了試類似的函數(shù),發(fā)現(xiàn)FindWindowA函數(shù)上是LPCWSTR,于是改成FindWindowA終于編譯過了,實(shí)現(xiàn)的功能就是把名為無標(biāo)題?-?記事本的窗口關(guān)閉.
我學(xué)習(xí)這類東西一向喜歡先弄出來一個(gè)能正確運(yùn)行的樣例,然后再弄明白有問題的地方,這次也不例外.關(guān)于這個(gè)程序我主要有這幾個(gè)方面不太明白:1.句柄是個(gè)啥玩意;2.LPCSTR和LPCWSTR又是什么東西;3.FindWindow函數(shù)還有啥其他調(diào)用方式.
先搞明白句柄是什么東西,當(dāng)然還要靠百度.
句柄 , 是整個(gè)windows編程的基礎(chǔ) . 一個(gè)句柄是指使用的一個(gè)唯一的整數(shù)值 , 即一個(gè)四字節(jié)長(zhǎng)的數(shù)值 , 來標(biāo)志應(yīng)用程序中的不同對(duì)象和同類對(duì)象中的不同的實(shí)例 , 諸如 , 一個(gè)窗口 , 按鈕 , 圖標(biāo) , 滾動(dòng)條 , 輸出設(shè)備 , 控件或者文件等 . 應(yīng)用程序能夠通過句柄訪問相應(yīng)的對(duì)象的信息 , 但是句柄不是一個(gè) 指針, 程序不能利用句柄來直接閱讀文件中的信息 . 如果句柄不用在I/O文件中 , 它是毫無用處的 . 句柄是windows用來標(biāo)志應(yīng)用程序中建立的或是使用的唯一整數(shù) , windows使用了大量的句柄來標(biāo)志很多對(duì)象 .
關(guān)于句柄我是這樣理解的:它有點(diǎn)類似于算法中的哈希值,對(duì)于一個(gè)對(duì)象系統(tǒng)分配給它一個(gè)唯一的值來標(biāo)記存儲(chǔ)該對(duì)象變動(dòng)情況的位置.
LPCWSTR是一個(gè)指向unicode編碼字符串的32位指針 , 所指向字符串是wchar型 , 而不是char型 .
原來LPCWSTR是 unicode 字符串指針,那unicode又是什么東西呢(請(qǐng)?jiān)徫业臒o知,我真的連 unicode 是啥都不知道)?看過 這篇文章 之后才大概有了個(gè)了解.比較特別之處在于定義unicode字符串時(shí)要在左邊加一個(gè)L,就像這樣:
wchar_t wStr[] = L"中文";
除此之外,我又了解到在VS2005以后,編碼方式默認(rèn)為unicode,部分函數(shù)在使用時(shí)默認(rèn)調(diào)用unicode方式(函數(shù)名加W),而非ansi方式(函數(shù)名加A).之前那個(gè)程序由于"無標(biāo)題 - 記事本"是編碼為ansi的字符串,所以調(diào)用默認(rèn)的unicode方式時(shí)出現(xiàn)錯(cuò)誤,而使用FindWindowA之后采用ansi方式才編譯通過.然后我又把剛才的調(diào)用方式改為wnd=FindWindow(NULL,L"無標(biāo)題 - 記事本");終于編譯通過.wchar_t的輸出:一般說來有兩種方式,一個(gè)是wcout,還有是wprintf()之類的函數(shù),悲劇的是無論哪種方法都沒編譯過.后來看一個(gè)博客里說要在main函數(shù)里加上_tsetlocale(LC_ALL, L"CHS");于是wcout能用了,wprintf仍然不行.先不管它,繼續(xù)往后看.
第二個(gè)API函數(shù):SendMessage函數(shù).SendMessage函數(shù)能向指定句柄所對(duì)應(yīng)的對(duì)象發(fā)送信息,示例程序:

POINT curpos; while ( 1 ) { GetCursorPos( & curpos); HWND hWnd = WindowFromPoint(curpos); SendMessage(hWnd,WM_CHAR,WPARAM( ' g ' ), 0 ); Sleep( 300 ); }
該程序?qū)崿F(xiàn)的功能是向鼠標(biāo)所指向的編輯窗口輸入g.
POINT就是表示坐標(biāo)的數(shù)據(jù)類型.GetCursorPos(&curpos)表示取當(dāng)前鼠標(biāo)的坐標(biāo).WindowFromPoint(curpos)表示獲得curpos處的對(duì)象的句柄.
WM_CHAR表示輸出字符.
接著,我想寫一個(gè)程序給自己發(fā)送標(biāo)準(zhǔn)輸入數(shù)據(jù):

while ( 1 ) { GetCursorPos( & curpos); HWND hWnd = WindowFromPoint(curpos); SendMessage(hWnd,WM_CHAR,WPARAM( ' g ' ), 0 ); SendMessage(hWnd,WM_CHAR,WPARAM( ' \r ' ), 0 ); Sleep( 300 ); char ch; cerr << " waiting for reading " << endl; cin >> ch; if (ch== ' g ' ) break ; }
意思就是當(dāng)通過SendMessage函數(shù)向程序窗口發(fā)送一個(gè)g,如果被成功讀入就跳出循環(huán),一開始我第2個(gè)SendMessage里發(fā)送的是 ’ \n ’ ,結(jié)果沒法觸發(fā)讀入,接著改成 ’ \0 ’ ,還是不行,又改成 ’ \r ’ ,這次終于成功了,原來回車鍵輸入的是一個(gè) ’ \r ’ 啊,之前一直以為是 ’ \n ’ 呢...
再往下又看到一個(gè)更有趣的:模擬鼠標(biāo)動(dòng)作

void RightClick(HWND wnd) { SendMessage(wnd,WM_RBUTTONDOWN, 0 , 0 ); Sleep( 100 ); SendMessage(wnd,WM_RBUTTONUP, 0 , 0 ); }
其中,WM_RBUTTONDOWN表示鼠標(biāo)右鍵按下,WM_RBUTTONUP表示鼠標(biāo)右鍵抬起.測(cè)試了一下運(yùn)行沒什么大問題,不過看起開必須等我再單擊一下鼠標(biāo)左鍵才能讓程序繼續(xù)執(zhí)行.這樣感覺用起來很不舒服,而且也沒有什么應(yīng)用價(jià)值.后來有看到專門有一個(gè)函數(shù)mouse_event能模擬鼠標(biāo)的點(diǎn)擊.關(guān)于這個(gè)函數(shù)的詳細(xì)信息我看不太懂,就只用了一個(gè)最簡(jiǎn)單的應(yīng)用:鼠標(biāo)左擊.再結(jié)合剛才的SendMessage函數(shù),做了一個(gè)刷屏軟件,雖然功能很弱,但做完的時(shí)候還是感覺很激動(dòng).弱弱地貼一下我的代碼:

// 刷屏軟件.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。 // #include<math.h> #include <stdio.h> #include <stdlib.h> #include < string .h> #include " stdafx.h " #include <Windows.h> #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <locale> #include <cstring> using namespace std; void Home_Page() { printf( " 1.使用說明.\n " ); printf( " 2.開始運(yùn)行.\n " ); printf( " 3.退出程序.\n " ); } void Left_Click() { mouse_event(MOUSEEVENTF_LEFTDOWN, 0 , 0 , 0 , 0 ); mouse_event(MOUSEEVENTF_LEFTUP, 0 , 0 , 0 , 0 ); } void Software_Description() { printf( " 本軟件使用很簡(jiǎn)單,只要按提示一步一步操作即可.\n " ); printf( " 也許有些使用者覺得軟件寫的太腦殘,請(qǐng)?jiān)?我剛接觸這方面,這個(gè)程序純屬練手.\n " ); printf( " 特別提示:由于作者水平問題,請(qǐng)您在所有信息發(fā)送完成之前不要移動(dòng)您的鼠標(biāo),否則可能會(huì)產(chǎn)生難以預(yù)料的結(jié)果.\n " ); printf( " 同樣由于作者的水平問題,目前只支持英文文本(Ansi字符集)的發(fā)送.\n " ); printf( " 如果發(fā)送內(nèi)容中包含多個(gè)單詞,建議用下劃線\'_\'連接\n " ); printf( " 聯(lián)系作者:winifred.oier@gmail.com\n " ); system( " pause " ); } void Main_Program() { printf( " 請(qǐng)輸入您希望發(fā)送的內(nèi)容(一行):\n " ); string TexttobeSend; cin >> TexttobeSend; printf( " 請(qǐng)輸入您希望每隔多長(zhǎng)時(shí)間發(fā)送一次(單位:毫秒):\n " ); int DelayTime; cin >> DelayTime; printf( " 您希望將該信息發(fā)送多少遍:\n " ); int SendTime; cin >> SendTime; printf( " 請(qǐng)?jiān)?秒內(nèi)將鼠標(biāo)放在發(fā)送信息的編輯框里\n " ); HWND InputBox; POINT curpos; Sleep( 5000 ); GetCursorPos( & curpos); InputBox = WindowFromPoint(curpos); cerr << " The Input Box has been engaged " << endl; printf( " 請(qǐng)?jiān)?秒內(nèi)將鼠標(biāo)放在發(fā)送按鈕上.再次提示:由于作者水平太爛,執(zhí)行完之前千萬別亂動(dòng)鼠標(biāo).\n " ); Sleep( 5000 ); for ( int i= 1 ;i<=SendTime;i++ ) { for ( int j= 0 ;j<TexttobeSend.length();j++ ) SendMessage(InputBox,WM_CHAR,WPARAM(TexttobeSend[j]), 0 ); Left_Click(); Sleep(DelayTime); } } int _tmain( int argc, _TCHAR* argv[]) { int Command_Code; while ( true ) { Home_Page(); cin >> Command_Code; switch (Command_Code) { case 1 : Software_Description(); break ; case 2 : Main_Program(); break ; case 3 : return 0 ; } system( " cls " ); } return 0 ; }
不過在寫代碼的時(shí)候發(fā)現(xiàn)一個(gè)問題,不同的頭文件包含順序可能會(huì)影響能否編譯,還有就是編譯出來的可執(zhí)行文件只能在我的電腦上執(zhí)行,我用同學(xué)的電腦測(cè)試發(fā)現(xiàn)缺少一個(gè)MS...的動(dòng)態(tài)鏈接庫,不明白為什么.
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
