電腦遊戲製作開發設計論壇 首頁 電腦遊戲製作開發設計論壇
任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入 

Google
[實用&教學包裝] win32 基礎視窗 [1.0c UA] 2011/08/13 更新

 
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式中級班:資料結構、Win32 API、各種視窗函式庫
上一篇主題 :: 下一篇主題  
發表人 內容
babu61509
散播福音的祭司


註冊時間: 2007-08-26
文章: 142

681.01 果凍幣

發表發表於: 2009-5-7, AM 9:44 星期四    文章主題: [實用&教學包裝] win32 基礎視窗 [1.0c UA] 2011/08/13 更新 引言回覆

2011/08/03 新增 Unicode 版本,會依專案屬性自動變換。
2011/08/03 新增 1.0a UA版,修正初始化順序不正確導致指定的標題跟視窗位置大小無效的bug。
2011/08/04 新增 1.0b UA版,新增DefMP預設視窗訊息處理、resetLocation()置中視窗位置。
2011/08/13 新增 1.0c UA版,改用#infdef判斷是否重複讀入,使用AdjustWindowRect來計算Client Rect大小。

已經包起來了,先發表來佔個位置,有興趣的人可以稍微看一下,等有空再來好好的修一下註解等等。

.h內容(取WinFormA):
代碼:

class WinFormA{
private:
   HWND ConsoleHwnd;      // Console 的 HWND
   HWND Hwnd;            // 建立出來的 Windows HWND
   HINSTANCE Hinstance;   // 建立出來的 Windows HINSTANCE
   string WinTitle;      // 建立出來 Windows 的標題文字
   string ClassName;
   WNDCLASSEX wc;
   void Init();         // 初始化函式
   void CreateWin();      // 建立視窗
   int X,Y,Width,Height;   // 視窗位置大小
   static LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);   // 視窗事件處理函式
   LRESULT MyMsg( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);               //
   INT WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow );   // 主視窗函式
public:
   WinForm();            // 建構式
   WinForm(string Win_Title);   // 建構式(視窗標題名稱)
   WinForm(string Win_Title, int x , int y , int width , int height);   // 建構式(視窗標題名稱,X位置,Y位置,視窗寬度,視窗高度)
   ~WinForm();            // 解構式
   static LRESULT DefMP( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);   // 預設訊息處理
   HWND GetHWND();               // 取得視窗的 HWND
   void ShowConsole(bool Show);   // 是否顯示 Console 視窗
   int Show();            // 顯示 Windows 視窗
   void resetLocation();   // 置中視窗
   int (*MyMainLoop)();      // 自訂主迴圈函式
   LRESULT (*MyMsgProc)( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);   // 自訂視窗處理函式
};


使用方法 :
1. 建立一個空白視窗。
代碼:

#include "WinForm.h"

void main()
{
   WinForm *form1 = new WinForm();
   form1->Show();
   delete form1;
}

2. 建立一個標題為 我自己的視窗 的視窗。
代碼:

#include "WinForm.h"

void main()
{
   WinForm *form1 = new WinForm("我自己的視窗");
   form1->Show();
   delete form1;
}


3. 建立一個標題為 我自己的視窗 ,位置在(100,100),寬為800,高為600像素的視窗。
代碼:

#include "WinForm.h"

void main()
{
   WinForm *form1 = new WinForm("我自己的視窗",100,100,800,600);
   form1->Show();
   delete form1;
}


自訂主迴圈函式與視窗訊息函式:
代碼:

#include "WinForm.h"

int mymainfun(){
   return 0;
}

LRESULT mymsg( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
   switch( msg )
   {
      case WM_DESTROY:
         PostQuitMessage( 0 );
         return 0;
   }

   return DefWindowProc( hWnd, msg, wParam, lParam );
}

void main()
{
   WinForm *form1 = new WinForm();
   form1->MyMainLoop = mymainfun;   // 自訂主迴圈
   form1->MyMsgProc = mymsg;      // 自訂視窗訊息
   form1->Show();
   delete form1;
}


取得視窗HWND方法 :
代碼:

HWND hwnd = form1->GetHWND();

Console被當為偵錯視窗,要顯示可以呼叫
代碼:

form1->ShowConsole(true);

置中視窗位置:
代碼:

form1->resetLocation();


