PracticU

ממשק מרובה מסמכים - MDI

בלי כתוביותעם כתוביות
PracticU › קורס WinForms - תוכנות רגילות בווינדוס › ממשק מרובה מסמכים - MDI
מילון מושגים:
ממשק - נקודת מגע בין רכיבים: ממשק משתמש שבו אדם מפעיל תוכנה, או ממשק תכנותי שמגדיר אילו פעולות רכיב אחד חושף לאחר.
טופס - אזור בממשק שבו המשתמש מזין נתונים בשדות ושולח אותם, למשל טופס הרשמה או התחברות.
לולאה - מבנה בקרה שחוזר על קטע קוד שוב ושוב כל עוד תנאי מתקיים או עבור כל פריט באוסף.
אירוע - התרחשות שהמערכת מזהה ויכולה להגיב לה, כמו לחיצת עכבר, הקשה או סיום פעולה.
כפתור - רכיב בממשק המשתמש שהמשתמש לוחץ עליו כדי להפעיל פעולה, כמו שליחת טופס או מעבר לדף אחר.
תבנית - מבנה בסיסי מוכן שממנו יוצרים פריטים דומים, כמו תבנית עמוד או תבנית מסמך.
Visual Studio - סביבת פיתוח משולבת (IDE) של מיקרוסופט לכתיבה, ניפוי והרצה של קוד, בעיקר בשפות .NET.
תמונה - קובץ גרפי המוצג על המסך. בהקשר של וירטואליזציה או Docker, תבנית מוכנה שממנה יוצרים מכונה או קונטיינר.

ממשק מרובה מסמכים - MDI
השיעור עוסק ב-MDI (Multi Document Interface): טופס ראשי שמכיל בתוכו טפסים משניים שהמשתמש יכול לפתוח במקביל, כמו אלבום תמונות או כמה מסמכים פתוחים יחד.
יצירת טופס MDI
1. בטופס הראשי מגדירים את התכונה IsMdiContainer = true. הטופס הופך לקונטיינר שבתוכו נפתחים טפסים נוספים.
2. מוסיפים MenuStrip עם תפריט Window, שבו נמצאים הפריטים לניהול החלונות.
3. טופס ילד (Child Form) נוצר כטופס רגיל. כדי שיופיע בתוך ה-MDI מגדירים לו MdiParent = this לפני Show(). בלי השורה הזאת הוא נפתח כטופס עצמאי.
4. בתוך הקונטיינר הטופס הילד לא יוצא מגבולותיו, והמשתמש יכול לגרור אותו, להגדיל ולפתוח עוד חלונות.
מתי זה מתאים
כשיש כמה מסמכים שונים שדומים זה לזה והמשתמש צריך לעבוד בהם במקביל: אלבום תמונות, כמה דוחות, כמה מסמכים לכתיבה.
סידור חלונות
הפונקציה LayoutMdi מסדרת את החלונות הפתוחים בצורה שנקבעת ע"י ארגומנט:
- Cascade: מדורג, אחד מאחורי השני.
- TileVertical: אנכי, אחד ליד השני.
- TileHorizontal: אופקי, אחד מעל השני.
- ArrangeIcons: מסדר את החלונות המוקטנים שבתחתית.
סגירת כל החלונות
לולאה על MdiChildren וקריאה ל-Close() לכל טופס סוגרת את כולם. הדובר הציג זאת בפריט תפריט Close All.
עבודה עם מספר חלונות פתוחים
- בטופס הילד הדובר הגדיר משתנים ברמת הטופס (_currentPoint, _pen) כך שלכל טופס יש ציור נפרד.
- מאירוע MouseDown שומרים את הנקודה. ב-MouseMove, אם הכפתור השמאלי לחוץ (e.Button == MouseButtons.Left), מציירים קו מהנקודה הקודמת לנקודה הנוכחית ומעדכנים את הנקודה.
- תפריטי צבע ועובי קו מופעלים מתפריט הטופס הראשי. הדובר הדגים שהתפריט של הטופס הפעיל מופיע בשורת התפריט הראשית של ה-MDI, ושהפעולה משפיעה רק על הטופס שנבחר.
תבנית מוכנה של Visual Studio
Visual Studio מציעה תבנית MDI Parent Form עם תפריטים, סרגל כלים וסרגל סטטוס מוכנים, ופונקציות לפתיחה וסגירה של חלונות. הדובר הציג את התבנית ואת מה שהיא מכילה.
תרגיל
טופס MDI Parent מהתבנית המוכנה. טופס Child עם PictureBox, ותפריט ראשי שבו המשתמש בוחר תמונה בעזרת OpenFileDialog. כל חלון ילד מציג תמונה אחת, כך שהמשתמש מקבל אלבום תמונות.
בסיום השיעור הסטודנט יודע לבנות טופס MDI, לפתוח טפסי ילד בתוכו, לסדר אותם, ולסגור את כולם.
השיעור הבא בקורס: הרצאה על Resources

