• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            斜樹(shù)的空間

            集中精力,放棄一切的去做一件事情,只要盡力了,即使失敗了,你也不會(huì)后悔!

              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              47 隨筆 :: 0 文章 :: 12 評(píng)論 :: 0 Trackbacks

            #


            一:列文件清單
            1. List
            (gdb) list line1,line2

            二:執(zhí)行程序
            要想運(yùn)行準(zhǔn)備 調(diào)試的程序,可使用run命令,在它后面可以跟隨發(fā)給該程序的任何參數(shù),包括標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出說(shuō)明符(<和>)和外殼通配符 (*、?、[、])在內(nèi)。
            如果你使用不帶參數(shù)的run命令,gdb就再次使用你給予前一條run命令的參數(shù),這是很有用的。
            利用 set args 命令就可以修改發(fā)送給程序的參數(shù),而使用show args 命令就可以查看其缺省參數(shù)的列表。
            (gdb)set args –b –x
            (gdb) show args
            backtrace命令為堆棧提供向后跟蹤功能。
            Backtrace 命令產(chǎn)生一張列表,包含著從最近的過(guò)程開(kāi)始的所以有效過(guò)程和調(diào)用這些過(guò)程的參數(shù)。

            三:顯示數(shù)據(jù)
            利用print 命令可以檢查各個(gè)變量的值。
            (gdb) print p (p為變量名)
            whatis 命令可以顯示某個(gè)變量的類型
            (gdb) whatis p
            type = int *

            print 是gdb的一個(gè)功能很強(qiáng)的命令,利用它可以顯示被調(diào)試的語(yǔ)言中任何有效的表達(dá)式。表達(dá)式除了包含你程序中的變量外,還可以包含以下內(nèi)容:
            l 對(duì)程序中函數(shù)的調(diào)用
            (gdb) print find_entry(1,0)
            l 數(shù)據(jù)結(jié)構(gòu)和其他復(fù)雜對(duì)象
            (gdb) print *table_start
            $8={e=reference=’\000’,location=0x0,next=0x0}
            l 值的歷史成分
            (gdb)print $1 ($1為歷史記錄變量,在以后可以直接引用 $1 的值)
            l 人為數(shù)組
            人為數(shù) 組提供了一種去顯示存儲(chǔ)器塊(數(shù)組節(jié)或動(dòng)態(tài)分配的存儲(chǔ)區(qū))內(nèi)容的方法。早期的調(diào)試程序沒(méi)有很好的方法將任意的指針換成一個(gè)數(shù)組。就像對(duì)待參數(shù)一樣,讓我們 查看內(nèi)存中在變量h后面的10個(gè)整數(shù),一個(gè)動(dòng)態(tài)數(shù)組的語(yǔ)法如下所示:
            base@length
            因此,要想顯示在h后面的10個(gè)元素,可 以使用h@10:
            (gdb)print h@10
            $13=(-1,345,23,-234,0,0,0,98,345,10)

            四: 斷點(diǎn)(breakpoint)
            break命令(可以簡(jiǎn)寫為b)可以用來(lái)在調(diào)試的程序中設(shè)置斷點(diǎn),該命令有如下四種形式:
            l break line-number 使程序恰好在執(zhí)行給定行之前停止。
            l break function-name 使程序恰好在進(jìn)入指定的函數(shù)之前停止。
            l break line-or-function if condition 如果condition(條件)是真,程序到達(dá)指定行或函數(shù)時(shí)停止。
            l break routine-name 在指定例程的入口處設(shè)置斷點(diǎn)

            如 果該程序是由很多原文件構(gòu)成的,你可以在各個(gè)原文件中設(shè)置斷點(diǎn),而不是在當(dāng)前的原文件中設(shè)置斷點(diǎn),其方法如下:
            (gdb) break filename:line-number
            (gdb) break filename:function-name

            要想設(shè)置 一個(gè)條件斷點(diǎn),可以利用break if命令,如下所示:
            (gdb) break line-or-function if expr
            例:
            (gdb) break 46 if testsize==100

            從斷點(diǎn)繼續(xù)運(yùn)行:countinue 命令
            五. 斷點(diǎn)的管理

            1. 顯示當(dāng)前gdb的斷點(diǎn)信息:
            (gdb) info break
            他會(huì)以如下的形式顯示所有的斷點(diǎn)信 息:
            Num Type Disp Enb Address What
            1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155
            2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168
            (gdb)
            2.刪除指定的某個(gè)斷點(diǎn):
            (gdb) delete breakpoint 1
            該命令將會(huì)刪除編號(hào)為1的斷點(diǎn),如果不帶編號(hào)參數(shù),將刪除所有的斷點(diǎn)
            (gdb) delete breakpoint
            3.禁止使用某個(gè)斷點(diǎn)
            (gdb) disable breakpoint 1
            該命令將禁止斷點(diǎn) 1,同時(shí)斷點(diǎn)信息的 (Enb)域?qū)⒆優(yōu)?n
            4.允許使用某個(gè)斷點(diǎn)
            (gdb) enable breakpoint 1
            該 命令將允許斷點(diǎn) 1,同時(shí)斷點(diǎn)信息的 (Enb)域?qū)⒆優(yōu)?y
            5.清除原文件中某一代碼行上的所有斷點(diǎn)
            (gdb)clean number
            注:number 為原文件的某個(gè)代碼行的行號(hào)
            六.變量的檢查和賦值
            l whatis:識(shí)別數(shù)組或變量的類型
            l ptype:比whatis的功能更強(qiáng),他可以提供一個(gè)結(jié)構(gòu)的定義
            l set variable:將值賦予變量
            l print 除了顯示一個(gè)變量的值外,還可以用來(lái)賦值

            七.單步執(zhí)行
            l next
            不進(jìn)入的單步執(zhí)行
            l step
            進(jìn)入的單步執(zhí)行
            如果已經(jīng)進(jìn)入了某函數(shù),而想退出該函數(shù)返回到它的調(diào)用函數(shù)中,可使用命令finish
            八.函數(shù)的調(diào) 用
            l call name 調(diào)用和執(zhí)行一個(gè)函數(shù)
            (gdb) call gen_and_sork( 1234,1,0 )
            (gdb) call printf(“abcd”)
            $1=4
            l finish 結(jié)束執(zhí)行當(dāng)前函數(shù),顯示其返回值(如果有的話)

            九. 機(jī)器語(yǔ)言工具
            有一組專用的gdb變量可以用來(lái)檢查和修改計(jì)算機(jī)的通用寄存器,gdb提供了目前每一臺(tái)計(jì)算機(jī)中實(shí)際使用的4個(gè)寄存器的標(biāo)準(zhǔn)名字:
            l $pc : 程序計(jì)數(shù)器
            l $fp : 幀指針(當(dāng)前堆棧幀)
            l $sp : 棧指針
            l $ps : 處理器狀態(tài)

            十.信號(hào)
            gdb通常可以捕捉到發(fā)送給它的大多數(shù)信號(hào),通過(guò)捕捉信號(hào),它就可決定對(duì)于正在運(yùn)行的進(jìn)程要做些什么工 作。例如,按CTRL-C將中斷信號(hào)發(fā)送給gdb,通常就會(huì)終止gdb。但是你或許不想中斷gdb,真正的目的是要中斷gdb正在運(yùn)行的程序,因 此,gdb要抓住該信號(hào)并停止它正在運(yùn)行的程序,這樣就可以執(zhí)行某些調(diào)試操作。

            Handle命令可控制信號(hào)的處理,他有兩個(gè)參數(shù),一個(gè) 是信號(hào)名,另一個(gè)是接受到信號(hào)時(shí)該作什么。幾種可能的參數(shù)是:
            l nostop 接收到信號(hào)時(shí),不要將它發(fā)送給程序,也不要停止程序。
            l stop 接受到信號(hào)時(shí)停止程序的執(zhí)行,從而允許程序調(diào)試;顯示一條表示已接受到信號(hào)的消息(禁止使用消息除外)
            l print 接受到信號(hào)時(shí)顯示一條消息
            l noprint 接受到信號(hào)時(shí)不要顯示消息(而且隱含著不停止程序運(yùn)行)
            l pass 將信號(hào)發(fā)送給程序,從而允許你的程序去處理它、停止運(yùn)行或采取別的動(dòng)作。
            l nopass 停止程序運(yùn)行,但不要將信號(hào)發(fā)送給程序。
            例 如,假定你截獲SIGPIPE信號(hào),以防止正在調(diào)試的程序接受到該信號(hào),而且只要該信號(hào)一到達(dá),就要求該程序停止,并通知你。要完成這一任務(wù),可利用如下 命令:
            (gdb) handle SIGPIPE stop print
            請(qǐng)注意,UNIX的信號(hào)名總是采用大寫字母!你可以用信號(hào)編 號(hào)替代信號(hào)名
            如果你的程序要執(zhí)行任何信號(hào)處理操作,就需要能夠測(cè)試其信號(hào)處理程序,為此,就需要一種能將信號(hào)發(fā)送給程序的簡(jiǎn)便方法,這就是 signal命令的任務(wù)。該 命令的參數(shù)是一個(gè)數(shù)字或者一個(gè)名字,如SIGINT。假定你的程序已將一個(gè)專用的SIGINT(鍵盤輸入,或CTRL-C;信號(hào)2)信號(hào)處理程序設(shè)置成采 取某個(gè)清理動(dòng)作,要想測(cè)試該信號(hào)處理程序,你可以設(shè)置一個(gè)斷點(diǎn)并使用如下命令:
            (gdb) signal 2
            continuing with signal SIGINT(2)
            該程序繼續(xù)執(zhí)行,但是立即傳輸該信號(hào),而且處理程序開(kāi)始運(yùn)行.

            十一. 原文件的搜索
            search text:該命令可顯示在當(dāng)前文件中包含text串的下一行。
            Reverse-search text:該命令可以顯示包含text 的前一行。

            十二.UNIX接口
            shell 命令可啟動(dòng)UNIX外殼,CTRL-D退出外殼,返回到 gdb.

            十三.命令的歷史
            為了允許使用歷史命令,可使用 set history expansion on 命令
            (gdb) set history expansion on

            小結(jié):常用 的gdb命令
            backtrace 顯示程序中的當(dāng)前位置和表示如何到達(dá)當(dāng)前位置的棧跟蹤(同義詞:where)
            breakpoint 在程序中設(shè)置一個(gè)斷點(diǎn)
            cd 改變當(dāng)前工作目錄
            clear 刪除剛才停止處的斷點(diǎn)
            commands 命中斷點(diǎn)時(shí),列出將要執(zhí)行的命令
            continue 從斷點(diǎn)開(kāi)始繼續(xù)執(zhí)行
            delete 刪除一個(gè)斷點(diǎn)或監(jiān)測(cè)點(diǎn);也可與其他命令一起使用
            display 程序停止時(shí)顯示變量和表達(dá)時(shí)
            down 下移棧幀,使得另一個(gè)函數(shù)成為當(dāng)前函數(shù)
            frame 選擇下一條continue命令的幀
            info 顯示與該程序有關(guān)的各種信息
            jump 在源程序中的另一點(diǎn)開(kāi)始運(yùn)行
            kill 異常終止在gdb 控制下運(yùn)行的程序
            list 列出相應(yīng)于正在執(zhí)行的程序的原文件內(nèi)容
            next 執(zhí)行下一個(gè)源程序行,從而執(zhí)行其整體中的一個(gè)函數(shù)
            print 顯示變量或表達(dá)式的值
            pwd 顯示當(dāng)前工作目錄
            pype 顯示一個(gè)數(shù)據(jù)結(jié)構(gòu)(如一個(gè)結(jié)構(gòu)或C++類)的內(nèi)容
            quit 退出gdb
            reverse-search 在源文件中反向搜索正規(guī)表達(dá)式
            run 執(zhí)行該程序
            search 在源文件中搜索正規(guī)表達(dá)式
            set variable 給變量賦值
            signal 將一個(gè)信號(hào)發(fā)送到正在運(yùn)行的進(jìn)程
            step 執(zhí)行下一個(gè)源程序行,必要時(shí)進(jìn)入下一個(gè)函數(shù)
            undisplay display命令的反命令,不要顯示表達(dá)式
            until 結(jié)束當(dāng)前循環(huán)
            up 上移棧幀,使另一函數(shù)成為當(dāng)前函數(shù)
            watch 在程序中設(shè)置一個(gè)監(jiān)測(cè)點(diǎn)(即數(shù)據(jù)斷點(diǎn))
            whatis 顯示變量或函數(shù)類型
            ****************************************************
             GNU的調(diào)試器稱為gdb,該程序是一個(gè)交互式工具,工作在字符模式。在 X Window 系統(tǒng)中,有一個(gè)gdb的前端圖形工具,稱為xxgdb。gdb 是功能強(qiáng)大的調(diào)試程序,可完成如下的調(diào)試任務(wù):
              * 設(shè)置斷點(diǎn);
            * 監(jiān)視程序變量的值;
              * 程序的單步執(zhí)行;
              * 修改變量的值。
              在可以使用 gdb 調(diào)試程序之前,必須使用 -g 選項(xiàng)編譯源文件。可在 makefile 中如下定義 CFLAGS 變量:
               CFLAGS = -g
            運(yùn)行 gdb 調(diào)試程序時(shí)通常使用如下的命令:
               gdb progname

              在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有:
              * aliases:命令別名
              * breakpoints:斷點(diǎn)定義;
              * data:數(shù)據(jù)查看;
              * files:指定并查看文件;
              * internals:維護(hù)命令;
              * running:程序執(zhí)行;
              * stack:調(diào)用棧查看;
              * statu:狀態(tài)查看;
              * tracepoints:跟蹤程序執(zhí)行。
              鍵入 help 后跟命令的分類名,可獲得該類命令的詳細(xì)清單。


            gdb 的常用命令
            命令 解釋
              break NUM 在指定的行上設(shè)置斷點(diǎn)。
              bt 顯示所有的調(diào)用棧幀。該命令可用來(lái)顯示函數(shù)的調(diào)用順序。
              clear 刪除設(shè)置在特定源文件、特定行上的斷點(diǎn)。其用法為clear FILENAME:NUM
              continue 繼續(xù)執(zhí)行正在調(diào)試的程序。該命令用在程序由于處理信號(hào)或斷點(diǎn)而 導(dǎo)致停止運(yùn)行時(shí)。
              display EXPR 每次程序停止后顯示表達(dá)式的值。表達(dá)式由程序定義的變量組成。
              file FILE 裝載指定的可執(zhí)行文件進(jìn)行調(diào)試。
              help NAME 顯示指定命令的幫助信息。
              info break 顯示當(dāng)前斷點(diǎn)清單,包括到達(dá)斷點(diǎn)處的次數(shù)等。
              info files 顯示被調(diào)試文件的詳細(xì)信息。
              info func 顯示所有的函數(shù)名稱。
              info local 顯示當(dāng)函數(shù)中的局部變量信息。
              info prog 顯示被調(diào)試程序的執(zhí)行狀態(tài)。
              info var 顯示所有的全局和靜態(tài)變量名稱。
              kill 終止正被調(diào)試的程序。
              list 顯示源代碼段。
              make 在不退出 gdb 的情況下運(yùn)行 make 工具。
              next 在不單步執(zhí)行進(jìn)入其他函數(shù)的情況下,向前執(zhí)行一行源代碼。
              print EXPR 顯示表達(dá)式 EXPR 的值。

            ******gdb 使用范例************************
            -----------------
            清單 一個(gè)有錯(cuò)誤的 C 源程序 bugging.c
            代碼:

            -----------------
            1 #i nclude
            2
            3 static char buff [256];
            4 static char* string;
            5 int main ()
            6 {
            7   printf ("Please input a string: ");
            8 gets (string);  
            9   printf ("\nYour string is: %s\n", string);
            10 }


            -----------------
            上面這個(gè)程序非常簡(jiǎn)單,其目的是接受用戶的輸入,然后將用戶的輸入打印出來(lái)。該程序使用了一個(gè)未經(jīng)過(guò)初始化的字符串地址 string,因此,編譯并運(yùn)行之后,將出現(xiàn) Segment Fault 錯(cuò)誤:
            $ gcc -o bugging -g bugging.c
            $ ./bugging
            Please input a string: asfd
            Segmentation fault (core dumped)
            為了查找該程序中出現(xiàn)的問(wèn)題,我們利用 gdb,并按如下的步驟進(jìn)行:
            1.運(yùn)行 gdb bugging 命令,裝入 bugging 可執(zhí)行文件;
            2.執(zhí)行裝入的 bugging 命令 run;
            3.使用 where 命令查看程序出錯(cuò)的地方;
            4.利用 list 命令查看調(diào)用 gets 函數(shù)附近的代碼;
            5.唯一能夠?qū)е?gets 函數(shù)出錯(cuò)的因素就是變量 string。用print命令查看 string 的值;
            6.在 gdb 中,我們可以直接修改變量的值,只要將 string 取一個(gè)合法的指針值就可以了,為此,我們?cè)诘?行處設(shè)置斷點(diǎn) break 8;
            7.程序重新運(yùn)行到第 8行處停止,這時(shí),我們可以用 set variable 命令修改 string 的取值;
            8.然后繼續(xù)運(yùn)行,將看到正確的程序運(yùn)行結(jié)果。
            (http://www.fanqiang.com)

            posted @ 2010-10-12 11:56 張貴川 閱讀(682) | 評(píng)論 (0)編輯 收藏


            Unix已經(jīng)有35年歷史了。許多人認(rèn)為它開(kāi)始于中世紀(jì),這個(gè)中世紀(jì)是相對(duì)于
            計(jì)算機(jī)技術(shù)的產(chǎn)生和發(fā)展來(lái)說(shuō)的。在過(guò)去的時(shí)間里,Unix和它的子分支Linux收集
            有許多的歷史和一些完全古老的語(yǔ)言。在這篇技巧文章中,我們將介紹一少部分古
            老的語(yǔ)言和它們的目的和作用,以及它們真正的來(lái)源。 

            RC 

            在Linux中,最為常用的縮略語(yǔ)也許是“rc”,它是“runcomm”的縮寫――即名詞
            “run   command”(運(yùn)行命令)的簡(jiǎn)寫。今天,“rc”是任何腳本類文件的后綴,這些
            腳本通常在程序的啟動(dòng)階段被調(diào)用,通常是Linux系統(tǒng)啟動(dòng)時(shí)。如   
            /etc/rs是
            Linux啟動(dòng)的主腳本,而.bashrc是當(dāng)Linux的bash   shell啟動(dòng)后所運(yùn)行的腳
            本。.bashrc的前綴“.”是一個(gè)命名標(biāo)準(zhǔn),它被設(shè)計(jì)用來(lái)在用戶文件中隱藏那些用戶
            指定的特殊文件;“ls”命令默認(rèn)情況下不會(huì)列出此類文件,“rm”默認(rèn)情況下也不會(huì)
            刪除它們。許多程序在啟動(dòng)時(shí),都需要“rc”后綴的初始文件或配置文件,這對(duì)于
            Unix的文件系統(tǒng)視圖來(lái)說(shuō),沒(méi)有什么神秘的。 

            ETC 

            在“etc
            /bin”中的“etc”真正代表的是“etcetera”(附加物)。在早期的Unix系
            統(tǒng)中,最為重要的目錄是“bin”目錄   (“bin”是“binaries”二進(jìn)制文件――編譯后的
            程序的縮寫),“etc”中則包含瑣碎的程序,如啟動(dòng)、關(guān)機(jī)和管理。運(yùn)行一個(gè)Linux
            必須的東西的列表是:一個(gè)二進(jìn)制程序,etcetera,etcetera――換句話說(shuō),是一個(gè)
            底層的重要項(xiàng)目,通常添加一些次等重要的零碎事物。今天,   “etc”包含了廣泛
            的系統(tǒng)配置文件,這些配置文件幾乎包含了系統(tǒng)配置的方方面面,同樣非常重要。 

            Bin 

            今天,許多在Linux上運(yùn)行的大型子系統(tǒng),如GNOME或Oracle,所編譯成的程
            序使用它們自己的“bin”目錄(或者是   
            /usr/bin,或者是/usr/local/bin)作為標(biāo)
            準(zhǔn)的存放地。同樣,現(xiàn)在也能夠在這些目錄看到腳本文件,因?yàn)?#8220;bin”目錄通常添
            加到用戶的PATH路徑中,這樣他們才能夠正常的使用程序。因此運(yùn)行腳本通常在
            bin中運(yùn)行良好。 

            TTY 

            在Linux中,TTY也許是跟終端有關(guān)系的最為混亂的術(shù)語(yǔ)。TTY是TeleTYpe的
            一個(gè)老縮寫。Teletypes,或者   teletypewriters,原來(lái)指的是電傳打字機(jī),是
            通過(guò)串行線用打印機(jī)鍵盤通過(guò)閱讀和發(fā)送信息的東西,和古老的電報(bào)機(jī)區(qū)別并不是
            很大。之后,當(dāng)計(jì)算機(jī)只能以批處理方式運(yùn)行時(shí)(當(dāng)時(shí)穿孔卡片閱讀器是唯一一種
            使程序載入運(yùn)行的方式),電傳打字機(jī)成為唯一能夠被使用的“實(shí)時(shí)”輸入
            /輸出設(shè)
            備。最終,電傳打字機(jī)被鍵盤和顯示器終端所取代,但在終端或   TTY接插的地
            方,操作系統(tǒng)仍然需要一個(gè)程序來(lái)監(jiān)視串行端口。一個(gè)getty“Get   TTY”的處理過(guò)
            程是:一個(gè)程序監(jiān)視物理的TTY
            /終端接口。對(duì)一個(gè)虛擬網(wǎng)絡(luò)沮喪服務(wù)器(VNC)來(lái)說(shuō),
            一個(gè)偽裝的TTY(Pseudo
            -TTY,即家貓的TTY,也叫做“PTY”)是等價(jià)的終端。當(dāng)你運(yùn)
            行一個(gè)xterm(終端仿真程序)或GNOME終端程序時(shí),PTY對(duì)虛擬的用戶或者如xterm一
            樣的偽終端來(lái)說(shuō),就像是一個(gè)TTY在運(yùn)行。“Pseudo”的意思是“duplicating   
            in 
            a   fake   way”(用偽造的方法復(fù)制),它相比“
            virtual”或“emulated”更能真實(shí)的
            說(shuō)明問(wèn)題。而在現(xiàn)在的計(jì)算中,它卻處于被放棄的階段。 

            Dev 

            從TTY留下的命令有“stty”,是“
            set   tty”(設(shè)置TTY)的縮寫,它能夠生成
            一個(gè)配置文件
            /etc/initab(“initialization   table”,初始表),以配置gettys
            使用哪一個(gè)串口。在現(xiàn)代,直接附加在Linux窗口上的唯一終端通常是控制臺(tái),由
            于它是特殊的TTY,因此被命名為“console”。當(dāng)然,一旦你啟動(dòng)
            X11,“console”TTY就會(huì)消失,再也不能使用串口協(xié)議。所有的TTY都被儲(chǔ)存在
            /dev”目錄,它是“[physical]   devices”([物理]設(shè)備)的縮寫。以前,你必須在
            電腦后面的串口中接入一個(gè)新的終端時(shí),手工修改和配置每一個(gè)設(shè)備文件。現(xiàn)
            在,Linux(和   Unix)在安裝過(guò)程中就在此目錄中創(chuàng)建了它所能向?qū)У拿恳粋€(gè)設(shè)備
            的文件。這就是說(shuō),你很少需要自己創(chuàng)建它。 

            隨著硬件在電腦中的移出移進(jìn),這些名字將變得更加模糊不清。幸運(yùn)的是,
            今天在Linux上的高等級(jí)軟件塊對(duì)歷史和硬件使用容易理解的名字。舉例來(lái)說(shuō),
            嗯,Pango(http:
            //www.pango.org/)就是其中之一。 

            如果你對(duì)這些內(nèi)容很感興趣,那么我建議你閱讀宏大的,但有些以美國(guó)英語(yǔ)
            歷史為中心的,由Eric   S.   Raymond撰寫的Jargon   File。它并沒(méi)有解釋所有
            在Unix中使用的術(shù)語(yǔ),但是它給出了這些形成的大致情況。  

            posted @ 2010-10-11 23:29 張貴川 閱讀(267) | 評(píng)論 (0)編輯 收藏

            獲得CWinApp:
             -在CMainFrame,CChildFrame,CDocument,CView中直接調(diào)用AfxGetApp()或用theApp
             -在其它類中只能用AfxGetApp()

            獲得CMainFrame:
             -在CMinApp中用AfxGetMainWnd()或者m_pMainWnd
             -在CChildFrame中可用GetParentFrame()
             -在其它類中用AfxGetMainWnd()

            獲得CChildFrame:
             -在CView中用GetParentFrame()
             -在CMainFrame中用MDIGetActive()或GetActiveFrame()
             -在其它類中用AfxGetMainWnd()->MDIGetActive()或AfxGetMainWnd()->GetActiveFrame()

            獲得CDocument:
             -在CView中用GetDocument()
             -在CChildFrame中用GetActiveView()->GetDocument()
             -在CMainFrame中用
              -if SDI:GetActiveView()->GetDocument()
              -if MDI:MDIGetActive()->GetActiveView()->GetDocument()
             -在其它類中
              -if SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()
              -if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

            獲得CView:
             -在CDocument中 POSITION pos = GetFirstViewPosition();GetNextView(pos)
             -在CChildFrame中 GetActiveView()
             -在CMainFrame中
              -if SDI:GetActiveView()
              -if MDI:MDIGetActive()->GetActiveView()
             -在其它類中
              -if SDI:AfxGetMainWnd()->GetActiveView()
              -if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()


            不過(guò)要注意在doc中要取得view的指針C*View要注意類C*View聲明的問(wèn)題,
            因?yàn)槟J(rèn)情況下,mfc在*View.h中已經(jīng)包含了*Doc.h,如果在*Doc.h中包含
            *View.h,就會(huì)引起嵌套包含問(wèn)題,這樣要在*Doc.h中加入 class C*View;
            而在*Doc.cpp中加入 #include "*View.h"

            //////////////////////////////////////////////////////////////////
            其實(shí)完全可以在CYourApp中添加各種視或文檔的指針,在那些視或文檔初
            始化的時(shí)候?qū)⒅羔槀鹘oCYourApp中的對(duì)應(yīng)變量,這樣以后不管在哪用上面
            指針只需(CYourApp*)AfxGetApp()取其屬性變量即可,明了而且清楚更是
            方便我一直專門操作的說(shuō):)

            //////////////////////////////////////////////////////////////////
            我先拋塊磚,有玉的砸過(guò)來(lái)!
            在何時(shí)何地,你都可以通過(guò)以下方法精確的得到任何一個(gè)對(duì)象(Application,DocTemplate,Document,View,Frame)
            1。通過(guò)AfxGetApp()得到當(dāng)前的App對(duì)象;
            2。通過(guò)AfxGetMainWnd()得到主窗口;
            3。通過(guò)CMDIFrameWnd::GetActiveFrame得到當(dāng)前活動(dòng)窗口;
            4。通過(guò)GetNextWindow()遍例所有的子窗口;(如果要得到你想要的子窗口,可以通過(guò)特定的成員變量來(lái)標(biāo)志);
            5。通過(guò)CWinApp::GetFirstDocTemplatePostion()以及CWinApp::GetNextDocTemplate()的組合應(yīng)用來(lái)遍歷所有的DocTemplate對(duì)象,并且用CDocTemplate::GetDocString()來(lái)判斷當(dāng)前得到的文檔莫板對(duì)象是哪個(gè)。
            6。通過(guò)CDocTemplate::GetFirstDocPosition()以及CDocTemplate的GetNextDoc()組合來(lái)遍歷所有的該模板的文檔對(duì)象,并用CDocument::GetDocTemplate()來(lái)得到文檔模板,用CDocment::GetTitle() 或者GetPathName()來(lái)判斷當(dāng)前的文檔是哪個(gè)。
            7。通過(guò)CDocuemt的GetFirstViewPositon()以及GetNextView()來(lái)遍歷視圖對(duì)象,一般通過(guò)訪問(wèn)View的成員變量來(lái)區(qū)別各個(gè)視圖;通過(guò)CView::GetDocument()來(lái)得到文檔對(duì)象;
            8。Frame->View: 通過(guò)GetActiveView方法;
            9。Frame->Doc:通過(guò)GetActiveDocument();
            10。View->Frame:GetParentFrame();
            11。View->Doc:GetDocuemt()//前面已經(jīng)說(shuō)了。
            12。Doc->View:前面說(shuō)了;
            13。Doc->Frame:不知道有沒(méi)有很直接的方法。
            MFC應(yīng)用程序中指針的使用

            1) 在View中獲得Doc指針
            2) 在App中獲得MainFrame指針
            3) 在View中獲得MainFrame指針
            4) 獲得View(已建立)指針
            5) 獲得當(dāng)前文檔指針
            6) 獲得狀態(tài)欄與工具欄指針
            7) 獲得狀態(tài)欄與工具欄變量
            8) 在Mainframe獲得菜單指針
            9) 在任何類中獲得應(yīng)用程序類
            10) 從文檔類取得視圖類的指針(1)
            11) 在App中獲得文檔模板指針
            12) 從文檔模板獲得文檔類指針
            13) 在文檔類中獲得文檔模板指針
            14) 從文檔類取得視圖類的指針(2)
            15) 從一個(gè)視圖類取得另一視圖類的指針

            VC中編程對(duì)于剛剛開(kāi)始學(xué)習(xí)的同學(xué),最大的障礙和問(wèn)題就是消息機(jī)制和指針獲取與
            操作。其實(shí)這些內(nèi)容基本上是每本VC學(xué)習(xí)工具書上必講的內(nèi)容,而且通過(guò)MSDN很多
            問(wèn)題都能解決。下面文字主要是個(gè)人在編程中指針使用的一些體會(huì),說(shuō)的不當(dāng)?shù)牡?br>方請(qǐng)指正。一般我們使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,
            無(wú)論是多文檔還是單文檔,都存在指針獲取和操作問(wèn)題。下面這節(jié)內(nèi)容主要是一般
            的框架,然后再講多線程中的指針使用。使用到的類需要包含響應(yīng)的頭文件。首先
            一般獲得本類(視,文檔,對(duì)話框都支持)實(shí)例指針this,用this的目的,主要可以通
            過(guò)類中的函數(shù)向其他類或者函數(shù)中發(fā)指針,以便于在非本類中操作和使用本類中的
            功能。

             1) 在View中獲得Doc指針 CYouSDIDoc *pDoc=GetDocument();一個(gè)視只能有一個(gè)文
            檔。
             2) 在App中獲得MainFrame指針
            CWinApp 中的 m_pMainWnd變量就是MainFrame的指針
            也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
             3) 在View中獲得MainFrame指針 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
             4) 獲得View(已建立)指針 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
            CyouView *pView=(CyouView *)pMain->GetActiveView();
             5) 獲得當(dāng)前文檔指針 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();
             6) 獲得狀態(tài)欄與工具欄指針 CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
            CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

             7) 如果框架中加入工具欄和狀態(tài)欄變量還可以這樣
            (CMainFrame *)GetParent()->m_wndToolBar;
            (CMainFrame *)GetParent()->m_wndStatusBar;

             8) 在Mainframe獲得菜單指針 CMenu *pMenu=m_pMainWnd->GetMenu();
             9) 在任何類中獲得應(yīng)用程序類
            用MFC全局函數(shù)AfxGetApp()獲得。

             10) 從文檔類取得視圖類的指針
            我是從http://download.cqcnc.com/soft/program/article/vc/vc405.html學(xué)到的,
            從文檔獲得視圖類指針目的一般為了控制同一文檔的多個(gè)視圖的定位問(wèn)題,我的體會(huì)
            特別是文字處理CEditView當(dāng)產(chǎn)生多個(gè)視圖類時(shí),這個(gè)功能是非常需要的。
            CDocument類提供了兩個(gè)函數(shù)用于視圖類的定位:
            GetFirstViewPosition()和GetNextView()
            virtual POSITION GetFirstViewPosition() const;
            virtual CView* GetNextView(POSITION& rPosition) const;

            注意:GetNextView()括號(hào)中的參數(shù)用的是引用方式,因此執(zhí)行后值可能改變。
            GetFirstViewPosition()用于返回第一個(gè)視圖位置(返回的并非視圖類指針,而是一
            個(gè)POSITION類型值),GetNextView()有兩個(gè)功能:返回下一個(gè)視圖類的指針以及用
            引用調(diào)用的方式來(lái)改變傳入的POSITION類型參數(shù)的值。很明顯,在Test程序中,只有
            一個(gè)視圖類,因此只需將這兩個(gè)函數(shù)調(diào)用一次即可得到CTestView的指針如下(需定
            義一個(gè)POSITION結(jié)構(gòu)變量來(lái)輔助操作):
            CTestView* pTestView;
            POSITION pos=GetFirstViewPosition();
            pTestView=GetNextView(pos);

            這樣,便可到了CTestView類的指針pTestView.執(zhí)行完幾句后,變量pos=NULL,因?yàn)闆](méi)
            有下一個(gè)視圖類,自然也沒(méi)有下一個(gè)視圖類的POSITION.但是這幾條語(yǔ)句太簡(jiǎn)單,不
            具有太強(qiáng)的通用性和安全特征;當(dāng)象前面說(shuō)的那樣,當(dāng)要在多個(gè)視圖為中返回某個(gè)指
            定類的指針時(shí),我們需要遍歷所有視圖類,直到找到指定類為止。判斷一個(gè)類指針指
            向的是否某個(gè)類的實(shí)例時(shí),可用IsKindOf()成員函數(shù)時(shí)行檢查,如:
             pView->IsKindOf(RUNTIME_CLASS(CTestView));
            即可檢查pView所指是否是CTestView類。

            有了以上基礎(chǔ),我們已經(jīng)可以從文檔類取得任何類的指針。為了方便,我們將其作
            為一個(gè)文檔類的成員函數(shù),它有一個(gè)參數(shù),表示要獲得哪個(gè)類的指針。實(shí)現(xiàn)如下:
            CView* CTestDoc::GetView(CRuntimeClass* pClass)
            {
             CView* pView;
             POSITION pos=GetFirstViewPosition();

             while(pos!=NULL){
              pView=GetNextView(pos);
              if(!pView->IsKindOf(pClass))
              break;
             }

             if(!pView->IsKindOf(pClass)){
              AfxMessageBox("Connt Locate the View.\r\n http://www.VCKBASE.com");
              return NULL;
             }

             return pView;
            }

            其中用了兩次視圖類的成員函數(shù)IsKindOf()來(lái)判斷,是因?yàn)橥顺鰓hile循環(huán)有三種
            可能:

            1.pos為NULL,即已經(jīng)不存在下一個(gè)視圖類供操作;
            2.pView已符合要求。

            1和2同是滿足。這是因?yàn)镚etNextView()的功能是將當(dāng)前視圖指針改變成一個(gè)視圖
            的位置同時(shí)返回當(dāng)前視圖指針,因此pos是pView的下一個(gè)視圖類的POSITION,完全
            有可能既是pos==NULL又是pView符合需要。當(dāng)所需的視圖是最后一個(gè)視圖是最后一
            個(gè)視圖類時(shí)就如引。因此需采用兩次判斷。
            使用該函數(shù)應(yīng)遵循如下格式(以取得CTestView指針為例):
            CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));
            RUNTIME_CLASS是一個(gè)宏,可以簡(jiǎn)單地理解它的作用:將類的名字轉(zhuǎn)化為
            CRuntimeClass為指針。至于強(qiáng)制類型轉(zhuǎn)換也是為了安全特性考慮的,因?yàn)閺耐粋€(gè)
            基類之間的指針類型是互相兼容的。這種強(qiáng)制類型轉(zhuǎn)換也許并不必要,但能避免一
            些可能出現(xiàn)的麻煩。

            3.從一個(gè)視圖類取得另一視圖類的指針綜合1和2,很容易得出視圖類之間互相獲得
            指針的方法:就是用文檔類作中轉(zhuǎn),先用1的方法得到文檔類的指針,再用2的方法,
            以文檔類的視圖定位函數(shù)取得另一個(gè)視圖類。同樣,可以實(shí)現(xiàn)成一個(gè)函數(shù):
            (假設(shè)要從CTestAView中取得指向其它視圖類的指針)
            CView* CTestAView::GetView(CRuntimeClass* pClass)
            {
             CTestDoc* pDoc=(CTestDoc*)GetDocument();
             CView* pView;
             POSITION pos=pDoc->GetFirstViewPosition();
             while(pos!=NULL){
              pView=pDoc->GetNextView(pos);
              if(!pView->IsKindOf(pClass))
              break;
             }
             if(!pView->IsKindOf(pClass)){
              AfxMessageBox("Connt Locate the View.");
              return NULL;
             }

             return pView;
            }
            這個(gè)函數(shù)和2中的GetView()相比,一是多了第一句以取得文檔類指針,二是在
            GetFirstViewPosition()和GetNextView()前加上了文檔類指針,以表示它們是文檔
            類成員函數(shù)。有了此函數(shù);當(dāng)要從CTestAView中取得CTestBView的指針時(shí),只需如
            下:CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));
            11)對(duì)于單文檔中也可以加入多個(gè)文檔模板,但是一般的開(kāi)發(fā)就使用MDI方式開(kāi)發(fā)
            多文檔模板,其方法與上述視圖的獲取方法很接近,這里稍做解釋,如果不清楚,
            請(qǐng)查閱MSDN,(以下四個(gè)內(nèi)容(11、12、13、14)來(lái)源:
            http://sanjianxia.myrice.com/vc/vc45.htm

            可以用CWinApp::GetFirstDocTemplatePostion獲得應(yīng)用程序注冊(cè)的第一個(gè)文檔模板
            的位置;利用該值來(lái)調(diào)用CWinApp::GetNextDocTemplate函數(shù),獲得第一個(gè)
            CDocTemplate對(duì)象指針。 POSITION GetFirstDocTemplate( ) const;
            CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;

            第二個(gè)函數(shù)返回由pos 標(biāo)識(shí)的文檔模板。POSITION是MFC定義的一個(gè)用于迭代或?qū)ο?br>指針檢索的值。通過(guò)這兩個(gè)函數(shù),應(yīng)用程序可以遍歷整個(gè)文檔模板列表。如果被檢索
            的文檔模板是模板列表中的最后一個(gè),則pos參數(shù)被置為NULL。

             12)一個(gè)文檔模板可以有多個(gè)文檔,每個(gè)文檔模板都保留并維護(hù)了一個(gè)所有對(duì)應(yīng)文
            檔的指針列表。
            用CDocTemplate::GetFirstDocPosition函數(shù)獲得與文檔模板相關(guān)的文檔集合中第一
            個(gè)文檔的位置,并用POSITION值作為CDocTemplate::GetNextDoc的參數(shù)來(lái)重復(fù)遍歷與
            模板相關(guān)的文檔列表。函數(shù)原形為:
            viaual POSITION GetFirstDocPosition( ) const = 0;
            visual CDocument *GetNextDoc(POSITION & rPos) const = 0; 

            如果列表為空,則rPos被置為NULL.

             13)在文檔中可以調(diào)用CDocument::GetDocTemplate獲得指向該文檔模板的指針。
            函數(shù)原形如下: CDocTemplate * GetDocTemplate ( ) const;
            如果該文檔不屬于文檔模板管理,則返回值為NULL。

             14)一個(gè)文檔可以有多個(gè)視。每一個(gè)文檔都保留并維護(hù)一個(gè)所有相關(guān)視的列表。
            CDocument::AddView將一個(gè)視連接到文檔上,將該視加入到文檔相聯(lián)系的視的列表
            中,并將視的文檔指針指向該文檔。當(dāng)有File/New、File/Open、Windows/New或
            Window/Split的命令而將一個(gè)新創(chuàng)建的視的對(duì)象連接到文檔上時(shí), MFC會(huì)自動(dòng)調(diào)用
            該函數(shù),框架通過(guò)文檔/視的結(jié)構(gòu)將文檔和視聯(lián)系起來(lái)。當(dāng)然,程序員也可以根據(jù)自
            己的需要調(diào)用該函數(shù)。
            Virtual POSITION GetFirstViewPosition( ) const;
            Virtual CView * GetNextView( POSITION &rPosition) cosnt;

            應(yīng)用程序可以調(diào)用CDocument::GetFirstViewPosition返回與調(diào)用文檔相聯(lián)系的視的
            列表中的第一個(gè)視的位置,并調(diào)用CDocument::GetNextView返回指定位置的視,并將
            rPositon的值置為列表中下一個(gè)視的POSITION值。如果找到的視為列表中的最后一個(gè)
            視,則將rPosition置為NULL.

             15)從一個(gè)視圖類取得另一視圖類的指針
            這個(gè)應(yīng)用在多視的應(yīng)用程序中很多見(jiàn),一般如果自己在主程序或者主框架中做好變
            量記號(hào),也可以獲得,還有比較通用的就是用文檔類作中轉(zhuǎn),以文檔類的視圖遍歷
            定位,取得另一個(gè)視圖類。這個(gè)功能從本文第10項(xiàng)中可以得到。


            轉(zhuǎn)自:http://www.shnenglu.com/justin-shi/archive/2008/06/14/53196.html

            posted @ 2010-08-28 12:33 張貴川 閱讀(263) | 評(píng)論 (0)編輯 收藏

            屬性-》C/C++-》預(yù)編譯頭-》創(chuàng)建使用預(yù)編譯頭-》不使用
             

            posted @ 2010-08-02 22:42 張貴川 閱讀(3153) | 評(píng)論 (1)編輯 收藏

               工具欄(ToolBar)是一種非常方便的控件,能大大增加用戶操作的效率,但是基于對(duì)話框的程序,卻不能像使用編輯框(Edit Box)和列表框(List Box)一樣,方便地增加工具欄控件。本文將介紹一種在對(duì)話框中加入工具欄的方法。

              一、 技術(shù)要點(diǎn)分析

              所有的Windows控件(包括工具欄、編輯框等)都派生自CWnd類,這就意味著,我們可以用窗口類的Create()函數(shù)把它們“創(chuàng)建”并顯示到另一個(gè)窗口(例如對(duì)話框)上。把工具欄加入到對(duì)話框中正是使用了這樣的一種方法。

              通常,我們使用CToolBarCtrl類(派生自CWnd類)來(lái)創(chuàng)建并管理工具欄控件。使用這個(gè)類創(chuàng)建一條工具欄的一般步驟如下:

              1.派生一個(gè)CToolBarCtrl的對(duì)象;

              2.調(diào)用CToolBarCtrl::Create函數(shù)創(chuàng)建工具欄對(duì)象;

              3.調(diào)用CToolBarCtrl::AddBitmap()和CToolBarCtrl::AddString()為工具欄對(duì)象加入位圖和提示信息;

              4.派生一個(gè)TBUTTON數(shù)組對(duì)象進(jìn)行工具欄中各按鈕的具體設(shè)置;

              5.修改主窗口的OnNotify()函數(shù),以顯示工具欄上的提示信息。

              以上步驟在下面的范例代碼中會(huì)有具體體現(xiàn)。


              二、 范例程序的建立與主要代碼分析


              利用Visual C++ 的向?qū)梢粋€(gè)基于對(duì)話框的程序,命名為ToolBarInDial。修改主對(duì)話框樣式如圖1。繪出一條工具欄的位圖并建立一選單,設(shè)置幾個(gè)子選單項(xiàng),然后建立一組工具欄的提示信息串(String Table),一旦鼠標(biāo)在工具欄某項(xiàng)上停留,就會(huì)顯示提示信息。下面給出程序中的主要代碼。

              在主對(duì)話框CToolBarInDialDlg的類定義中有如下的變量說(shuō)明:

              CToolBarCtrl ToolBar;

              int ButtonCount;

              int ButtonBitmap;

              BOOL DoFlag;

              TBBUTTON m_Button[5];

              //設(shè)置工具欄上具體信息的變量數(shù)組

              //主對(duì)話框的初始化函數(shù)

              BOOL CToolBarInDialDlg::OnInitDialog()

              {

              RECT rect;

              //設(shè)置工具欄的顯示范圍

              rect.top=0; rect.left=0; rect.right=48; rect.bottom=16;

              ToolBar.Create(WS_CHILD|WS_VISIBLE|CCS_TOP|TBSTYLE_TOOLTIPS|CCS_ADJUSTABLE,rect,this,0);

              //建立工具欄并設(shè)置工具欄的樣式

              ButtonBitmap=ToolBar.AddBitmap(5,IDB_PLAY); //加入工具欄的位圖

              ButtonString=ToolBar.AddString(IDS_FIRST);//加入工具欄的提示信息

              //以下代碼開(kāi)始設(shè)置各具體的按鈕

              m_Buttons[ButtonCount].iBitmap=

              ButtonBitmap+ButtonCount; //ButtonCount初值為0

              m_Buttons[ButtonCount].idCommand=ID_PLAY; //工具欄與選單上某子項(xiàng)對(duì)應(yīng)

              m_Buttons[ButtonCount].fsState=TBSTATE_ENABLED;

              //設(shè)置工具欄按鈕為可選

              m_Buttons[ButtonCount].fsStyle=TBSTYLE_BUTTON;

              //設(shè)置工具欄按鈕為普通按鈕

              m_Buttons[ButtonCount].dwData=0;

              m_Buttons[ButtonCount].iString=IDS_LAST;

               ++ButtonCount;

              //類似地設(shè)置第二個(gè)按鈕

              m_Buttons[ButtonCount].iBitmap=ButtonBitmap+ButtonCount;

              m_Buttons[ButtonCount].idCommand=ID_STOP;

              m_Buttons[ButtonCount].fsState=TBSTATE_ENABLED;

              m_Buttons[ButtonCount].fsStyle=TBSTYLE_BUTTON;

              m_Buttons[ButtonCount].dwData=0;

              m_Buttons[ButtonCount].iString=IDS_NEXT;

              ++ButtonCount;

              ……//省略設(shè)置剩下的按鈕的代碼

               ToolBar.AddButtons(ButtonCount,m_Buttons);

              //為工具欄加入按鈕并顯示在對(duì)話框中

               return TRUE;

              }

              //當(dāng)鼠標(biāo)在工具欄上停留時(shí),調(diào)用這個(gè)函數(shù)來(lái)顯示提示信息

              BOOL CToolBarInDialDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)

              {

              TOOLTIPTEXT* tt;

              tt=(TOOLTIPTEXT*)lParam;

              CString Tip;

              switch(tt->hdr.code)

              {

              case TTN_NEEDTEXT:

              //該信息表明要求顯示工具欄上的提示

              switch(tt->hdr.idFrom)

              {

              case ID_PLAY:



              Tip.LoadString(IDS_FIRST); //設(shè)置對(duì)應(yīng)于工具欄上ID_PLAY的按鈕的提示信息

              break;

              case ID_STOP:

              Tip.LoadString(IDS_NEXT);

              //IDS_FIRST,IDS_NEXT等為一系列CString串

              break;

              ……//類似地設(shè)置剩下按鈕的提示信息

              }

               strcpy(tt->szText,(LPCSTR)Tip);

               //顯示提示信息

              break;

              }

              return CDialog::OnNotify(wParam, lParam, pResult);

              }

              //該演示程序的工具欄能由用戶定制,隨時(shí)增加或刪除工具欄中的某一項(xiàng)

              void CToolBarInDialDlg::OnApply()

              {

               switch(DoFlag) //用戶選擇了增加或刪除工具欄中的“退出”按鈕

              {

              case TRUE: //增加工具欄上的“退出”按鈕

              m_Buttons[ButtonCount].iBitmap=ButtonBitmap+ButtonCount;

              m_Buttons[ButtonCount].idCommand=ID_QUIT;

              m_Buttons[ButtonCount].fsState=TBSTATE_ENABLED;

              m_Buttons[ButtonCount].fsStyle=TBSTYLE_BUTTON;

              m_Buttons[ButtonCount].dwData=0;

              m_Buttons[ButtonCount].iString=IDS_FIRST;

              ToolBar.InsertButton(ButtonCount,&&m_Buttons[ButtonCount]);

              //根據(jù)m_Buttons的信息在工具欄的尾部加上一個(gè)按鈕

              break;

              case FALSE:

              if(ToolBar.GetButtonCount()==4) //刪除工具欄上某一特定位置的按鈕

              {

              ToolBar.DeleteButton(3);

              //刪除工具欄上某一按鈕

              }

              break;

              }

              }

              void CToolBarInDialDlg::OnPlay() //響應(yīng)函數(shù)舉例

              {

              ……

              //對(duì)應(yīng)選單項(xiàng)的響應(yīng)函數(shù)

              }
            posted @ 2010-08-01 09:44 張貴川 閱讀(1013) | 評(píng)論 (0)編輯 收藏

            安裝步驟其實(shí)很簡(jiǎn)單,但是你不知道的話,就真的不會(huì)。
            1.創(chuàng)建虛擬機(jī),選擇光盤鏡像。
            2.啟動(dòng)后會(huì)讓分區(qū)。分區(qū)時(shí)會(huì)讓你重啟。
            3.重啟后按F2進(jìn)入虛擬機(jī)中的BIOS設(shè)置為光盤啟動(dòng)。
            4.進(jìn)去后就可以了。一路安裝。
            5.安裝完后再次進(jìn)入BIOS,設(shè)置啟動(dòng)為 硬盤 啟動(dòng)。

            接著在教你怎樣用虛擬機(jī)和DOS共享文件:(源自gagbage同學(xué)制作)
            /Files/Viking/share.pdf
            posted @ 2010-07-24 08:51 張貴川 閱讀(249) | 評(píng)論 (0)編輯 收藏

            大學(xué)生活過(guò)的挺失敗的,我是個(gè)不甘心落后的人,在技術(shù)上,我不認(rèn)為自己比別人差,然而我卻沒(méi)有做出什么成績(jī)出來(lái)。
             究其原因,我發(fā)現(xiàn):我太浮躁了!
            每門技術(shù)我都學(xué)了一半,沒(méi)有堅(jiān)持下去。做的也不認(rèn)真。才造成了我現(xiàn)在半杯水的樣子。看真周圍的同學(xué)都成功的做出了很多作品。并且能賺到錢了,就感到了什么叫壓力。
            每門技術(shù)都很深?yuàn)W,每門技術(shù)卻又是那樣的誘人,你會(huì)什么都想學(xué),什么都想深入,然而卻沒(méi)有時(shí)間,總是被其他事情打斷學(xué)習(xí)進(jìn)程。從大二接觸到學(xué)習(xí)匯編,玩LINUX,卻沒(méi)有堅(jiān)持下來(lái)。大二下有玩單片機(jī)和FPGA,但在硬件的基礎(chǔ)課程上模電和數(shù)字邏輯上學(xué)的是在是太爛,最終也放棄了。我就沒(méi)想過(guò)認(rèn)真的去復(fù)習(xí)一下課程。后面接觸了MFC,又是從0開(kāi)始學(xué)起,為了圖快,便只看書,程序?qū)懙纳俚模A(chǔ)沒(méi)打的結(jié)實(shí),花費(fèi)了大量的時(shí)間然而卻沒(méi)有成果。
            后來(lái)遇到了一群驅(qū)動(dòng)愛(ài)好著,終于理解到什么叫做學(xué)習(xí)的氛圍,一個(gè)人學(xué)習(xí)真的是很累人,進(jìn)步很慢。也終于理解了為什么布施定律是成功之道。
            當(dāng)然自己也終結(jié)了很多的學(xué)習(xí)方法,但最重要的一條還是:技術(shù)的路上踏實(shí)認(rèn)真才是捷徑。
            同時(shí)發(fā)現(xiàn)數(shù)學(xué)課程是多么的重要。
            同時(shí)發(fā)現(xiàn)自己浪費(fèi)了好多時(shí)間在女孩的身上,結(jié)果她們最后的話都是不想談戀愛(ài)。我決定以后談戀愛(ài)都找女人,胸部至少有明顯的突出,這樣的女人談戀愛(ài)會(huì)更容易些交互些(母性特征)。
            還有男人成熟的開(kāi)始:就是開(kāi)始想賺錢買車,買房的時(shí)候。
            我是看到我同學(xué)這學(xué)期都賺錢買車,買房和女友出去同居了,才意識(shí)到這些東西。想想,自己真的太浮躁,不認(rèn)真,浪費(fèi)了太多認(rèn)真積累的時(shí)間,真的太失敗!
            大家有幸看到我的帖子的話,記住只要選好一個(gè)你喜歡的方向,踏實(shí)認(rèn)真的專研下去就可以了,因?yàn)闆](méi)門技術(shù)都很深?yuàn)W,你沒(méi)有那么多的時(shí)間成為全才,看看你自己究竟學(xué)了什么東西!至于他踏實(shí)認(rèn)真的方法,因個(gè)體而異。
             我目前認(rèn)為最踏實(shí)的方法就是
            1.認(rèn)認(rèn)真真總結(jié)每章所學(xué)的內(nèi)容,可以放到自己的blog上,也可以找個(gè)筆記本來(lái)認(rèn)真做筆記,現(xiàn)在才深刻認(rèn)識(shí)到寫好字的重要性。
            2.課后習(xí)題每一題都要認(rèn)真做,最好把答案都發(fā)布到自己的blog上。
            3.系統(tǒng)的學(xué)習(xí)。不要介意你從0開(kāi)始看,簡(jiǎn)單就看快一點(diǎn),不能不看。
            4.慢即是快。不要浮躁,你不可能是全才,找準(zhǔn)一個(gè)方向,不要總是換。一本書一本書的看,認(rèn)真看完一本在看下一本。相信自己是正確的。因?yàn)楹穹e才能薄發(fā)。
            posted @ 2010-07-09 11:01 張貴川 閱讀(166) | 評(píng)論 (0)編輯 收藏

            assume cs:codeseg
            codeseg segment
                    mov ax,2000H
                    mov ss,ax
                    mov sp,0
                    add sp,4
                    pop ax
                    pop bx
                    push ax
                    push bx
                    pop ax
                    pop bx
                    mov ax,4c00H
                    int 21h
            codeseg ends
            end

            按理來(lái)說(shuō)是DOS中沒(méi)有棧保護(hù)的啊?怎么會(huì)就溢出了呢?

            經(jīng)過(guò)大量的調(diào)試測(cè)試:

            我試過(guò)了,只有ADD SP,N

            N <= 10H

            并且 N = 奇數(shù) 的時(shí)候就會(huì)崩潰


            偶數(shù)不崩潰?

            N >= 10H  的時(shí)候,奇偶都可以
            N=7,9,B就直接崩潰
            偶數(shù)在<=4就觸發(fā) DEBUG 的斷點(diǎn)中斷 INT 3中斷

            可能關(guān)乎 16位機(jī)的取數(shù)原則:16位機(jī)取每次取2個(gè)字節(jié),并且最好取偶數(shù)地址,取奇數(shù)地址則要讀取內(nèi)存2次。意思是棧中的內(nèi)存SP地址(包括DI,SI等)最好是2的倍數(shù)(16位機(jī)),這樣訪存時(shí)間最快。32則是4的倍數(shù)。

            但是為什么會(huì)崩潰我還是不明白??
            posted @ 2010-06-29 16:19 張貴川 閱讀(227) | 評(píng)論 (0)編輯 收藏

            在使用  重疊IO模型 的時(shí)候遇到一個(gè)連個(gè) 頭文件 包含錯(cuò)誤,windows.h 和 winsock2.h。在網(wǎng)上找到一篇文章,覺(jué)得方法很好,特轉(zhuǎn)載:

            在我初學(xué)Windows網(wǎng)絡(luò)編程時(shí),曾經(jīng)遇到過(guò)兩類編譯錯(cuò)誤(VC6的Build窗口嘩嘩的顯示了102個(gè)Errors),都是些類型未定義或者重復(fù)定義問(wèn)題,讓我感到很郁悶。這兩種錯(cuò)誤情況下的第一條錯(cuò)誤信息分別為:

            錯(cuò)誤情形1:mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier
            錯(cuò)誤情形2:winsock2.h(99) : error C2011: 'fd_set' : 'struct' type redefinition
            后來(lái),我靜下心來(lái)仔細(xì)分析一下錯(cuò)誤提示及相關(guān)文件,終于找到了原因。

            我們知道,Windows網(wǎng)絡(luò)編程至少需要兩個(gè)頭文件:winsock2.h和windows.h,而在WinSock2.0之前還存在一個(gè)老版本的winsock.h。正是這三個(gè)頭文件的包含順序,導(dǎo)致了上述問(wèn)題的出現(xiàn)。

            先讓我們看看winsock2.h的內(nèi)容,在文件開(kāi)頭有如下宏定義:

            #ifndef _WINSOCK2API_
            #define _WINSOCK2API_
            #define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
            _WINSOCK2API_很容易理解,這是最常見(jiàn)的防止頭文件重復(fù)包含的保護(hù)措施。_WINSOCKAPI_的定義則是為了阻止對(duì)老文件winsock.h的包含,即是說(shuō),如果用戶先包含了winsock2.h就不允許再包含winsock.h了,否則會(huì)導(dǎo)致類型重復(fù)定義。這是怎樣做到的呢?很簡(jiǎn)單,因?yàn)閣insock.h的頭部同樣存在如下的保護(hù)措施:

            #ifndef _WINSOCKAPI_
            #define _WINSOCKAPI_
            再回過(guò)頭來(lái)看winsock2.h,在上述內(nèi)容之后緊跟著如下宏指令:

            /*
             * Pull in WINDOWS.H if necessary
             */
            #ifndef _INC_WINDOWS
            #include <windows.h>
            #endif /* _INC_WINDOWS */
            其作用是如果用戶沒(méi)有包含windows.h(_INC_WINDOWS在windows.h中定義)就自動(dòng)包含它,以定義WinSock2.0所需的類型和常量等。

            現(xiàn)在切換到windows.h,查找winsock,我們會(huì)驚奇的發(fā)現(xiàn)以下內(nèi)容:

            #ifndef WIN32_LEAN_AND_MEAN
            #include <cderr.h>
            #include <dde.h>
            #include <ddeml.h>
            #include <dlgs.h>
            #ifndef _MAC
            #include <lzexpand.h>
            #include <mmsystem.h>
            #include <nb30.h>
            #include <rpc.h>
            #endif
            #include <shellapi.h>
            #ifndef _MAC
            #include <winperf.h>
            #if(_WIN32_WINNT >= 0x0400)
            #include <winsock2.h>
            #include <mswsock.h>
            #else
            #include <winsock.h>
            #endif /* _WIN32_WINNT >=  0x0400 */

            #endif
            // 這里省略掉一部分內(nèi)容
            #endif /* WIN32_LEAN_AND_MEAN */

            看到?jīng)]?windows.h會(huì)反向包含winsock2.h或者winsock.h!相互間的包含便是萬(wàn)惡之源!

            下面具體分析一下問(wèn)題是怎么發(fā)生的。

            錯(cuò)誤情形1:我們?cè)谧约旱墓こ讨邢劝瑆insock2.h再包含windows.h,如果WIN32_LEAN_AND_MEAN未定義且_WIN32_WINNT大于或等于0x400,那么windows.h會(huì)在winsock2.h開(kāi)頭被自動(dòng)引入,而windows.h又會(huì)自動(dòng)引入mswsock.h,此時(shí),mswsock.h里所用的socket類型還尚未定義,因此會(huì)出現(xiàn)類型未定義錯(cuò)誤。

            錯(cuò)誤情形2:先包含windows.h再包含winsock2.h,如果WIN32_LEAN_AND_MEAN未定義且_WIN32_WINNT未定義或者其版本號(hào)小于0x400,那么windows.h會(huì)自動(dòng)導(dǎo)入舊有的winsock.h,這樣再當(dāng)winsock2.h被包含時(shí)便會(huì)引起重定義。

            這里要說(shuō)明的是,宏WIN32_LEAN_AND_MEAN的作用是減小win32頭文件尺寸以加快編譯速度,一般由AppWizard在stdafx.h中自動(dòng)定義。_WIN32_WINNT的作用是開(kāi)啟高版本操作系統(tǒng)下的特殊函數(shù),比如要使用可等待定時(shí)器(WaitableTimer),就得要求_WIN32_WINNT的值大于或等于0x400。因此,如果你沒(méi)有遇到上述兩個(gè)問(wèn)題,很可能是你沒(méi)有在這些條件下進(jìn)行網(wǎng)絡(luò)編程。

            問(wèn)題還沒(méi)有結(jié)束,要知道除了VC自帶windows庫(kù)文件外,MS的Platform SDK也含有這些頭文件。我們很可能發(fā)現(xiàn)在之前能夠好好編譯的程序在改變了windows頭文件包含路徑后又出了問(wèn)題。原因很簡(jiǎn)單,Platform SDK中的windows.h與VC自帶的文件存在差異,其相同位置的代碼如下:

            #ifndef WIN32_LEAN_AND_MEAN
            #include <cderr.h>
            #include <dde.h>
            #include <ddeml.h>
            #include <dlgs.h>
            #ifndef _MAC
            #include <lzexpand.h>
            #include <mmsystem.h>
            #include <nb30.h>
            #include <rpc.h>
            #endif
            #include <shellapi.h>
            #ifndef _MAC
            #include <winperf.h>
            #include <winsock.h>  // 這里直接包含winsock.h
            #endif
            #ifndef NOCRYPT
            #include <wincrypt.h>
            #include <winefs.h>
            #include <winscard.h>
            #endif
            #ifndef NOGDI
            #ifndef _MAC
            #include <winspool.h>
            #ifdef INC_OLE1
            #include <ole.h>
            #else
            #include <ole2.h>
            #endif /* !INC_OLE1 */
            #endif /* !MAC */
            #include <commdlg.h>
            #endif /* !NOGDI */
            #endif /* WIN32_LEAN_AND_MEAN */

            唉,我們不禁要問(wèn)MS為什么要搞這么多花樣,更讓人氣憤的是,既然代碼不一樣,windows.h里卻沒(méi)有任何一個(gè)宏定義能夠幫助程序辨別當(dāng)前使用的文件是VC自帶的還是PSDK里的。

            后來(lái),我寫了一個(gè)頭文件專門處理winsock2.h的包含問(wèn)題,名為winsock2i.h,只需在要使用WinSock2.0的源文件里第一個(gè)包含此文件即可,不過(guò)由于前面提到的問(wèn)題,當(dāng)使用PSDK時(shí),需要手工定義一下USING_WIN_PSDK,源碼如下:

            //
            // winsock2i.h - Include winsock2.h safely.
            //
            // Copyleft  02/24/2005  by freefalcon
            //
            //
            // When WIN32_LEAN_AND_MEAN is not defined and _WIN32_WINNT is LESS THAN 0x400,
            // if we include winsock2.h AFTER windows.h or winsock.h, we get some compiling
            // errors as following:
            //   winsock2.h(99) : error C2011: 'fd_set' : 'struct' type redefinition
            //
            // When WIN32_LEAN_AND_MEAN is not defined and _WIN32_WINNT is NOT LESS THAN 0x400,
            // if we include winsock2.h BEFORE windows.h, we get some other compiling errors:
            //   mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier
            //
            // So, this file is used to help us to include winsock2.h safely, it should be
            // placed before any other header files.
            //
            #ifndef _WINSOCK2API_

            // Prevent inclusion of winsock.h
            #ifdef _WINSOCKAPI_
            #error Header winsock.h is included unexpectedly.
            #endif

            // NOTE: If you use Windows Platform SDK, you should enable following definition:
            // #define USING_WIN_PSDK

            #if !defined(WIN32_LEAN_AND_MEAN) && (_WIN32_WINNT >= 0x0400) && !defined(USING_WIN_PSDK)
            #include <windows.h>
            #else
            #include <winsock2.h>
            #endif

            #endif//_WINSOCK2API_

            本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/freefalcon/archive/2006/11/09/1374733.aspx

            按照f(shuō)reefalcon提供的方法,到winsock2.h中看到:
            #ifndef _INC_WINDOWS
            #include <windows.h>
            #endif /* _INC_WINDOWS */
            其實(shí)只需包含#include <winsock2.h>就可以了,把#include <windows.h>放在#include <winsock2.h>后其實(shí)也是可以的,沒(méi)有包含錯(cuò)誤的問(wèn)題。

            但如果又出現(xiàn)這樣的錯(cuò)誤:
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__closesocket@4,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__WSAGetLastError@0,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__WSARecv@28,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__WSACreateEvent@0,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__accept@12,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__listen@8,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__bind@12,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__htons@4,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__htonl@4,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__socket@12,該符號(hào)在函數(shù) _main 中被引用
            1>server.obj : error LNK2019: 無(wú)法解析的外部符號(hào) __imp__WSAStartup@8,該符號(hào)在函數(shù) _main 中被引用

            如果出現(xiàn)這樣的錯(cuò)誤,那就是庫(kù)沒(méi)包含了,只要查查MSDN,找到包含這個(gè)函數(shù)的庫(kù)就行了,加入一句:

            #pragma   comment(lib,   "ws2_32.lib")

            posted @ 2010-05-18 20:51 張貴川 閱讀(1036) | 評(píng)論 (0)編輯 收藏

            剛遇到一個(gè)問(wèn)題,在MFC中我將映射方式由 MM_TEXT 改為 MM_HIENGLISH 后,竟然無(wú)法輸出漢字!!但改回 MM_TEXT 后就可以輸出漢字了。
            這個(gè)問(wèn)題很郁悶,找了很久也不知道是怎么回事....暫時(shí)先記在這里。。。

            posted @ 2010-05-16 22:17 張貴川 閱讀(91) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題
            共5頁(yè): 1 2 3 4 5 
            国产999精品久久久久久| 久久91这里精品国产2020| 久久se精品一区二区影院| 伊人久久大香线蕉亚洲| 日产久久强奸免费的看| 国产日韩久久久精品影院首页 | 色综合久久无码中文字幕| 久久精品无码av| 久久久艹| 久久最新免费视频| 日产久久强奸免费的看| 亚洲国产综合久久天堂| 亚洲伊人久久成综合人影院| 久久久这里有精品| 久久婷婷五月综合色奶水99啪| 2021国产精品久久精品| 久久天天躁狠狠躁夜夜不卡 | 国产69精品久久久久APP下载| 久久青青草原精品国产软件| 亚洲精品国产第一综合99久久| 伊人精品久久久久7777| 中文字幕久久久久人妻| 日产精品久久久久久久性色| 国产精品视频久久| 精品久久久久久无码人妻热 | 久久精品九九亚洲精品| 国产精品美女久久久| 99久久精品费精品国产| 亚洲午夜精品久久久久久浪潮| 麻豆av久久av盛宴av| 国产亚洲欧美精品久久久| 91精品国产91热久久久久福利| 精品久久久无码中文字幕| 久久久久亚洲av综合波多野结衣 | 91精品观看91久久久久久| 午夜精品久久久久久影视777| 久久综合九色综合网站| 久久国产成人精品麻豆| 色老头网站久久网| 欧美一区二区精品久久| 久久婷婷五月综合成人D啪|