超簡單的吧 ? 這樣win32基礎的第一步就踏出來了 ! (炸

參考資料 :

I want the HWND and HINSTANCE of a console window. How do I get it?

theForger's Win32 API教程第二版(簡體中文)

如何取得主控台視窗控制代碼 (HWND)

D - Mr. Bright: static WndProc


本論壇壇主yag



WinForm.rar
 描述:
WinForm 1.0c UA版

下載
 檔名:  WinForm.rar
 附件大小:  3.49 KB
 下載次數:  共 1040 次


_________________
已經畢業了!!


babu61509 在 2011-8-13, PM 9:55 星期六 作了第 14 次修改
回頂端
檢視會員個人資料 發送私人訊息
happylin
略有貢獻的成員


註冊時間: 2007-07-26
文章: 70

127.34 果凍幣

發表發表於: 2009-5-8, AM 11:37 星期五    文章主題: 引言回覆

這個程式有bug (也不能算是很嚴重的bug)
就是危反. 有借有還 再借不難的原則

new 了一個WinForm 可是沒有 delete

且沒有~WinForm() 的設計..
回頂端
檢視會員個人資料 發送私人訊息
babu61509
散播福音的祭司


註冊時間: 2007-08-26
文章: 142

681.01 果凍幣

發表發表於: 2009-5-8, PM 12:02 星期五    文章主題: 引言回覆

happylin 寫到:
這個程式有bug (也不能算是很嚴重的bug)
就是危反. 有借有還 再借不難的原則

new 了一個WinForm 可是沒有 delete

且沒有~WinForm() 的設計..

解構式沒寫是因為,剛開始想說還沒用到指標類的東西,暫時先放在一旁,結果後來忘了寫上去XD

現在補上去了。

_________________
已經畢業了!!
回頂端
檢視會員個人資料 發送私人訊息
skyvoice
偶而上來逛逛的過客


註冊時間: 2009-01-22
文章: 14

128.78 果凍幣

發表發表於: 2009-5-8, PM 1:06 星期五    文章主題: 引言回覆

這個檔案是之前到數位內容學院進修後並經過改良的版本,參考看看吧~


WindowFrame Beta 1.rar
 描述:

下載
 檔名:  WindowFrame Beta 1.rar
 附件大小:  6.66 KB
 下載次數:  共 1126 次

回頂端
檢視會員個人資料 發送私人訊息
damody
偶而上來逛逛的過客


註冊時間: 2009-05-18
文章: 8

81.28 果凍幣

發表發表於: 2009-9-7, AM 10:56 星期一    文章主題: 太大膽的寫法了= = 引言回覆

你竟然敢直接用LPCTSTR,真的是太誇張了= =
也不讓人從外面傳winproc
好吧,雖然我的也不是很好,不過還是放上來一下
.h
代碼:
#ifndef Win32Class_Im40eda407m1229c278a93mm7e5f_H
#define Win32Class_Im40eda407m1229c278a93mm7e5f_H

// Windows 標頭檔:
#include <windows.h>

class Win32Class
{       
public:
        Win32Class(void);
        HWND        ToCreateWindow(int x, int y, int width, int height, const wchar_t *title,  LRESULT (_stdcall *wndporc)(HWND, UINT, WPARAM, LPARAM) = &Win32Class::Proc);
        MSG        HandlePeekMessage(void);
        HWND        GetHandle(void);
        HINSTANCE        GetInstance(void);
        RECT        GetRect(void);
        void        GetMouseState(int &x, int &y, int button[3]);
        void        ToShow(void);
        void        ToHide(void);
        void        ToMove(UINT x, UINT y, UINT nWidth, UINT nHeight, bool bRepaint = true);
       
        static LRESULT CALLBACK Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
        {
                switch (message)
                {
                case WM_DESTROY:
                        PostQuitMessage(0);
                        break;
                default:
                        return DefWindowProc(hWnd, message, wParam, lParam);
                }
                return 0;
        }
private:
        HWND m_hWnd;
        HINSTANCE m_hInstance;
};


#endif // Win32Class_Im40eda407m1229c278a93mm7e5f_H
代碼:

.cpp
代碼:

/*
這是一個專門產生視窗的類別,像下面這樣,處理訊息的函數,必需從外面提供給ToCreateWindow,否則會使用預設的函數。
LRESULT CALLBACK Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        switch (message)
        {
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
}
ToCreateWindow的前五項函數是用來描述視窗的,第六項就是要像上面的函數, 記得要儲存回傳的HWND控制碼。
GetHandle只能得到最後一個視窗的控制碼。
注意!!!在無限迴圈中必需自行呼叫HandlePeekMessage來處理訊息。
GetMouseState可以獲得滑鼠狀態。
*/

#include "Win32Class.h"


Win32Class::Win32Class(void)
{
        m_hInstance = GetModuleHandle(NULL);
}

HWND Win32Class::ToCreateWindow(int x, int y, int width, int height, const wchar_t *title, LRESULT (_stdcall *wndporc)(HWND, UINT, WPARAM, LPARAM)/*= &Win32Class::Proc*/)
{
        WNDCLASS        window_class;
        memset(&window_class, 0, sizeof(WNDCLASS));
        // `設定視窗型態`
        window_class.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
        // `設定訊息處理函式為WndProc`
        window_class.lpfnWndProc = wndporc;
        // `取得目前執行的程式`
        window_class.hInstance = m_hInstance;
        // `使用內定的滑鼠游標`
        window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
        // `背景設為黑色, 其實有沒有設都沒差.`
        window_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
        // `給定一個註冊視窗時使用的名字`
        window_class.lpszClassName = title;
        // `跟作業系統註冊一個新的視窗`
        if (RegisterClass(&window_class) == 0)
        {
                return false;
        }
        // `計算視窗的邊線會佔掉的點數, 必要時要增加視窗大小.`
        RECT window_rect;
        SetRect(&window_rect, x, y, x+width, y+height);
        AdjustWindowRect(&window_rect, WS_OVERLAPPEDWINDOW, FALSE); //WS_POPUPWINDOW是單框線視窗
       
        // `準備工作完成, 開啟一個視窗.`
        HWND window_handle = CreateWindowEx(
                WS_EX_APPWINDOW,
                title,
                title,
                WS_OVERLAPPEDWINDOW,
                window_rect.left,        // x
                window_rect.top,        // y
                window_rect.right - window_rect.left,        // width
                window_rect.bottom - window_rect.top,        // height
                NULL,
                NULL,
                window_class.hInstance,
                NULL
                );
        if (window_handle == NULL)
                return false;
        m_hWnd = window_handle;       
        return window_handle;
}

MSG Win32Class::HandlePeekMessage()
{
        MSG msg;
        // 主訊息迴圈:
        if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
        {
                // `有訊息的話, 就把它送給訊息處理函式.`
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
        return msg;
}

HWND Win32Class::GetHandle(void)
{
        return m_hWnd;
}
HINSTANCE Win32Class::GetInstance(void)
{
        return m_hInstance;
}
void Win32Class::GetMouseState(int &x, int &y, int button[3])
{
        POINT p;
        GetCursorPos(&p);
        ScreenToClient(m_hWnd, &p);
        x = p.x;
        y = p.y;
        button[0] = GetKeyState(VK_LBUTTON) & 0x80 ? 1 : 0;
        button[1] = GetKeyState(VK_MBUTTON) & 0x80 ? 1 : 0;
        button[2] = GetKeyState(VK_RBUTTON) & 0x80 ? 1 : 0;
}

void Win32Class::ToShow(void)
{
        // `顯示視窗`
        ShowWindow(m_hWnd, SW_SHOWNORMAL);
        SetActiveWindow(m_hWnd);
}
void Win32Class::ToHide(void)
{
        // `顯示視窗`
        ShowWindow(m_hWnd, SW_HIDE);
        SetActiveWindow(m_hWnd);
}

void Win32Class::ToMove( UINT x, UINT y, UINT nWidth, UINT nHeight, bool bRepaint /*= true*/ )
{
        MoveWindow(m_hWnd , x, y, nWidth, nHeight, bRepaint);
}

RECT Win32Class::GetRect( void )
{
        RECT rect;
        GetWindowRect(m_hWnd, &rect);
        return rect;
}

_________________
有心情就是有壓力^^
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式中級班:資料結構、Win32 API、各種視窗函式庫 所有的時間均為 台灣時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
可以 在這個版面附加檔案
可以 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作