פרקי ההרצאה: ממשק מרובה מסמכים - MDI

  1. 00:00

    מהו MDI

  2. 01:08

    הגדרת IsMdiContainer

  3. 03:37

    הגדרת MdiParent לטופס בן

  4. 07:21

    סידור חלונות CASCADING

  5. 08:44

    סידורי Tile ו-ArrangeIcons

  6. 11:46

    סגירת כל החלונות עם MdiChildren

  7. 13:38

    טופס צייר כ-CHILD

  8. 16:19

    ציור עם MouseDown ו-MouseMove

תמלול ההרצאה: ממשק מרובה מסמכים - MDI

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

  1. 00:03

    כעת אנחנו הולכים לראות משהו שנקרא mdi שזה קיצור של multi document interface. מה זה אומר? זה אומר טופס פרנט שאנחנו יכולים לבנות שבתוכו אנחנו יכולים לפתוח טיפסי צ'יילד נוספים והוא בעצם עוטף את טיפסי הצ'יילד, את הטפסים שבתוכו.

  2. 00:30

    בואו נראה קודם כל איך עושים את זה ולמה בעצם זה יכול לעזור לנו לפעמים. בואו נפתח פרויקט ווינפורם רגיל, ניקח Windows Forms Application, נקרא לו Multi Document Interface.

  3. 00:52

    עכשיו מה שאנחנו רוצים לעשות זה להפוך את הטופס הראשי שיש לנו למשהו שנקרא MDI. בואו נקרא לו Main Form, ניגש לתכונות שלו ואחת מהתכונות של הטופס תגדיר שהטופס הזה הוא טופס MDI, Multi Document Interface.

  4. 01:19

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

  5. 01:43

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

  6. 01:58

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

  7. 02:19

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

  8. 02:36

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

  9. 02:57

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

  10. 03:44

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

  11. 03:57

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

  12. 04:18

    יש לנו פה לחצן ו-checkbox. כעת, אם אנחנו הולכים ויוצרים אובייקט חדש מסוג child form, ואנחנו רוצים להציג אותו, נציג אותו עם show, כעת אין ביניהם שום קשר, אין קשר בין ה-child form לבין ה-parent mdi.

  13. 04:56

    בואו נריץ, נלך ל-window, נבצע new window, ונראה שזה סתם טופס שלא קשור. אם אנחנו רוצים שהצ'יילד יהיה בעצם באמת צ'יילד של ה-MDI פרנט, אנחנו צריכים להגדיר עוד תכונה אחת.

  14. 05:14

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

  15. 05:30

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

  16. 05:46

    אני יכול לשים אותו פה בצד, ללכת ולפתוח עוד אחד. יש לי עכשיו שניים, אני יכול ללכת ולפתוח עוד אחד.

  17. 05:56

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

  18. 06:24

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

  19. 06:39

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

  20. 06:53

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

  21. 07:04

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

  22. 07:21

    סידור אחד זה סידור שנקרא קסקיידינג. קסקיידינג הכוונה מדורג. בואו נתפוס את זה, נלך לתכונות, ניתן לזה MNU קסקיידינג וכל מה שאנחנו רוצים לעשות בתוך הלחצן הזה זה את הפקודה הבאה layoutMDI פונקציה שמקבלת איזשהו אינם שמגדיר כיצד אנחנו רוצים לסדר את ה-child forms.

  23. 08:05

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

  24. 08:34

    זה מה שהסידור הזה עשה. אבל ישנם עוד מספר סידורים שאנחנו יכולים להגדיר. בואו נבנה אותם. סידור אחד נקרא Tile Vertical.

  25. 08:54

    הסידור הבא בתור נקרא Tile Horizontal, הדור האחרון נקרא Arrange Icons. בואו ניתן להם שמות משמעותיים. יש לנו פה את MNU, Tile ו-Vertical.

  26. 09:23

    יש לנו כאן את MNU, Tile, Horizontal. ויש לנו כאן את MNU, Arrange Icons. ובואו נראה מה כל אחד מתאר. ב-Tile, Vertical, אנחנו רוצים ללכת ל-Layout, MDI, ולתת MDI, Layout, נקודה, טייל ורטיקל.

  27. 10:00

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

  28. 10:27

    בואו נראה מה כל אחד מבצע. אני מריץ את התוכנית ואני פותח מספר חלונות. יש לנו פה New Window, אינו נמצא פה בצד, חלון שני, חלון שלישי.

  29. 10:45

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

  30. 10:57

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

  31. 11:21

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

  32. 11:36

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

  33. 12:07

    כל מה שאנחנו רוצים לעשות זה לרוץ ב-foreach form child form in mdi children mdi children והאוסף של ה-children הנוכחיים שלנו child form.close סוגר לנו את הטופס ולכן הלולה הזאתי הולכת לסגור את הכל.

  34. 12:40

    בואו נריץ, נפתח כמה חלונות, חלון ראשון, שני, שלישי, רביעי, אנחנו יכולים לראות אותם כאן, close all, סוגר לנו את כל החלונות.

  35. 12:57

    אז בעצם כאן אנחנו ראינו מה זה mdi ובואו ניישם איזה משהו מעניין עבור ה-child form. זה אנחנו יכולים לסגור, זה אנחנו יכולים לסגור ואנחנו יכולים להגיע ל-child form וליישם פה איזה משהו שיהיה מעניין בנוגע ל-mdi.

  36. 13:23

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

  37. 13:42

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

  38. 14:08

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

  39. 14:43

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

  40. 15:07

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

  41. 15:38

    אנחנו רוצים בעצם את הנקודה הנוכחית שהיוזר נמצא עליה. נקרא לזה co-end point. אז יש לנו את כל הפרמטרים האלה. נתחיל את הפן בפן default-it, נניח black.

  42. 16:10

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

  43. 16:57

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

  44. 17:17

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

  45. 17:28

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

  46. 17:58

    Next Point תהיה שווה ל-e.location. אז יש לנו את ה-Current Point שהיוזר לחץ עם העכבר על הטופס איפשהו, התחיל לגרור, קיבלנו את ה-Next Point, ואז יש לנו שתי נקודות, אחת הקורנט ואחת הנקסט.

  47. 18:19

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

  48. 18:45

    אנחנו רוצים מה-Cורנט פוינט עד ה-Next Point. שימו לב שתמיד אני נוהג משתנים גלובליים, כלומר data member מסטיפוס פרייבט יוגדרו עם קו תחתון ואיזושהי מוסכמה מסוימת.

  49. 19:06

    וכמובן המילה תתחיל בעוד קטנה. אם המשתנה הוא משתנה לוקאלי אנחנו לא מתחילים אותו עם קו תחתון, אנחנו פשוט רושמים אותו בconvention שנקראת camel naming convention כל מילה המילה הראשונה מתחילה בעוד קטנה וכל מילה אחרת מתחילה בעוד גדולה.

  50. 19:28

    לכן יש לנו פה את ה-current point עם קו תחתון לפני זה וה-next point ללא קו תחתון. למה ה-current point הוגדרה גלובלית? כי אנחנו רוצים שאירוע א' יכניס לה ערך, אירוע ב' יקרא את הערך שלה.

  51. 19:46

    והדבר הנוסף שאנחנו רוצים זה-current point שווה ל-next point, מפני שהיוזר כבר זז. אז יש לנו פה כרגע ממש את הציור עצמו שאמור להתבצע.

  52. 20:03

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

  53. 20:23

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

  54. 20:52

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

  55. 21:21

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

  56. 21:50

    לתפריט הזה נקרא "MNU line". ב-color יש לנו מספר צבעים, יש לנו Red, יש לנו גרין, בואו ניקח כאן בלו.

לקורס המלא: קורס WinForms אונליין

ההרצאה הקודמת: שימוש במספר טפסים - Multiple Forms

ההרצאה הבאה: הרצאה על Resources

הרצאות קשורות מקורסים אחרים

  • ממשק IEnumerable
  • ממשק גרפי של Git
  • הסבר על מה זה ממשק - API
  • ממשק גרפי של SCOM

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

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