這系列 ( console to windows) 文章並不會說到有關視窗程式設計的技巧,主要提供在 console 底下使用的人一些問題的指引與解決方案,但往往找到的解答都是有些讓初學者震驚的 windows.h ,於是特發此系列文章。若真是想學視窗程式設計,請考慮挑本 win32 視窗程式設計,或 MFC, BCB 視窗程式設計等此類書籍。當然,若評估考量後要用 C#, VB, JAVA... etc,也非常讚同,總之看官學得有興趣就好。

在往下看這系列的文章時,請先至少把基本的 C 或 C++ 學好,不然這部份對您而言沒有任何幫助。另,我該說先去多看看 windows.h 裡面有什麼東西嗎?如果您之前真的翻過 windows.h 裡面有什麼 struct, macro, function, 您會和我一樣,看得愈來愈亂,甚至裡面還有包含其它的 header, 再連過去看,這下真的是亂到不能再亂了!!於是我較建議,有需求的時候再上 MSDN 去查查,不然還是買本有系統的書回來學學,只是鮮少書籍專門在講 windows.h 裡面的 console 函式。

這次,重新先架構第一個程式 - Hello World, 相關說明如下

1. 資料型態 - HANDLE 、DWORD、LPDWORD

事實上這3種資料型態都是在 win32 重新定義的,定義如下

typedef void *HANDLE;
typedef unsigned long DWORD;
typedef unsigned long *LPDWORD;

其中比較讓人難以理解的或許是 HANDLE,但日後只要看到 HANDLE 宣告的東西,就暫時把它想像成 something's control handle (某項東西的控制權) 會好些。但實際上請別忘記,HANDLE 實質上是個 pointer to void。然而在 Win32 裡面取得 Console 之 handle ( 用白話一點的說就是要取得 console 的控制權),一律使用 GetStdHandle 函式,函式原型為:

HANDLE WINAPI GetStdHandle(
  __in          DWORD nStdHandle
);

這裡的 nStdHandle 指的是標準裝置,目前主要有3個值可以用,這3個值都已被 define 成 marco。(1) STD_INPUT_HANDLE:標準輸入之 handle,通常指的是鍵盤 (2) STD_OUTPUT_HANDLE:標準輸出之 handle,通常指的是螢幕 (3)STD_ERROR_HANDLE:標準錯誤之 handle,通常指的也是螢幕。

而在此範例中,我們只是要把 Hello, World!! 顯示在螢幕之輸出裝置上,所以我們這次只先用 STD_OUTPUT_HANDLE,片段碼便成為

HANDLE hin = GetStdHandle(STD_OUTPUT_HANDLE);

2. 引用表頭檔 - windows.h

在這裡我們除了 stdio.h 、string.h 之外,我們還調用了 windows.h ,也由於 windows.h 太過於博大精深,此系列文章也不可能對它做完全、詳細的介紹 (真是這樣的話就直接去買本 windows.h 的 spec 比較快)。

3.  使用 WriteConsole 指令

這次我們用了一次 ConsoleWrite 指令,目前還有用到 printf 指令,但讀者可試著把所有的 printf 指令全都換成 ConsoleWrite 指令。而往後將再介紹其它 WriteConsole 等之相關指令。

 

原始碼

/*
       console to window - how to draw the word in the console
             - by Edison.X.
*/

#include <windows.h>
#include <stdio.h>
#include <string.h>

#define BUFFER_LEN 256
int main()
{
        const char buffer[BUFFER_LEN] = "Hello, World!!";
        HANDLE hin;
        DWORD WriteWord;

        hin = GetStdHandle(STD_OUTPUT_HANDLE);
        if(WriteConsole(hin, buffer, sizeof(buffer), &WriteWord, NULL)){
                // success
                printf("buffer size: %d\n", sizeof(buffer));
                printf("buffer length: %d\n", strlen(buffer));
                printf("write bytes: %u\n", WriteWord);
        }
        else {
                // fail.
                printf("WriteConsole Error!!");
        }
       
        return 0;
}

執行結果

WinConsole -001.png

說明

在此我們看到,實際上 buffer 長度雖為14,但當時在宣告時就用了 256 bytes,而用 ConsoleWrite 時,寫入的 bytes 是調用 sizeof(buffer),於是寫了 256 個字元進去。在此需特別注意,此程式不支援批次檔處理。如今寫一個 a.bat ,內容為 "HelloWorld.exe > a.txt",其結果將會是 "WriteConsole Error!!"。

edisonx 發表在 痞客邦 PIXNET 留言(1) 人氣()


留言列表 (1)

發表留言
  • Penut
  • 而在此範例中,我們只是要把 Hello, World!! 顯示在螢幕之輸出裝置上,所以我們這次只先用 STD_"INPUT"_HANDLE,片段碼便成為

    HANDLE hin = GetStdHandle(STD_OUTPUT_HANDLE);
    上面好像寫錯了,不過很謝謝版主的教學,非常豐富!
  • 已修正,感謝。

    edisonx 於 2014/12/26 16:47 回覆

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼

【 X 關閉 】

【PIXNET 痞客邦】國外旅遊調查
您是我們挑選到的讀者!

填完問卷將有機會獲得心動好禮哦(注意:關閉此視窗將不再出現)

立即填寫取消