Visual C++
Control
Control คืออะไร?
Control จริง ๆ แล้วก็คือ สิ่งที่โปรแกรม ใช้เป็นช่องทาง ติดต่อ สื่อสารกับผู้ใช้งาน นั้นเอง ซึ่งเราสามารถ ส่งข้อมูล เข้าไปให้โปรแกรม หรือรับรู้ สิ่งที่โปรแกรม ต้องการ บอกให้เรารับรู้ ได้ผ่านทาง Control นี้ โดย Control ในโปรแกรม ระบบวินโดวส์ นี้มีมากมาย หลายชนิด แต่ละชนิด ก็มีหน้าที่ แตกต่างกันไป ดังแสดง ในรูป

การสร้าง Control สามารถทำได้ 2 วิธี วิธีแรก คือการสร้าง ด้วยการเขียนโค้ด โดยตรง โดยการสร้าง วัตถุเป้าหมาย (object) ของคลาส ของ Control ที่เราต้องการ แล้วใช้คำสั่ง Create( ) ในการแสดง หน้าต่างของ Control นั้น ๆ ออกมา บนหน้าต่างแม่ (Parent window) อีกทีหนึ่ง เช่น

/*สร้าง Object ของคลาสปุ่มกด ในตอนประกาศคลาสของหน้าต่างแม่ (parent window)*/
CButton mybutton;

/*สร้าง หน้าต่าง ของปุ่มกด ออกมา ในตอน สร้างหน้าต่างแม่ (parent window)*/
mybutton.Create("Button1",
                             BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,
                             CRect( 10, 10, 80, 40),
                             this,
                             IDC_BUTTON1);

จะเห็นว่าการสร้าง Control ด้วยวิธีนี้ ต้องเขียนโค้ด คำสั่งมาก และ มีปัญหาในการ จัดวางตำแหน่ง ของ Control ให้ได้ ตำแหน่งตาม ต้องการ
ดังนั้น นักเขียนโปรแกรม ส่วนใหญ่มัก จะหันมาใช้วิธีที่สอง คือการสร้าง Control ลงบน Dialog box ด้วย Dialog editor ซึ่งจะช่วย ให้การจัดวาง ตำแหน่งของ Control ทำได้ง่ายขึ้น ดังนั้น ตัวอย่างใน บทนี้ เราจะ ใช้ dialog editor มาใช้ในการวาง control ลงบน dialog box ทั้งหมด เพื่อให้สามารถ ปรับตำแหน่ง ของ control ได้ตามต้องการ โดยหนูแจ๋วขออนุญาต พูดถึง control ที่ใช้บ่อย ๆ เท่านั้นนะคะ ส่วน control อื่น ๆ ให้เพื่อน ๆ หารายละเอียด เพิ่มเติมได้ จาก MSDN ค่ะ

1.Picture control
control ตัวแรก ที่เราจะพูดถึง คือ picture control ซึ่ง จริง ๆ แล้ว ก็เป็น static control แบบหนึ่งนั่นเองค่ะ แต่เป็น control ที่ใช้ในการ แสดงภาพบิตแมพ (bitmap) ออกมาบน หน้าต่างแม่ ได้ โดยก่อนที่จะ นำภาพบิตแมพ มาแสดง เราต้อง นำภาพบิตแมพ มาทำเป็น resource ของโปรแกรมเราเสียก่อน โดยให้เราสร้างภาพ ที่ต้องการ ด้วย โปรแกรมอะไร ก็ได้ หรือจะหาภาพ จากที่อื่น ๆ มาก็ได้ แต่ต้อง เป็นภาพชนิดบิตแมพ คือมีนามสกุล เป็น .bmp เท่านั้น จากนั้น ให้ทำการแทรก ภาพนี้เข้าไป ใน resource file ของเรา โดยในตอนนี้ หนูแจ๋ว จะแทรกเข้าไปใน resource file ของ โปรแกรมแบบ Dialog base ที่เราเขียนขึ้น ในบทที่แล้ว นะคะ โดยให้เราเปิด Project work space ของ โปรแกรม ที่เราเขียนขึ้น ในบทที่แล้ว จากนั้นให้เลือก เมนู insert -> resource ก็จะได้ หน้าจอ insert resource ดังแสดงในรูป ให้เลือก insert bitmap แล้วคลิ๊กปุ่ม import ค่ะ

ก็จะเข้าสู่หน้าจอ import resource ให้เลือกช่องชนิดของไฟล์ (file of type) เป็น All file แล้วเลือกไฟล์รูป .bmp ที่เราต้องการ จากนั้นให้คลิ๊กปุ่ม import

