C語言的基本語法我是不打算再提了,很多C語言編程的書,就是將壹些基本的數據類型、數據結構、語法,然後就是壹些數值
計算的實例,大多數都是雷同的,難免有抄襲之嫌,而且頁沒有多少實用價值。
本書以實用實例作為編程指導,指引大家編寫真正實用的程序。了解到大家對黑客程序、病毒、窗口類程序比較感興趣,因此我就拿這些實例進行講解。基於大家基本都用Windows XP SP3,我也就在這個系統上把程序調試成功後再給大家講解。編程環境,我還是喜歡VisualC++ 6.0
本書計劃從四個大的方面來講,這四個方面是:窗口類、文件操作類、網絡類、數據庫類。
都是時下流行的編程必備技術,也是軟件開發者,必須掌握的技術。中間以實例講解,逐步學習,相信大家看完後會有很大的提高的。
第壹章窗口類程序的編寫
這壹章就先來講解下窗口類程序的編寫。因為現在程序沒有界面,就像人沒有臉面壹樣,而且好的界面更能吸引人。從基本的界面開始,相信能給大家指明出壹條路的,使大家很容易地掌握窗口序的編寫。其實界面設計利用VC 6.0 的MFC,很容易地制作出來。這裏從底層開始寫代碼來寫界面程序,使大家知道壹些底層的東西,為以後學習打下好的基礎,相信您學了這些,再用VC 的MFC會得心應手的。
1.1
用 C 寫的第壹個壹個窗口程序
作為編程的開始,我們還是以壹個Hello World來開始我們的學習之旅。代碼如下:
#include <stdio.h>
void main()
{
printf("Hello World!");
}
這是壹個再簡單不過的C程序了,只要有點C語言的知識就能夠懂的,不過這裏估計還有些人,到現在還不知道#include
<stdio.h>中的頭文件stdio.h到底是什麽東西,我就來說下了,stdio.h是壹個文本文件,存在於磁盤上的,已VC為例它的位置如下圖:
也許妳聽說過printf()函數是在stdio.h中預定義的,但是妳見過其定義的形式沒有,沒有且看下圖
其定義形式,就如圖中所示,也許妳並不懂前面那些東西是什麽,不用擔心,以後我會慢慢解釋給大家的。函數是先定義才能使用的,所以stdio.h中定義printf函數,我我們在引用了stdio.h頭文件後就可以在程序中調用printf函數了。
上面是在命令行中顯示壹個“Hello World!”,沒什麽意思,下面我寫壹個窗口程序,顯示個Hello World!
#include <windows.h>
void main()
{
MessageBox(NULL,"Hello World!","我的第壹個窗口程序",MB_OK);
}
編譯運行後如下圖:
彈出的是壹個對話框,上面有Hello World,還有壹個標題和壹個“確定”按鈕。
當然妳會說這對話框也算個窗口嗎?這裏肯定的告訴妳:是的,對話框是窗口程序的壹個子集。妳可能還會這樣問,這樣壹個簡單的窗口有啥用呢,其實這樣的窗口非常有用,我們在操作計算機的時候,會出現壹些警告或提示的對話框,都是基本是這種方法寫出來的。就算是這個很簡單,學習本來不就是有易向難,有淺顯深奧去的過程嗎。
整個效果幾乎就是靠壹個函數MessageBox的功勞。這裏也先不介紹這個函數了,說些其他的。
其實用C編寫壹些惡程序,就是把編程環境中所提供的壹些函數熟悉了基本就可以了。用VC來寫成序,其中的頭文件有很多,定義了很多Windows API 函數、數據結構、宏,可以讓我們大家運用,通過它們,我們可以快速開發出使用的程序。這些Windows API在微軟的MSDN上查,上面有很多說明,部分還有代碼示例。不會是可以輸入函數名,查找相關信息,建議大家用英文版的Library,因為其內容比中文版的全面,英語不好的同學呢,就先看中文了
中文MSDN:/
英文MSDN:/library/en-us/
到這裏,我們就完成第壹個有界面程序的編寫,妳感覺寫有界面的程序難嗎?顯然不難。
下面看壹個向鋒和波波感興趣的程序:九九乘法
采用命令行形式
#include “stdio.h”
int i=0,j=0;
for(i=1;i<10;i++)
for(j=1;j<i+1;j++)
printf(“%d*%d=%d\t”,j,i,j*i);
printf(“\n”);
和那個javascript效果都是壹樣的,所以語言只要學好壹樣,其他的就很容易旁通的,學習就撿壹種學好,不要貪多。
好的,這壹節就這樣吧,大家先各自了解下微軟的MSDN,對以後的學習會有很大的幫助的。
1.2 第壹個真正的窗口程序
上壹節中,我們用MessageBox函數輕松地實現了壹個對話框窗口,可能妳會說,那僅僅是個沒有用的對話框而已,是的,只是對話框而已。我之所以以壹個對話框為例呢,是因為我只是想讓妳知道寫壹個有界面的程序並不是件難辦的事。明白了這壹點後,我們繼續。今天來編寫壹個真正的窗口程序。
下面就該羅嗦壹段了,由於大家以前並沒有寫過什麽窗口程序,寫的都是命令行下的,我們知道在命令行下的程序都有壹個主函數main,這個函數也就是程序的入口函數。我們現在用VC 6.0來寫,而且要寫窗口類程序,VC 6.0給我們提供了壹個專門用作窗口類程序的入口函數WinMain()
這個函數原型是這樣的
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTRlpCmdLine,
int nCmdShow
);
大家是不是感覺這個函數挺復雜的,有這麽幾個參數,而像main好像就沒有參數。其實main是有參數,這個向鋒和小四是知道了的。但是main函數的參數是可以省略的,而WinMain是不可以省的。這裏也要對VC6.0的編譯模式改下
看下圖
依次是“工程”→“設置”→“連接”,在“工程選項”裏把console改為windows就可以了。如果認真學了匯編,或是手寫命令編譯連接過C程序,就會知道這是幹什麽的。Console是控制臺的意思,以前我們用mian函數寫的程序都是以控制臺模式連接的,所以很少會有界面的。現在我們要寫有界面的程序,所以要選Windows(窗口)模式了。
我們寫入以下代碼,並按照上面說的方法去做,看看結果
#include "windows.h"
int WINAPI WinMain(HINSTANCEhInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
MessageBox(NULL,"WinMain創建的窗口程序","WinMain",MB_OK);
return0;
}
結果如下圖:
與第壹節中的這段代碼代碼比較下
#include “windows.h”
void main()
{
MessageBox(NULL,"Hello World!","我的第壹個窗口程序",MB_OK);
}
兩者比較下,後者多了個cmd窗口。可見用main寫的並沒有完全脫離命令行呀。所以以後我們寫窗口程序就用winmain了。
好了,轉過來,我們來看看WinMain()函數,其中有4個參數
先看下解釋(看不明白得先看完):
hInstance:應用程序當前事例的句柄。
hPrelnstance:應用程序的先事例的句柄。對於同壹個程序打開兩次,出現兩個窗口第壹次打開的窗口就是先前實例的窗口。對於壹個32的位程序,該參數總為NULL。
lpCmdLine:指向應用程序命令行的空字符串的指針,不包括函數名。獲得整個命令行,參看GetCommandLine。
nCmdShow:指明窗口如何顯示(是隱藏還是顯示,有沒有最大化按鈕之類的)。取值可以參考MSDN
這裏我相信有壹個詞大家好應該比較陌生,句柄(HANDLE)是吧。下面我就來簡單的說下
句柄其實就是Windows系統中壹個東西的唯壹標識。就是系統中有很多運行的程序或者資源之類的,為了更好的管理使用,Windows系統給它們每人壹個ID壹樣。懂得網頁制作的人應該知道網頁中各個元素的ID吧,網頁的ID如果重復話可能出現錯誤。那麽系統的句柄會不會有相同的,那是肯定不會有的了,就和我們的學號壹樣,系統自動分配每壹個模塊的句柄,是不會相同的了。
對於句柄大家可以先這樣理解著,不用壹下子搞懂得。以後學著學著就明白了。
估計大家對那幾個參數的類型改犯迷糊了吧。其實那幾個類型,並不是什麽新類型,都是Windows開發人員為了自己和他人編程方便,同過基本的C語言語法定義壹種新的結構體,或者是***同體,再者就是枚舉類型。我知道結構體、***同體和枚舉類型,很多老師是沒有講到的,因為在書的後邊,很多教C的,又是很垃圾的老師,所以不會講那麽快的。其實結構體這些數據類型,就是通過我們常用的字符、整型、浮點等數據類型構造壹個比較復雜的類型而已,舉個例子,就是我們知道C沒有壹個數據類型可以描述壹個人吧,那麽我構造壹個是不是很方便我們編程呢。我們可以這樣構造壹個
struct People
{
intage;//年齡
charsex[2];//性別
intheight;//身高
……
}
我們這樣定義以後就可以在我們以後的程序中利用這個數據類型了,People zhangsan;把zhangsan的身高172放到zhangsan.height中。這樣可以方便完成很多工作。所以結構體是很簡單的,還有其他的復雜數據類型也是很簡單的,都是有常用的簡單的類型來結合到壹起構造壹個復雜的而已。這和JAVA定義類是很相似的,java定義個人類,不是可以這樣的
public class People
{
publicint age;
publicstring sex;
publicheight;
……
}
看起來都差不多,而且用法也很相像。唯壹的差別其實就是類可以有方法,而結構體是沒有的(經過特殊處理也是可以的,這裏不用考慮)。
上面是為了讓大家了解下復雜數據類型的定義,羅嗦了壹大堆。下面來看下WinMain中第壹個參數的類型HINSTANCE這個只是個結構體而已,實際上和HANDLE這個類型差不多,但是有壹點差別,而HANDLE是這樣typedef PVOID HANDLE;定義的,PVOID是什麽呢,我們來看下typedef void *PVOID;說明PVOID是壹個指針,初始指向空(void)。因此可以知道句柄也是個指針而已。看著這麽復雜原來也只是指針。
這些都可以在微軟的msdn上查得到的,而且很詳細的
那個第二個LPSTR 根據字面上的意思就知道是字符串類型了。查壹查果然是。
大家壹定要利用好msdn,很有用的。
本節就到此結束了,主要是說明了壹個WinMain函數和結構體的事情,東西也不算太多,大家應該能接受得了吧。下節就來點復雜點深點的東西,希望大家做好心理準備。
1.3 窗口程序的編寫
在來啰嗦之前,希望大家能夠做好準備,這壹節知識有點多,內容有點長。但願大家能夠壹口氣讀完,如果壹口氣讀不完,那就換口氣接著讀。
上節中我們用MessageBox()就實現了壹個真正的窗口。MessageBox()中的原型如下:
Int MessageBox(HWND hWnd,
LPCTSTRlpText,
LPCTSTRlpCaption,
UINT uType);
參數解釋
hWnd 所屬對話框所屬窗口的句柄,如果是NULL,則此對話框不屬於任何壹個窗口。
lpText 對話框窗口的顯示內容。
lpCaption 對話框窗口的標題。
uType 對話框的樣式和動作(像是確定按鈕,還是取消按鈕就是設置這裏的)
關於這個函數的細節可以看這裏
/en-us/library/ms645505(VS.85).aspx
到此為止,妳也算是會了窗口程序的編寫,但只是壹個開始,不過這已經很好,可能會讓妳感覺到了C的魅力,也可能會稍微解點C語言能幹什麽的疑惑。在開始寫代碼之前,我有必要把細節和原理先說明下。
Windows下壹個窗口創建的過程有以下幾個步驟:
1. 程序創建壹個窗口,首先要向Windows系統註冊壹個窗口類wndclassex,其實就是定義壹個變量,變量的類型是WNDCLASSEX(結構體)。該結構體的定義與介紹看這裏(/en-us/library/ms633577(VS.85).aspx),
typedef struct {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;
成員介紹
cbSize 值為sizeof(WNDCLASSEX),在調用GetClassInfoEx前必須要先設置它值。
style 窗口類的樣式,它的值可以是窗口樣式值的任意組合。
可以有以下的值
lpfnWndProc 指向窗口處理函數(回調函數)。處理窗口事件,像單擊鼠標會怎樣,右擊鼠標會怎樣,都是由此函數控制的。
cbClsExtra 為窗口類的額外信息做記錄,系統初始化為0。
cbWndExtra 記錄窗口實例的額外信息,系統初始為0.如果程序使用WNDCLASSEX註冊壹個從資源文件裏創建的對話框,則此參數必須設置為DLGWINDOWEXTRA
hIcon 窗口類的圖標,為資源句柄,如果設置為NULL,系統將為窗口提供壹個默認的圖標。
hCursor 窗口類的鼠標樣式,為鼠標樣式資源的句柄,如果設置為NULL,系統提供壹個默認的鼠標樣式。
hbrBackground 窗口類的背景刷,為背景刷句柄,也可以為系統顏色值,如果顏色值已給出,則必須轉化為以下的HBRUSH的值
· COLOR_ACTIVEBORDER
· COLOR_ACTIVECAPTION
· COLOR_APPWORKSPACE
· COLOR_BACKGROUND
· COLOR_BTNFACE
· COLOR_BTNSHADOW
· COLOR_BTNTEXT
· COLOR_CAPTIONTEXT
· COLOR_GRAYTEXT
· COLOR_HIGHLIGHT
· COLOR_HIGHLIGHTTEXT
· COLOR_INACTIVEBORDER
· COLOR_INACTIVECAPTION
· COLOR_MENU
· COLOR_MENUTEXT
· COLOR_SCROLLBAR
· COLOR_WINDOW
· COLOR_WINDOWFRAME
· COLOR_WINDOWTEXT
lpszMenuName 指向壹個以NULL結尾的字符床,同目錄資源的名字壹樣。如果使用整型id表示菜單,可以用MAKEINTRESOURCE定義壹個宏。如果它的值為NULL,那麽該類創建的窗口將都沒有默認的菜單。
lpszClassName 窗口類的名字,字符串類型。
hIconSm 小圖標的句柄,在任務欄顯示的圖標,可以和上面的那個壹樣。
定義壹個WNDCLASSEX類型變量後,在給變量成員初始化後,我們就可以用
RegisterWindowEx(&wndclassex)來註冊這個窗口類了。
這個註冊過程,就和我們平常創建壹個項目壹樣,都要先註冊才能創建。