คือผมไม่ได้ต้องการที่จะกำหนดให้มันไปทำงานที่โปรแกรมใดโปรแกรมหนึ่งอ่ะครับ แต่ให้ทำมันหมดเลย เช่นสมมุติว่าผมจะทำให้ปุ่ม Ctrl เป็นปุ่ม PrintScreen ไรเงี้ยอ่ะครับ ผมก็ใช้ SendKeys.SendWait() ไปเรียกปุ่ม PrintScreen เมื่อมีการกดปุ่ม Ctrl มันก็ใช้ได้เลย แต่พอผมเปลี่ยนคำสั่งไปเป็น SendKeys.Send() มันดันขึ้น
SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method.
มันก็อาจเป็นเพราะผมไม่ได้ไปกำหนดมั้งครับว่าให้มันใช้ได้กับโปรแกรมอะไร(เดาเอา) ก็เพราะว่าปุ่ม PrintScreen ไม่ว่าจะอยู่โปรแกรมอะไร มันต้องทำงานได้ ทีนี้ผมเลยสงสัยความแตกต่างระหว่าง SendKeys.Send() กับ SendKeys.SendWait() ครับ ไม่เข้าใจว่า sendwait มันรออะไร ต่างกันยังไง กลัวใช้มันไปแบบไม่ค่อยเข้าใจว่ามันต่างกันยังไง แล้วมันจะทำอะไรได้ไม่ตรงแบบที่ต้องการอ่ะครับ อิอิ..
ข้อความผิดพลาดข้างบนต้องเป็นคนที่เคยเล่นกับ message มาบ้างถึงจะเข้าใจครับ
message ในที่นี้คือ windows system message เป็นรหัสขนาด 16 บิท (มั้งจำไม่ได้ = =)
เอาเป็นสั้นๆ ว่าถ้าจะใช้ SendKeys.Send() ก็ต้อง overrides wndproc ที่ระดับ Form ครับ
จะพยายามอธิบายสั้นๆ นะครับ
ใน 1 window (form) หรือ control ใดๆ ก็ตาม จะมีการเขียนตัวดัก message เอาไว้ (message handler) เมื่อเรากระทำการใดๆ เช่น กดคีย์บอร์ด, กดเมาส์ หรือแม้กระทั่ง กดย่อ/ขยาย/ปิด window, สลับหน้า ฯลฯ ก็จะมีการส่ง message ไปให้ message handler จัดการ
แม้กระทั่ง control อื่นๆ เช่น button, textbox อะไรก็แล้วแต่ ... ในการทำงานระดับต่ำมันก็ต้องส่ง event เข้า wndproc ของ Form ทั้งหมด (low level, ระดับ API ของ Windows)
message handler ตัวนี้ก็คือ wndproc นี่เอง ...
แต่ว่า Visual Studio เอา message กับ message handler มา re-brand ใหม่ แล้วเรียกให้มันเข้าใจง่ายขึ้นว่า event, event handler ก็ไอ้จำพวก button.onclick, textbox.onchange อะไรนั่นล่ะครับ
ถ้ายังงงก็ Google คำว่า C# wndproc ละกัน แต่ถ้าอยากเข้าใจสารตั้งต้น ก็แนะนำให้ค้นหาเรื่อง Windows Message อีกทีนึงครับ
ก็นะ ... พูดถึงเรื่องนี้แล้วหัวใจมันเต้นตุบตับครับ จำได้ว่าตอนศึกษาเรื่องนี้แล้วรู้สึก "orgasm" เลยทีเดียว
เขียนคำชวนโปรยท้ายหน่อยๆ ... hacker ก็ใช้ความรู้อันนี้ทำตัว keylogger นี่แหละครับ
อ้าว ... ลืม SendKeys.SendWait
รอคนอื่นละกัน เพราะผมไม่รู้จัก อิอิ
ขอบคุณ คุณ PaPaSEK และคุณ Invisible Force มากครับ
คือตรงคำว่า wait for the keystroke messages to be processed. เนี่ยแหละครับ ที่ผมอ่านแล้วไม่เข้าใจ 55+
อยากรู้ว่า ไม่รอ keystroke messages to be processed กับ รอ keystroke messages to be processed มันต่างกันยังไง เพราะถ้าผมใช้ sendwait มันก็ทำงานได้อย่างที่ผมคิดเอาไว้แล้วนะครับ คือไม่ว่าจะอยู่ที่โปรแกรมอะไร มันก็กดให้ผม เช่นให้มันไปกดปุ่ม PrintScreen ให้ผมไรเงี้ยอ่ะครับ แต่ที่ผมกลัวคือ ใช้มันไปแบบไม่ค่อยเข้าใจแล้วมันจะไปทำอะไรเกินความต้องการของผมอ่ะสิครับ อิอิ เลยอยากจะเข้าใจเรื่อง keystroke messages มันทำงานเสร็จกับไม่เสร็จหน่อยอ่ะครับ ว่ามันต่างกันยังไง..
ผมไม่แน่ใจนะครับว่ากระบวนการใน SendKeys.Send กับ SendKeys.SendWait จะเหมือนกับการใช้ winapi หรือเปล่า แต่ถ้าพูดถึงเฉพาะในส่วนของ winapi จะมีฟังค์ชั่นชื่อ SendMessage และ PostMessage
โดยทั้ง 2 ฟังค์ชั่นนี้ทำงานเหมือนกันก็คือ ส่ง window message ไปยัง window ที่กำหนด(โดยใช้ hwnd หรือ window handle ใส่เข้าไปเป็น parameter)
แต่สิ่งที่แตกต่างกันก็คือ SendMessage จะทำการส่ง message และรอจนกว่า window เป้าหมายจะทำการ process message เสร็จเรียบร้อยจึงจะ return ออกมาจาก function
แต่ PostMessage จะทำการส่ง message เข้าไปยัง message queue ของ window เป้าหมาย และ return ออกจาก function ทันทีโดยไม่รอให้ message ถูก process
ตอนนี้ผมได้พบอะไรบางอย่างจากการทดสอบการใช้งานอย่างง่ายๆของ SendKeys.Send() กับ SendKeys.SendWait() แล้วครับ เพราะผมหล่ะ งง สุดๆว่า ทำไมตัวอย่างมากมายจากใน internet มันดันทำได้แบบชิวๆ แต่ทำไมผมก็ดูแล้วดูอีก มันก็ทำไม่ได้ ผมเลยลองสร้างปุ่มกดเรียก SendKeys.Send("{PRTSC}") ไปเลย ระหว่าง WinForm กับ WPF เริ่มต้นด้วย WinForm มันก็ทำได้แบบชิวๆ ต่อมาก็เลยลองกับ WPF ดูบ้าง ชัดเจนเลยครับ มันทำไม่ได้ มันขึ้น
SendKeys cannot run inside this application because the application is not handling Windows messages. Either change the application to handle messages, or use the SendKeys.SendWait method.
สรุปคือใน WPF มันเรียกใช้ SendKeys.Send() แบบตรงๆเหมือน WinForm ไม่ได้แน่นอน ส่วนมันจะมีวิธีทำให้ใช้ได้ยังไง อันนี้ผมไม่รู้ละ ต้องค้นหาต่อไปว่า 2 อันนี้มันใช้แทนกันได้ไหม T^T
การที่จะต้องมี Wait หรือไม่ มันไม่ได้ต่างกันที่การจะส่งค่าออกไปครับ .. มันต่างกันที่ระดับการออกแบบหรือความต้องการของการ communicate ระหว่างโปรแกรมครับ คือ
ถ้าเราต้องการให้มี Wait เพื่อรอในสิ่งที่เราออกคำสั่งไป .. ก็แสดงว่าเราต้องการมั่นใจว่าสิ่งที่ออกคำสั่งไปนั้นได้ถูกกระทำเรียบร้อย เพื่ออะไร เพื่อว่าถ้ามันมีปัญหาเกิดขึ้น เราจะได้ออกคำสั่งซ้ำไปใหม่ได้ครับ
รบกวนช่วยยกตัวอย่างง่ายๆ ให้ฟังหน่อยได้มั้ยครับ ผมยังงงกับ wait for the keystroke messages to be processed. อยู่เลยครับ
การส่ง Keystroke ไม่ได้ใช้เฉพาะการส่งข้อความเท่านั้น .. Keystroke ยังสามารถส่งคำสั่งทาง Keyboard ให้โปรแกรมเปิดทำงานได้
ดังนั้นในกรณี ที่เกี่ยวข้องกับสิ่งที่เป็นคำสั่ง เช่นให้เปิดโปรแกรม และหากเราต้องมีการส่ง Keystroke message ถัดไปต่ออีกด้วย เช่นให้สั่งบันทึกไฟล์หลังจากที่เปิดนี้ทันที .. เราจะติดปัญหาว่าการส่ง Keystroke ครั้งที่สองจะไม่สามารถส่งต่อทันทีเพราะว่าจะต้องรอให้ Keystroke คำสั่งก่อนหน้านี้ที่สั่งให้โปรแกรมเปิดขึ้นมานั้นเสร็จเรียบร้อยก่อน .. ปัญหาคือเราจะรู้ได้อย่างไรว่าโปรแกรมจะใช้เวลาเปิดขึ้นมา มากน้อยเท่าใด ซึ่งอาจจะไม่เท่ากันในแต่ละครั้งก็ได้ .. หากเราใช้คำสั่ง Sendwait ก็จะง่ายกว่า เพราะไม่ต้องมากำหนดเวลาหน่วงเอาไว้ ระบบก็จะรอจนกว่าคำสั่งก่อนหน้าทำงานเสร็จแล้วจึงทำคำสั่งถัดไปให้
(ทั้งหมดนี้เป็นการคาดการณ์ครับ..อิอิ)
อ่า พอเห็นภาพละครับ ถึงจะเป็นแค่คาดการณ์ก็เถอะ อิอิ