จะได้หน้าจอของ bitmap editor ขึ้นมา ซึ่งเราสามารถแก้ไข รายละเอียดของรูป ได้ตามใจชอบ (*** แต่ถ้ารูป bitmap ที่ import เข้ามา มีสีมากกว่า 256 สี ***) จะไม่สามารถเรียก bitmap editor ขึ้นมาได้ เพราะ bitmap editor ของ Visual studio มีความสามารถ ในการแก้ไขภาพ bitmap ที่มีสีได้ไม่เกิน 256 สี เท่านั้น แต่ถ้ามีสี มากกว่านี้ ภาพก็สามารถ แสดงได้ แต่ไม่สามารถแก้ไขได้ ใน bitmap editor เท่านั้นเองค่ะ ตอน นี้ถ้าเรา คลิ๊กดูที่ resource view ก็จะเห็นว่า ภาพ bitmap ถูกโหลด มาไว้ใน resource file เรียบร้อยแล้ว โดยมี ID เป็น IDB_BITMAP1 ดังแสดงในรูปค่ะ

คราวนี้ เรามาเปิด Dialog box ที่มี ID เป็น IDD_DIALOG1 ขึ้นมา โดยการดับเบิ้ลคลิ๊ก ที่ Dialog resource ที่มี ID เป็น IDD_DIALOG1 ก็จะเข้าสู่ หน้าจอของ Dialog editor จากนั้น ให้ใช้เมาส์ คลิ๊กแล้วลาก เอา picture control มาวางบน Dialog box ดังแสดงในรูป

เรามาปรับแต่ง คุณสมบัติ ของ picture control ให้สามารถ แสดงภาพ bitmap ที่เราต้องการ โดย ใช้เมาส์ คลิ๊กขวา ที่ picture control จะได้ short cut menu ขึ้นมา ให้เลือกหัวข้อ properties ก็จะได้ หน้าจอ picture properties ให้เลือกชนิด (type) ของภาพ เป็นแบบ bitmap และในช่อง image ให้เลือก bitmap resource ที่มี ID เป็น IDB_BITMAP1 ซึ่งก็คือภาพ bitmap ที่เรา import เข้ามา ในขั้นตอนแรก นั้นเองค่ะ

ภาพ bitmap ที่เราเลือกไว้ ก็จะมาปรากฏ บน dialog box editor ดังแสดงในรูป ให้ใช้เมาส์ คลิ๊กแล้วลาก ให้ภาพอยู่ใน ตำแหน่งที่สวยงาม

ลอง build โปรแกรม แล้วลอง execute ดู ก็จะได้หน้าตา ของ dialog box พร้อมกับมี ภาพ bitmap แสดงอยู่ ดังในรูป
จะเห็นว่า เราสามารถ นำภาพ bitmap มาใส่ไว้ใน dialog box ของเราได้ง่าย โดยไม่ต้องเขียน โค้ดโปรแกรมเลย แม้แต่บรรทัดเดียว โดยใช้ picture control นี้เองค่ะ โดย resource editor จะเพิ่มโค้ด เกี่ยวกับ การกำหนด ค่าต่าง ๆ ลงไปในไฟล์รีซอร์ทสคริปท์ ซึ่งในกรณี ของ โปรแกรมที่เราสร้างขึ้น ก็คือไฟล์ resource.rc นั้นเองค่ะ ถ้าเพื่อน ๆ สงสัยว่า มีการเพิ่มโค้ด อะไรลงไปบ้าง ก็ลองเปิด ไฟล์ resource.rc ดูนะคะ


2.Button control
control ตัวที่สอง ที่เราจะพูดถึง คือ ปุ่มกดนั่นเองค่ะ ในบทแรก ๆ เราได้มีการ ใช้ control ตัวนี้ มาบ้างแล้ว แต่คราวนี้ เราจะมา กล่าวถึง ในรายละเอียด เพิ่มเติมนะคะ
เรารู้ว่า ปุ่มกด ก็คือ control ตัวหนึ่ง ซึ่งคอยรับข้อมูล จากผู้ใช้งาน เมื่อผู้ใช้งาน ใช้เมาส์คลิ๊ก ที่ปุ่มกดนี้ ก็จะ มีการ ส่งแมสเสจ BN_CLICKED (Button Notification message CLICKED) กลับมาให้ หน้าต่างแม่ ของปุ่มกดนี้ ซึ่งในที่นี้ก็คือ หน้าต่างของ dialog box ที่เราใช้เป็น หน้าต่างหลักของโปรแกรมนั่นเอง โดยเรา จะดักจับ Message นี้ได้ ด้วยมาโคร ON_BN_CLICKED( ) ซึ่งมีรูปแบบดังนี้

	ON_BN_CLICKED( id, memberFxn ) 
	โดย 	id ก็คือ หมายเลย ID ของปุ่มที่ถูกกด
		memberFxn( ) ก็คือ ฟังก์ชั่นที่ จะถูกเรียก เพื่อตอบสนอง ต่อการกดปุ่มนี้
