1. การประกาศ message map
จะทำได้โดยการพิมพ์บรรทัด DECLARE_MESSAGE_MAP( ) ลงไปในการประกาศคลาสที่สืบทอดมาจากคลาสหน้าต่าง
ของวินโดวส์ของเรา
เช่น
/* Class ของหน้าต่างโปรแกรมของเรา ที่สืบทอดมาจากคลาส CFrameWnd */
class CMainWin : public CFrameWnd
{
public:
CMainWin( );
DECLARE_MESSAGE_MAP( ) /* ประกาศ message map ตรงท้ายสุดของการประกาศคลาส */
};
2.
การเพิ่มมาโครที่สัมพันธ์กับ message ลงไปใน message map
การที่โปรแกรมของเราจะตอบสนองกับ message ที่วินโดวส์
ส่งมาให้ได้นั้น จะต้องมีการเพิ่มมาโครที่สัมพันธ์กับ message ที่เราต้องการลงไปใน
message map ของโปรแกรมที่เราเขียนขึ้นนั้นเสียก่อน โดยมาโครของ message ในแบบของ
MFC นั้น จะมีชื่อเดียวกันกับ message มาตรฐานของวินโดวส์ (standard Windows message)
แต่จะขึ้นต้นด้วยคำว่า ON_ และปิดท้ายด้วยเครื่องหมายวงเล็บ() เช่น มาโครของ message
WM_LBUTTONUP ก็คือ ON_WM_LBUTTONUP( ) , มาโครของ WM_PAINT ก็คือ ON_WM_PAINT(
) แต่มีข้อยกเว้นอยู่อย่างหนึ่ง คือ มาโครของ WM_COMMAND จะเป็น ON_COMMAND(
)
การเพิ่มมาโครเข้าไปใน message map จะพิมพ์แทรกลงไประหว่างคำสั่ง
BEGIN_MESSAGE_MAP และ END_MESSAGE_MAP ยกตัวอย่างเช่น ถ้าในโปรแกรม ของคุณ ต้องการจัดการกับ
message WM_CHAR จะต้องพิมพ์บรรทัดต่อไปนี้ลงไปใน message map
BEGIN_MESSAGE_MAP(CMainWin,CFrameWnd) ON_WM_CHAR( ) END_MESSAGE_MAP( )
เนื่องจากในโปรแกรม ที่เราเชียนขึ้น สามารถม ีหน้าต่างวินโดวส์ ได้หลายหน้าต่าง และแต่ละหน้าต่างก็ สามารถมี message map ของตนเอง ทำให้เราสามารถ กำหนดได้ว่า message map ใดเป็นของวินโดวส์ใดได้ โดยในคำสั่ง BEGIN_MESSAGE_MAP จะมีพารามิเตอร์ 2 ตัวคือ Owner กับ Base ดังแสดงตัวอย่าง
BEGIN_MESSAGE_MAP(Owner, Base) /* เว้นไว้เติมมาโครของ message ที่ต้องการจัดการ */ END_MESSAGE_MAP( )
Owner
ก็คือ ชื่อคลาสของ หน้าต่าง ที่จะจัดการกับ message นั้น
ส่วน Base ก็คือชื่อคลาสแม่ (Base Class) ของคลาสที่จะจัดการกับ
message นั้น
3.
การประกาศฟังก์ชั่นที่เป็นตัวจัดการกับ message นั้น ๆ ลงในการประกาศคลาส ของหน้าต่างวินโดวส์ของเรา
ฟังก์ชั่นที่เป็นตัวจัดการกับ message เราเรียกอีกอย่างว่า
message handler จะมีชื่อเดียวกับชื่อของ message ของเรา แต่จะขึ้นต้นด้วย คำว่า
On แทน เช่น ตัวจัดการกับ message WM_CHAR ก็คือฟังก์ชั่นที่มีชื่อว่า OnChar(
) นั่นเอง หรือตัวจัดการกับ message WM_LBUTTONDOWN ก็คือฟังก์ชั่น OnLButtonDown()
นั่นเอง ดังนั้น จากการประกาศคลาสในข้อที่ 1 ก็จะต้องมีการประกาศ ฟังก์ชั่น ที่เป็นตัว
จัดการกับ message นั้นลงไปด้วย ดังนี้
/* Class ของหน้าต่างโปรแกรมของเรา ที่สืบทอดมาจากคลาส CFrameWnd */
class CMainWin : public CFrameWnd
{
public: CMainWin( );
afx_msg void OnChar(UINT ch, UINT count, UINT flags ); /* ประกาศฟังก์ชั่นที่เป็นตัวจัดการกับ message WM_CHAR */
DECLARE_MESSAGE_MAP( ) /* ประกาศ message map ตรงท้ายสุดของการประกาศคลาส */
};
จะสังเกตว่าฟังก์ชั่น OnChar( ) จะมีคำว่า afx_msg ขึ้นต้นด้วย เพราะฟังก์ชั่นที่เป็นตัวจัดการ message ในแบบ MFC นี้จะต้อง ใช้คำว่า afx_msg เป็นตัวกำหนด ชนิดของฟังก์ชั่นเสมอ
4. เขียนรายละเอียดของฟังก์ชั่นที่เป็นตัวจัดการกับ message
นั้น ๆ ลงในโปรแกรมของเรา
เช่นในการจัดการกับ message WM_CHAR โดยทุกครั้งเมื่อมีการกดปุ่มบนคีย์บอร์ด
ในขณะที่หน้าต่างวินโดวส์ของโปรแกรมเรา active อยู่ จะมีตัวอักษรที่เรากด ไปปรากฎบน
พื้นที่ทำงาน (client area) ของหน้าต่างวินโดวส์เรา ตรงตำแหน่งมุมบนซ้ายมือสุด
เราจะเขียน รายละเอียด ของฟังก์ชั่นตัวจัดการ message WM_CHAR ดังต่อไปนี้
char str[80]; /* กำหนดตัวแปร เป็นตัวเก็บ string ที่จะนำไปแสดง */
/* รายละเอียดของฟังก์ชั่นที่ใช้จัดการกับ message WM_CHAR */
afx_msg void CMainWin::OnChar(UINT ch, UINT count, UINT flags)
{
CClientDC dc(this);
dc.TextOut(1, 1," ", 3); /* ลบตัวอักษรก่อนหน้านี้ */
wsprintf(str, "%c", ch); /* แปลงตัวอักษรที่ได้รับ ไปเป็น string */
dc.TextOut(1, 1, str, strlen(str)); /* ส่ง string ที่ได้ออกวินโดวส์ */
}
คราวนี้ก็ลองมาดูตัวโปรแกรมทั้งหมดกัน อย่าลืม สร้างโปรเจคท์ใหม่ แล้วใช้คำสั่ง Project->setting จะได้ไดอะล็อกบ็อกซ์ขึ้นมา ในช่อง Microsoft Foundation Class ให้เลือกเป็น Use MFC in static library หรือ Use MFC in share dll ก็ได้ แล้วคลิ๊ก OK ก็จะออกมาที่หน้าจอทำงาน ตามปกติ
จากนั้นให้เลือกเมนู File -> New จะปรากฎ ไดอะลอกบอกซ์ใ้หเลือกชนิด ของไฟล์ใหม่ที่ต้องการสร้าง ให้เลือกเป็น C/C++ header file เพื่อจะสร้าง header file ขึ้นมา ตั้งชื่อ header file เป็น message.h แล้วคลิ๊ก OK จากนั้นก็เขียนโปรแกรมดังต่อไปนี้ลงใน หน้าต่างทำงาน
/* ไฟล์ ชื่อ message.h */
/* ประกาศคลาสของหน้าต่างวินโดวส์ของเรา ที่สืบทอดมาจากคลาส CFrameWnd */
class CMainWin : public CFrameWnd
{
public:
CMainWin( );
afx_msg void OnChar(UINT ch, UINT count, UINT flags);
DECLARE_MESSAGE_MAP( )
};
/* ประกาศคลาสของโปรแกรมเรา ที่สืบทอดมาจากคลาส CWinApp */
class CApp : public CWinApp
{
BOOL InitInstance( );
};
save ไฟล์นี้ จากนั้นให้เลือกเมนู File -> New จะได้ ไดอะลอกบอกซ์ให้เลือกชนิดของไฟล์ ที่ต้องการสร้าง ตอนนี้ให้เลือกเป็น C/C++ Source File เพื่อเป็นการสร้าง source file ของ โปรแกรมของเรา ตั้งชื่อไฟล์เป็น message.cpp แล้วคลิ๊ก OK แล้วเขียนโปรแกรมต่อไปนี้ ลงในหน้าต่างทำงาน
/* ไฟล์ชื่อ message.cpp */
#include <afxwin.h> /* ต้อง include ไฟล์นี้ทุกครั้งที่เขียนแบบ MFC */
#include <string.h> /* include function ที่จัดการกับ string เข้ามา */
#include "message.h"/* include ไฟล์ที่ประกาศคลาสของเราเข้ามา */
char str[80]; /* กำหนดตัวแปร str เป็นอาเรย์ ของตัวแปรชนิด char จำนวน 80 ตัว */
/* ประกาศเป็นตัวแปรชนิด global เพื่อให้เรียกใช้ได้จากทุกแห่งในโปรแกรม */
CMainWin::CMainWin( ) /* function constructor ของคลาสหน้าต่างวินโดวส์เรา */
{
Create(NULL, "Test WM_CHAR message map");
}
/* รายละเอียดของฟังก์ชั่น InitInstance */
BOOL CApp::InitInstance( )
{
m_pMainWnd = new CMainWin;
m_pMainWnd -> ShowWindow(m_nCmdShow);
m_pMainWnd -> UpdateWindow( );
return TRUE;
}
/* ส่วนของ message map ของหน้าต่างวินโดวส์ CMainWin ที่สืบทอดมาจากคลาส CFrameWnd*/
BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd)
ON_WM_CHAR( )
END_MESSAGE_MAP( )
/* รายละเอียดของฟังก์ชั่นที่ใช้จัดการ message WM_CHAR */
afx_msg void CMainWin::OnChar(UINT ch, UINT count, UINT flags)
{
CClientDC dc(this); /* สร้างออปเจคส์ของคลาส CClientDC ซึ่งจะรับค่า Device context ของ */
/* client area ของหน้าต่างวินโดวส์นี้มาเก็บไว้ */
dc.TextOut(1, 1, " ", 3); /* เขียนข่องว่าง (space) ลงบน client area ตำแหน่งบนซ้ายสุด */
wsprintf(str, "%c", ch); /* แปลงตัวอักขระ ch ไปเก็บไว้ที่ตัวแปรอาเรย์ str */
dc.TextOut(1, 1, str, strlen(str)); /* เขียนตัวอักขระลงบน client area ตำแหน่งบนซ้ายสุด */
}
CApp myapp; /* สร้างออปเจคท์ของคลาสโปรแกรมของเรา */
จากนั้น save ไฟล์ แล้วทำการ build โปรแกรมตามที่ได้กล่าวไว้แล้วในบทก่อน แล้วทำการ execute โปรแกรม ก็จะได้หน้าต่างโปรแกรมขึ้นมา ลองกดปุ่มตัว อักษรใด ๆ ก็ได้บนคีย์บอร์ด จะได้ตัวอักษรปรากฎบนมุมบนซ้ายของ พื้นที่ทำงาน (Client area) ของวินโดวส์ ดังแสดงในรูป

