PracticU

שגרת החלון

בלי כתוביותעם כתוביות
PracticU › קורס C למתקדמים - עבודה מול חומרה Win32 › שגרת החלון
מילון מושגים:
פונקציה - קטע קוד בעל שם שמבצע משימה מוגדרת, מקבל ערכי קלט (פרמטרים) ויכול להחזיר תוצאה. מאפשרת לארגן קוד ולהשתמש בו שוב.
כפתור - רכיב בממשק המשתמש שהמשתמש לוחץ עליו כדי להפעיל פעולה, כמו שליחת טופס או מעבר לדף אחר.
משתנה - שם שמפנה למקום בזיכרון שבו נשמר ערך שיכול להשתנות במהלך ריצת התוכנית, כמו מספר, טקסט או אובייקט.

שגרת החלון
ההרצאה מסבירה את שגרת החלון (Window Procedure) ב-Win32: מה היא מקבלת, איך מטפלים בהודעת הסגירה, ואיך אפשר להחליף את השגרה של חלון קיים בשגרה משלנו.
השלבים העיקריים
1. הודעת הסגירה: כשהמשתמש לוחץ על X, נשלחת הודעה WM_CLOSE לשגרת החלון. אם לא מטפלים בה, הפונקציה DefWindowProc סוגרת את החלון.
2. אפשרות לא לסגור: בתוך השגרה אפשר לשאול את המשתמש, ואם הוא בוחר לא, מחזירים 0 ולא מסיימים. ההרצאה מדגימה שאם בוחרים כן, מסיימים את התוכנית.
3. סאב-קלאסינג: באמצעות SetWindowLong עם GWL_WNDPROC מחליפים את השגרה של חלון קיים (כמו כפתור או שדה טקסט) בשגרה משלנו. השגרה המקורית נשמרת ומופעלת דרך CallWindowProc.
4. טיפוס לשגרה: מגדירים typedef לפוינטר לפונקציה, כדי שהקאסטינג יהיה קריא יותר.
5. בעיה בין חלונות: החלפת שגרה של חלון אחד בשגרה של חלון אחר גורמת לקריסה, כי לכל חלון יש מבנה נתונים שהשגרה המקורית בונה. לכן כל חלון צריך לשמור את השגרה שלו בנפרד.
6. שמירה ב-GWLP_USERDATA: ההרצאה שומרת את השגרה המקורית של כל חלון בשדה המשתמש של החלון (user data), וזה מאפשר להפעיל אותה לפי ה-HWND.
שימו לב
המרצה מזהירה שכשמשתמשים במשתנה גלובלי לשמירת הפוינטרים, הקוד נשבר כשיש כמה חלונות. לכן עדיף לשמור את הפוינטר בתוך החלון עצמו.
השיעור הבא בקורס: סיכום - בניית חלון מאפס

פרקי ההרצאה: שגרת החלון

  1. 00:00

    המשך הפרויקט מההרצאה הקודמת

  2. 00:40

    לולאה אינסופית לטיפול בהודעות

  3. 01:31

    ערכי ההחזרה של WndProc

  4. 02:31

    איך החלון אמור להתנהג בלחיצה על X

  5. 03:43

    סגירת החלון מול סגירת האפליקציה

  6. 04:38

    החלפת הפונקציה המטפלת בחלון

  7. 05:56

    שמירת הפונקציה המקורית במשתנה

  8. 13:57

    Subclassing: חדירה לחלון קיים

תמלול ההרצאה: שגרת החלון