คลาสที่ ทำหน้าที่ ควบคุมปุ่มกด นี้ ก็คือ CButton นั่นเอง แต่ตอนนี้ เรา ยังไม่ได้ใช้งาน คลาส CButton นี้ เพราะ เรายังไม่จำเป็นต้อง มีการควบคุม ปุ่มกดนี้ เป็นกรณีพิเศษ แต่เราจะ ได้เรียนรู้ การใช้งานคลาส CButton ในหัวข้อต่อไป ค่ะ

เริ่มเขียนโปรแกรม เราลองมา เขียนโค้ด เพื่อทดสอบ การใช้งานปุ่มกด กันนะคะ โดยเราจะ นำโปรแกรมแบบ dialog base ที่เขียน ขึ้นในบทที่แล้ว มาเพิ่มเติม ปุ่มกด ลงไปอีกหนึ่งปุ่ม โดยเปิด โปรเจค ที่เราเพิ่งใส่ picture control ลงไปเมื่อกี้ แล้ว ดับเบิ้ลคลิ๊ก ที่ไดอะล็อก ที่มี ID เป็น IDD_DIALOG1 ก็จะเปิด Dialog editor ของไดอะล็อก IDD_DIALOG1 ขึ้นมา จากนั้น ให้ลาก เอา button control ลงไปวางใน Dialog box ของเรา

ให้คลิ๊กเมาส์ขวา บน button control แล้วเลือกหัวข้อ properties บน short cut menu เพื่อ เปิดหน้าต่าง การปรับตั้ง คุณสมบัติของ button control นี้ ให้เรา แก้ไขค่า ID ของปุ่มกด เป็น IDC_INPUT และแก้ค่า caption เป็น &Input Dialog เพื่อเปลี่ยน ตัวอักษรบนปุ่มกดนี้ ให้เป็น Input Dialog ดังแสดง ในรูป

เมื่อเสร็จสิ้น การสร้างปุ่มกด ลงบน dialog หลักของโปรแกรม แล้ว เราก็จะมา สร้าง dialog อันที่สอง ขึ้นมา เพื่อทดสอบ การทำงาน ของปุ่มกด ของเรา โดย ให้เลือกเมนู Insert -> Resource จะได้หน้าต่าง ของ การ Insert Resource ขึ้นมา ให้เลือกหัวข้อ Dialog แล้วคลิ๊กปุ่ม New เพื่อเป็นการสร้าง Dialog box ขึ้นมาใหม่

จะเห็นว่า ใน resource view จะมี Dialog box ใหม่เกิดขึ้นมา โดยมี ID เป็น IDD_DIALOG2 เราสามารถ เปลี่ยนค่า ID นี้เป็นอะไรก็ได้ ตามใจชอบ แต่ในที่นี้หนูแจ๋ว คงค่า ID ไว้เหมือนเดิมค่ะ

เมื่อ สร้าง Dialog อันที่สอง เรียบร้อยแล้ว ต่อไปก็เป็น ขั้นตอน การสร้าง Class เพื่อมาห่อหุ้ม dialog box อันที่สองนี้ โดยให้เราเลือกเมนู File -> new แล้วเลือกสร้าง header ไฟล์ โดยให้ชื่อเป็น inputdialog.h แล้ว เขียนโค้ด ของการประกาศคลาส ของ Dialog อันที่สอง ลงไป ดังต่อไปนี้ค่ะ
/*File inputdialog.h */
/* Dialog derived class */

#include <afxwin.h>
#include "resource.h"

class CInputDialog : public CDialog
{
  public:
              /* function constructor */
	CInputDialog( );
               
	afx_msg void OnOK();     // function handler OnOK 
	afx_msg void OnCancel(); // function handler OnCancel
 	
	/* ประกาศการ map message */
	DECLARE_MESSAGE_MAP()
 };
จากนั้น ให้สร้างไฟล์ใหม่ อีกไฟล์หนึ่ง ให้เป็นไฟล์ชนิด .cpp โดย ตั้งชื่อเป็น inputdialog.cpp แล้วเขียนโค้ด ต่อไปนี้ลงไป
/*File inputdialog.cpp */
/* CInputDialog class implementation */
#include "inputdialog.h"

/* message map */
BEGIN_MESSAGE_MAP(CInputDialog,CDialog)

END_MESSAGE_MAP()

