ข้อมูลจาก Iczelion
เราจะศึกษาว่าวินโดว์โพรซิเยอร์สามารถรับและตอบสนองต่อเมาส์ได้อย่างไร โดยตัวอย่างโปรแกรมในบทนี้จะรอการคลิ๊กเมาส์แล้วจึงแสดงข้อความ ณ ตำแหน่งที่คลิ๊กเมาส์นั้นใน client area ของวินโดว์
วินโดวส์จะตรวจสอบและส่งเมสเสจเตือนถ้ามีการทำงานของเมาส์ไปยังวินโดว์ที่เมาส์ทำงานอยู่คล้ายๆ กับการทำงานกับคีย์บอร์ด การทำงานของเมาส์นั้นมีทั้งการคลิ๊กซ้าย คลิ๊กขวา การเคลื่อนที่บนวินโดว์ รวมทั้งการดับเบิ้ลคลิ๊กด้วย แต่ที่ต่างจากคีย์บอร์ดก็คือถ้าเป็นคีย์บอร์ด เมสเสจที่ส่งมาจะเป็นเมสเสจของวินโดว์ที่กำลังรับโฟกัสอยู่ ส่วนเมาส์นั้นจะส่งไปยังวินโดว์ใดก็ตามที่เมาส์เคลื่อนที่อยู่ด้านบน ไม่ว่าวินโดว์นั้นจะแอกทีฟอยู่หรือไม่ รวมทั้งเมสเสจของเมาส์ที่อยู่นอก client area ของวินโดว์ด้วย แต่เรากล่าวถึงเฉพาะส่วนที่อยู่ใน client area
เมสเสจที่เกี่ยวกับการทำงานของปุ่มของเมาส์ มี WM_LBUTTONDOWN,WM_RBUTTONDOWN และ WM_LBUTTONUP, WM_RBUTTONUP สำหรับเมาส์ที่มีสามปุ่มจะมีเมสเสจเพิ่มขึ้มมาคือ WM_MBUTTONDOWN และ WM_MBUTTONUP. วินโดวส์จะส่งเมสเสจ WM_MOUSEMOVE ไปยังวินโดว์ที่เมาส์เคลื่อนที่อยู่บน client area ของวินโดว์นั้น
วินโดว์จะสามารถรับเมสเสจการดับเบิ้ลคลิ๊ก WM_LBUTTONDBCLK หรือ WM_RBUTTONDBCLK ก็ต่อเมื่อคลาสของวินโดว์นั้นมีสไตล์แฟล็ก CS_DBLCLKS อยู่ด้วย มิฉะนั้นวินโดว์ก็จะรับได้แค่เมสเสจที่เกี่ยวกับการกดหรือปล่อยปุ่มเมาส์เท่านั้น
เมสเสจดังกล่าวที่ส่งมานั้นจะส่งมาพร้อมกับ wParam และ lParam ตำแหน่งของเมาส์ที่ส่งเมสเสจเข้ามาจะอยู่ที่ lParam โดยตำแหน่ง x จะอยู่ที่ low word ส่วน y จะอยู่ที่ high word ของ lParam เมื่อเทียบกับมุมบนซ้ายของ client area ส่วนค่าของ wParam จะเป็นสถานะของปุ่มเมาส์และคีย์ Shift และ Ctrl
|
.ELSEIF uMsg==WM_LBUTTONDOWN mov eax,lParam and eax,0FFFFh mov hitpoint.x,eax mov eax,lParam shr eax,16 mov hitpoint.y,eax mov MouseClick,TRUE invoke InvalidateRect,hWnd,NULL,TRUE |
โพรซิเยอร์ของวินโดว์จะรอรับการคลิ๊กปุ่มซ้ายของเมาส์ เมื่อรับเมสเสจ WM_LBUTTONDOWN เข้ามา lParam จะเป็นตำแหน่งของเมาส์ใน client area และจะเก็บตำแหน่งนี้ในตัวแปรที่มีโครงสร้างแบบ POINT ซึ่งมีรูปแบบดังนี้
POINT STRUCT x dd ? y dd ? POINT ENDS |
แล้วจึงเซ็ทตัวแปร MouseClick ให้มีค่าเป็น TRUE เพื่อให้ทราบว่าอย่างน้อยมีการคลิ๊กปุ่มซ้ายของเมาส์ภายใน client area ของวินโดว์
mov eax,lParam and eax,0FFFFh mov hitpoint.x,eax |
เพราะว่าจุดโคออดิเนตของ x จะอยู่ที่ low word ของ lParam และเมมเบอร์ของ POINT เป็นตัวแปรแบบ 32 บิต จึงต้องกำหนดค่าด้วยรีจิสเตอร์ 32 บิตด้วย ดังนั้นจึงต้องทำให้ high word ของ eax เป็นศูนย์เสียก่อนด้วยคำสั่ง and eax,0FFFFh ก่อนที่จะเก็บค่าใส่ในตัวแปร hitpoint.x
shr eax,16 mov hitpoint.y,eax |
และจุดโคออดิเนต y เก็บอยู่ที่ high word ของ lParam จึงด้อง shift รีจิสเตอร์ eax ไปทางขวา 16 บิต เพื่อให้ low word เป็นค่าของโคออดิเนต y และ high word เป็นศูนย์ก่อนที่จะเก็บค่าลงตัวแปร hitpoint.y
หลังจากเก็บค่าตำแหน่งของเมาส์แล้ว เราเซ็ตค่า MouseClick ให้เป็น TRUE เพื่อให้โค้ดของการวาดหน้าจอในส่วน WM_PAINT ทราบว่าอย่างน้อยมีการคลิ๊กเมาส์ซ้ายภายใน client area จึงสามารถวาดตัวอักษร ณ ตำแหน่งที่มีการคลิ๊กเมาส์ หลังจากนั้นจึงเรียกฟังก์ชั่น InvalidateRec เพื่อบังคับให้วินโดว์วาดพื้นที่ client area ทั้งหมดใหม่
.IF MouseClick invoke lstrlen,ADDR AppName invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR AppName,eax .ENDIF |
โค้ดในส่วนของ WM_PAINT จะตรวจสอบตัวแปร MouseClick ว่ามีค่าเป็น TRUE หรือไม่ ถ้ามีค่าเป็น TRUE ก็จะทำการวาดตัวอักษรลงไปในตำแหน่งที่คลิ๊กเมาส์ แต่ในตอนเริ่มโปรแกรมไม่ควรจะมีตัวอักษรปรากฏขึ้นบน client area ดังนั้นจึงต้องกำหนดค่าของ MouseClick ให้มีค่าเป็น FALSE และจะเปลี่ยนเป็น TRUE เมื่อมีการคลิ๊กเมาส์ซ้ายเกิดขึ้น
เมื่อมีการคลิ๊กเมาส์มันจะเรียกฟังก์ชั่น lstrlen เพื่อหาค่าความยาวของตัวอักษร (AppName) ที่จะแสดงบนหน้าจอ ค่าความยาวของตัวอักษรที่ให้กลับมาจะเก็บไว้ที่ตัวแปร eax แล้วจึงนำไปใส่ในพารามิเตอร์สุดท้ายของฟังก์ชั่น TextOut เพื่อให้พิมพ์ตัวอักษรออกมา