ตอนนี้โปรแกรม ของเรา ก็ดูจะทำงานได้ เหมือนที่ต้องการ แต่จริง ๆ แล้ว ยังมีข้อบกพร่อง อย่างหนึ่ง อยู่ในโปรแกรมนี้ เพื่อน ๆ พอจะทราบไม๊คะ? ถ้ายังไม่ทราบ ก็ลอง minimize หน้าต่าง ของโปรแกรม ที่เราเขียนขึ้น ลงไปก่อนนะคะ แล้วลอง restore หน้าต่างวินโดวส์ ของเราให้กลับขึ้นมา แสดงบนจอภาพใหม่ จะพบว่า ตัวอักษรที่อยู่ ด้านบนซ้าย ของพื้นที่ทำงาน บนวินโดวส์ หายไป ที่เป็นเช่นนี้ เพราะว่า วินโดวส์จะไม่มีการ เก็บข้อมูลที่แสดง บนพื้นที่ทำงานไว้ เมื่อถูก minimize หรือเมื่อถูกหน้าต่าง ของวินโดวส์อื่น ๆ ทับ จึงเป็นหน้าที่ ของผู้เขียนโปรแกรม ที่จะต้องเขียน code ตรงส่วนนี้เอง ซึ่งเราจะกล่าวถึงต่อไป ในบทที่ 6 นะคะ
แล้วพบกันไหม่ คราวหน้าค่ะ หนูแจ๋ว