/* function constructor ของ CInputDialog ซึ่งไปเรียกใช้ function constructor
   ของ CDialog โดยส่ง ID ของไดอะล็อกบอกซ์ อันที่สอง ที่สร้างขึ้นไปให้ด้วย */
CInputDialog::CInputDialog():CDialog(IDD_DIALOG2,NULL)
{
}
ก็เป็นอัน เสร็จสิ้นการ สร้าง class มาห่อหุ้ม Dialog box อันที่สอง ต่อไป ก็เป็นการเพิ่มเติม โค้ดคำสั่ง ในไฟล์ ของ Dialog หลักของเรา ให้สามารถ กดปุ่ม เพื่อเรียก Dialog อันที่สอง ให้แสดงออกมา บน จอภาพได้ โดยให้เรา เปิดไฟล์ ที่ประกาศคลาส ของ Dialog หลักของ โปรแกรม คือไฟล์ mydialog.h ขึ้นมา เพื่อ เพิ่มเติม การประกาศ ฟังก์ชั่น ที่จะถูกเรียกใช้ เมื่อมีการกดปุ่ม Input Dialog ดังแสดงต่อไปนี้
/*File mydialog.h */
/* Dialog derived class */

#include <afxwin.h>
#include "resource.h"

class CMyDialog : public CDialog
{
  public:
              /* function constructor */
	CMyDialog( );
	
	afx_msg void OnInputDialog();// ประกาศ ฟังก์ชั่น ที่จะถูกเรียกใช้ เมื่อกดปุ่ม Input dialog
 	
	/* ประกาศการ map message */
	DECLARE_MESSAGE_MAP()
 };
แล้ว เราก็มาทำการเพิ่มเติม โค้ดเพื่อเรียก ใช้ Dialog อันที่สอง นี้ โดยเปิดไฟล์ mydialog.cpp มาเพิ่มเติม โค้ด คำสั่งลงไป ดังต่อไปนี้
/*File mydialog.cpp */
/* CMyDialog class implementation */
#include "mydialog.h"
#include "inputdialog.h" // include ไฟล์ header ที่ประกาศคลาส dialog อันที่สอง ลงไปด้วย


/* message map */
BEGIN_MESSAGE_MAP(CMyDialog,CDialog)
   ON_BN_CLICKED(IDC_INPUT,OnInputDialog)// ดักจับ แมสเสจ BN_CLICKED ที่ส่งออกมาจาก ปุ่มกด 
                                                                                  //IDC_INPUT แล้ว ไปเรียกฟังก์ชั่น OnInputDialog () ให้ทำงาน
END_MESSAGE_MAP()

/* function constructor ของ CMyDialog ซึ่งไปเรียกใช้ function constructor
   ของ CDialog โดยส่ง ID ของไดอะล็อกบอกซ์ ที่สร้างขึ้นไปให้ด้วย */
CMyDialog::CMyDialog():CDialog(IDD_DIALOG1,NULL)
{
}

// function handler ที่ถูกเรียกให้ทำงาน เมื่อมีการกดปุ่ม IDC_INPUT 
afx_msg void CMyDialog::OnInputDialog()
{ 
  CInputDialog d1;// สร้าง object ของ คลาส Dialog อันที่สอง (CInputDialog)
  d1.DoModal(); // สร้าง dialog อันที่สองให้เป็น dialog แบบ Modal 
}
จากนั้น ให้ save ไฟล์ แล้ว build โปรแกรม แล้วจึง execute ดู ถ้าไม่มี อะไรผิดพลาด เราจะได้หน้าต่าง หลัก ของโปรแกรม ของเรา ออกมา ดังแสดงในรูป

เมื่อเรา คลิ๊กปุ่มกด Input Dialog ก็จะมีการ สร้าง Dialog อันที่สอง ขึ้นมา ซึ่งเป็น Dialog แบบ Modal คือเมื่อ เปิดขึ้นมาแล้ว เราไม่สามารถ คลิ๊กกลับไป ที่หน้าต่างหลัก ของโปรแกรมได้อีก จนกว่า จะ Dialog อันที่สอง นี้ จะปิดไปเสียก่อน

เขียนมาตั้งนาน เพิ่งจะพูดถึง control ไป 2 ตัวเอง คือ picture control และ button control คงต้องยก เรื่อง ของ control อื่น ๆ ไปเป็นตอนหน้า ล่ะค่ะ หวังว่า เพื่อนคง ได้ ไอเดีย จากบทความตอนนี้ ไม่มากก็น้อย นะคะ แล้ว ในบทความคราวหน้า หนูแจ๋วจะ พูดถึง control อื่น ๆ ต่อไปค่ะ

หนูแจ๋ว

Hosted by www.Geocities.ws

1