הטקסט המלא של הדקות הראשונות בהרצאה «שגרת החלון» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.

  1. 00:04

    טוב, אז אנחנו רוצים להמשיך מה שהתחלנו בהרצאה הקודמת. בואו נפתח Visual Studio, Simple Dialog Sample 101. נסגור את זה, הנה הוא, נפתח? לא, לא נפתח, לחמת אחרים...

  2. 00:22

    זה. יפה, אז זה היה לנו כבר ווינפור. אז רצינו בהרצאה הקודמת לעשות שהם, אוקיי, אז היוזר לחץ על X, X זה Close, בבקשה לסגירה. בבקשה לסגירה, אם אתה רוצה לסגור, אם כן, אז ניידע את מיין שאנחנו רוצים להסתכל על לולאה, זה לא בהכרח מיין, אבל ניידע את הלולאה האין

  3. 00:50

    סופית שאנחנו רוצים לסיים. ואז גילינו שאם אנחנו ממשיכים בהמשך אחרי פוסט מסג', זה לא פתאום היא יוצאת מהפונקציה, אלא היא ממשיכה, ממשיכים.

  4. 01:06

    ואז דף וינדו פוק מופעלת עבור קלוז, דף וינדו פוק עבור וינדו קלוז סוגרת את החלון, היא עושה דסטרוי וינדו, סוגרת את החלון, החלון נעלם, זה לא מה שרצינו במקרה שהיוזר רוצה no אם היוזר רוצה no לא רוצה לסגור אנחנו בכל מקרה מגיעים לפה לא טוב אז יש כל מיני אפשרויות לפתור את זה אפשרות אחת היא פשוט לשים פה

  5. 01:31

    return 0 או return 1 תלוי אני כבר זה זהו מה הרשמות של מה שאנחנו מחזירים אז האמת שכדאי קצת לקרוא ולהבין אנחנו לא נעשה את זה כרגע אם משהו לא יעבוד לנו אז ננסה לפתור את זה בוא ננסה לראות אם זה עובד ואז אם היוזר, אז אם אנחנו, רגע, רגע, סליחה.

  6. 01:59

    אם דווקא, סליחה, בכל מקרה, אם קיבלנו זה, אז אני רוצה זה, ככה וככה, נכון? אם קיבלתי קלוז, בין אם היוזר רוצה לסגור ובין אם הוא לא רוצה, רגע, אם הוא רוצה לסגור, אז דווקא עדיף לקרוא לזה, הוא רוצה לסגור, אז אני גם אגיד לאפליקציה ואני גם אסגור, נכון?

  7. 02:27

    טוב, האמת היא שאם אני, רגע, השאלה היא, השאלה היא בעצם למה התכוון המשורר? שהיוזר לוחץ, מה בעצם, כן, בעצם נשאלת השאלה, איך אנחנו היינו רוצים שהחלון שלנו יתנהג?

  8. 02:41

    הווינפרו קובע את ההתנהגות של החלון, איך היינו רוצים שהחלון יתנהג? כשהיוזר לוחץ על קלוז, מה אנחנו רוצים? שהחלון ייעלם או לא ייעלם?

  9. 02:51

    ובלי קשר לזה אנחנו רוצים, האם אנחנו רוצים שהאפליקציה תיסגר או לא תיסגר? כמובן שאם האפליקציה תיסגר אז גם החלון ייסגר, אבל אז זה כבר לא מעניין אותי, גם אם החלון יישאר בטוח, אבל הוא ייסגר, הכל ייסגר.

  10. 03:04

    השאלה הנשאלת היא איך אנחנו רוצים שהחלון יתנהג בדאבל עם קלוז, האם אני רוצה. השאלה היא קוויט מה? קוויט זה אפליקיישן או קוויט זה וינדו?

  11. 03:14

    אז בואו נגיד שהגיוני להגיד גם וגם, שאם אני רוצה קלוז, אם אני רוצה אכן לסגור, אז בסדר, אז אני סוגר, אם יצא לי שכן יקרה, לא יקרה, זה לא מעניין, אני סוגר, אבל אם אני רוצה לא לסגור, בוא נגיד לא קלוז לא קוויט אתה רוצה לסגור אותו לחלון קלוז דיס ווינדו ווינדו לסגור את החלון לא אקזיט המבלבל קוויט דיס ווינדו אה בעצם זה לא משנה בעצם קוויט אם אתה רוצה לסיים

  12. 03:48

    בקיצור האם אתה רוצה לסיים כן או לא אם אתה רוצה לסיים אני אטפל בהכל זה מטפל תכלס בהכל ואם אתה לא רוצה לסיים אם זה נו אז פה כתוב return אפס לפחות לא נגיע לזה שזה יסגור לנו אבל מה אם הוא רוצה לסגור את החלון ולא לסגור את האפליקציה?

  13. 04:15

    אז במקרה כזה אנחנו צריכים לסגור את החלון, זה כבר צריך טיפול אחר. אבל על זה נדבר בהזדמנות אחרת. בואו קודם כל נריץ את זה, נראה שזה עובד. אז אם הוא אומר no, החלון יישאר בחיים.

  14. 04:32

    אבל אם הוא אומר yes, אז כל האפליקציה תמות. יפה, סבבה. אוקיי, אתם מתחילים להבין איך הדבר הזה עובד, להצעה.

  15. 04:44

    יפה. טוב, לפני שנמשיך, הדבר הבא שאני רוצה להראות זו טכניקה מאוד עוצמתית בואו נראה מה מה שאני רוצה לעשות זה דבר כזה אוקיי אז עשינו קרנט ווינדו ואז החלפנו לו את הווין פרוק שלו עם ווין פרוק שלנו יפה מאוד ועכשיו הוא מפעיל את הווין פרוק שלנו אז בואו נגיד שהייתי רוצה שהוא יפעיל את הווין

  16. 05:13

    פרוק שלנו אבל שגם יפעיל את הווין פרוק שלו איך עושים דבר שכזה זאת אומרת הרי כאן אני מפעיל את הדיפולט ווינדו פרוק יפה מאוד, אבל הייתי רוצה לא להפעיל את הדיבוס ואינו פרוק, הייתי רוצה להפעיל את הווין פרוק המקורי.

  17. 05:29

    הווין פרוק המקורי גם לא להפעיל את הדיבוס ואינו פרוק עבור כל מיני דברים, אבל עבור דברים מסוימים, כמו התצוגה שהוא מראה כפתור ומראה כפתור נלחץ והוא מטפל.

  18. 05:43

    בקיצור הייתי רוצה שהוא כן יפעיל את הווין פרוק שלנו, וכמה שהייתי רוצה זה לא להפעיל את הדיבוס ואינו פרוק אלא להפעיל את הבדון פרוק, איפה הפרוק המקורי?

  19. 05:56

    יפה, אז מה שאני רוצה זה את הפרוק המקורי. אז איפה הפרוק המקורי? אז נעשה פה ctrl-shift-רווח. סבור שהפרוק המקורי, או כל דבר מקורי שבעצם הכנסנו לפה, הרי פה אני יכול להכניס כל מיני דברים, תלוי במה זה.

  20. 06:13

    אמרתי, תחליף את הווין פרוק המקורי, תדחוף את זה. כשאני אומר לו תדחוף את זה, כמו הרבה פונקציות של Windows API, שאומרים לו קבל הזוג זוג ומקיא החוצה את הישן.

  21. 06:27

    אז פה אני יכול להגיד לו, זה הישן. אז long, וזה ה-Original proc. יפה, זה ה-proc המקורי. יפה, עכשיו את ה-proc המקורי אני רוצה להעביר לחלון.

  22. 06:44

    אז איך אני אעביר? פה אני במיין, ושם איזה פונקציה אחרת. אז איך אני אעביר? אז אני יכול להעביר את זה כמשתנה גלובלי. נכון, אז זה יהיה winproc 1 ו-winproc 2. ותכף נראה, ננסה לעשות טכניקה אחרת, תרשום שאני רוצה להראות טכניקה אחרת.

  23. 07:03

    זה יהיה winprog2 יפה מאוד אבל אני רוצה לתקן משתנים גלובליים אז בואו ניקח את זה גרור וקרופי ואת זה אני מעיף ואת זה אני מעיף יפה אז יש לי את זה וקונטרול cv וזה אחד וזה שתיים נקודה פסיק נקודה פסיק ואנטר וזה משתנים גלובליים כל הכבוד הבעיה עם c++ משתנים גלובליים אם אני אנסה להשתמש בהם לפני

  24. 07:33

    אז הוא אמר אני רוצה פה לדחוף את הפונקציה המקורית שלי אז רגע אז אם אני אנסה פה בכלל לכתוב אוריג'ינל קונטרול רווח הוא בכלל לא מכיר את האוריג'ינל למה הוא לא מכיר את האוריג'ינל מי יודע אם c++ צריך הצהרה או הגדרה לפני אז ניקח את זה ונגרור את זה לכאן יפה מאוד יפה אז עכשיו

  25. 08:07

    זה לפני עכשיו בואו נראה אם הוא מכיר קונטרול רווח יפה אני רוצה להפעיל את זה טוב אבל האמת היא שיש איזה לונג אז אולי עדיף להגדיר לא לקבל את זה כלונג אלא כבר לקבל את זה כפונקציה טוב אני לא יכול לקבל את זה כפונקציה כי זה מחזיר אותו כלונג אני יכול להמיר את זה פה אבל אני גם יכול להמיר את זה פה זה לא משנה איפה

  26. 08:32

    אני ממיר את זה בוא נמיר את זה לא משנה איפה נמיר את זה פה יפה אז אוריג'ינל פרוק בואו נמיר אותו לפרוק אז איך נראה פרוק פרוק האמת שנראה ככה אבל אני צריך את הטיפוסים, ניקח את הטיפוסים, זה פרוק, בואו ניקח את זה, נגרור אותו, בעזרת גם עם קונטרול, פספסתי אותו, יפה, בואו נגרור

  27. 08:58

    אותו לכאן, עם קונטרול, שנשכפל את זה, חץ ואנטר, יפה, אז אני יכול להרוג את עצמי ולהגדיר פוינטר לפונקציה ולעשות קאסטינג, כן, ווין פרוק, נקרא לזה, זה יהיה, זה הולך להיות נורא נורא נורא קשה, אבל יש לנו הרצאות על פוינטרים, הוא ינפוג בעצם פה, אני לא צריך להגיד את השם, או זה לא משנה, אבל אני כן צריך להגדיר שם של משתנה שהוא

  28. 09:34

    יהיה הפוינטר החדש, זאת אומרת, אני יכול להגדיר, אוקיי, זה הטיפוס, זה פוינטר לפונקציה, זה הטיפוס, אבל אתה יכול את זה להעיף, זה לא מפריע.

  29. 09:48

    בקיצור, זה נורא נורא מסובך. הרבה יותר פשוט, כשעובדים עם פוינטרים ופונקציות, זה להשתמש ב-type def, אז בואו נגדיר type def, איך מגדירים type def?

  30. 10:00

    של פוינטר לפונקציה אז בואו נעשה רגע נחזיר את זה נקונטרול זה יפה זה משתנה והוא לא פוינטר לפונקציה אם אני רוצה להגדיר פוינטר לפונקציה איפה יש לי את הכוכבית פה אני רחץ אוקיי אני חושב אני לא בטוח תכף אנחנו ניווכח זה משתנה חדש כן השורה הזו פה בסוף אני שם נקודה פסיק זה נראה מוזר אבל העובדה

  31. 10:36

    היא שזה משתנה חדש והוא מסוג פוינטר פונקציה שמקבלת הפרמטרים הללו ומחזירה את זה והיא סטנדרט קוונינג קונבנצ'ן מבנה שלה אז זה פוינטר לפונקציה זה לא בריא להגדיר את המשתנה הזה כשאני בתוך פונקציה עם אותו שם אז בוא נגיד נקרא לזה פי פוינטר לווין פרוק יפה פוינטר לווין פרוק זה המשתנה ועכשיו נעשה

  32. 11:11

    לזה קאסטינג אז אני יכול להגיד שהמשתנה פוינטר לווין פרוק זה המשתנה והוא מקבל את הערך הזה. אבל אני צריך לעשות קאסטינג.

  33. 11:26

    נכון? אני צריך לעשות קאסטינג. אז קאסטינג, נוקחים את זה, קודם כל בואו נכין פה מקום לקאסטינג, זה לפני הטייפ דף, תבינו למה הטייפ דף כזה חשוב.

  34. 11:39

    אני לוקח את כל זה בלי הנקודה פסיק בסוף, ועושה עכבר ימני לכאן עם קופי, אבל אני מוציא את השם של המשתנה. אני לא רוצה להגדיר משתנה חדש, אני רוצה להשתמש בטיפוס.

  35. 11:55

    בואו נעשה פה קצת סדר, מה יש לנו? מה כתוב כאן? כתוב כאן שזה משתנה חדש מסוג פוינטים לפונקציה שמקבל את זה, מחזיר את זה וזה. אוקיי.

  36. 12:07

    עכשיו, המשתנה הזה שזה עתה הגדרנו, אני נותן לו ערך. אגב, יכולתי גם לשים פה שווה. בלי זה, וזה אותו דבר. אבל אני תמיד אוהב שורות נפרדות, אז שורות נפרדות.

  37. 12:23

    אז הגדרתי משתנה. המשתנה, אנחנו ניתן לו ערך. מה הערך? הערך זה זה. אבל באמצע אני עושה לזה קאסטינג, זה שורת הקאסטינג.

  38. 12:34

    מה הקאסטינג הזה עושה? אני פותח סוגריים, סוגר סוגריים, ובתוכם אני שם את הטיפוס של הפוינטר לפונקציה, אבל בלי שם של משתנה.

  39. 12:49

    אין פה שם של משתנה. יפה מאוד. זה בעצם קאסטינג. תכף אנחנו ננסה להגדיר טיפוס חדש שמחליף את זה, ואז זה יהיה אפשרי בלי הבלאגן הזה שחוזר על עצמו פעמיים, אבל לעת עתה זה בסדר, זה הפוינטר לווין פרוק, ועכשיו במקום זה אני

  40. 13:12

    אקרא לפוינטר לווין פרוק תחת סוגריים ואני אביא לו את הפרמטרים hwnd message w param וl param יפה זה נויץ אז הם נראים כמו כפתורים אבל הקוד עובר דרכנו אז זוכרים את זה זה עדיין שלנו יפה אז זה גם וגם הטכניקה הזו, טכניקה נורא עוצמתית, קוראים סאב קלאסינג.

  41. 14:02

    ולמעשה אני יכול ליישם אותה, במקרה הזה אנחנו מיישמים אותה על מחלקה שאנחנו, אין לנו את הקוד שלה. ובעצם חדרנו לקוד של, זה בעצם פילטר, חדרנו, עשינו פילטר על הקוד של מיקרוסופט.

  42. 14:21

    במיקרוסופט כתבו קוד א', ואני, לפני שהקוד של מיקרוסופט מבוצע, אני נכנס שם באמצע ואני יכול לעשות מניפולציות. יתרה על זאת, תנו לי חלון.

  43. 14:35

    שאני לא יצרתי אפילו, חלון באנשהו הוא, ואני יכול פשוט לעשות לו סאב קלאסינג. אני לא צריך ליצור את החלון כדי לעשות לו סאב קלאסינג, זה נקרא סאב קלאסינג.

  44. 14:46

    אני לא חייב ליצור את החלון ורק לעשות לו, אני יכול לקחת כל חלון ולעשות לו סאב קלאסינג. זה מאוד עוצמתי. אני יכול לשנות התנהגות של חלון קיים בלי קוד, בלי גישה לקוד של החלון המקורי.

לקורס המלא: קורס C למתקדמים אונליין

ההרצאה הקודמת: בניית חלון מאפס

ההרצאה הבאה: סיכום - בניית חלון מאפס

קורסים נוספים במסלול

  • קורס WinForms - תוכנות רגילות בווינדוס
  • פרויקט מעשי ב-#C - בונים מחשבון פשוט
  • פרויקט מעשי ב-#C - ספר טלפונים
  • פרויקט מעשי ב-#C - תוכנת צייר
  • קורס ADO.NET - חיבור אתר למסד נתונים
  • קורס תכנות מתקדם - #Advanced .NET C