Maxim

Some .Net applications are required to run as single instance process (at startup, each process “ensures” that he’s unique). This requirement may come from licensing issues, technical and/or other reasons. Quick search in Google will provide a variety of solutions, most of them are based on WindowsFormsApplicationBase object from VB.Net, usage of Mutex object and other techniques. I don’t like mixing VB with C#, and also Win-Forms solution isn’t “pure” enough for WPF applications. So I wrote my version of “Single Instance Manager”…

This post will provide short description about this small project and links to download the sources.

How to Create Single Instance Application for WPF, Win-Forms and Console Applications

The manager uses well-known ThreadPool object with WaitEventHandle object and IpcClientChannel to pass messages (objects) between processes (.Net Remoting).

Diagram: Pass object cross processes

[In Diagram: Instance A passes Console Arguments to Process B, before it closes it self]

Each application will use “ApplicationInstanceManager.CreateSingleInstance(…)” to register it self as single instance application.

image

[In Diagram: Description of “CreateSingleInstance(…)” Function]

The manager ensures that application has only one instance and also passes console arguments from new instances to running process, before “killing” them.

   1:  using System;
   2:  using System.Diagnostics;
   3:  using System.Runtime.Remoting;
   4:  using System.Runtime.Remoting.Channels;
   5:  using System.Runtime.Remoting.Channels.Ipc;
   6:  using System.Threading;
   7:   
   8:  namespace SingleInstanceApplication
   9:  {
  10:      /// <summary>
  11:      /// Application Instance Manager
  12:      /// </summary>
  13:      public static class ApplicationInstanceManager
  14:      {
  15:          /// <summary>
  16:          /// Creates the single instance.
  17:          /// </summary>
  18:          /// <param name="name">The name.</param>
  19:          /// <param name="callback">The callback.</param>
  20:          /// <returns></returns>
  21:          public static bool CreateSingleInstance(string name, EventHandler<InstanceCallbackEventArgs> callback)
  22:          {
  23:              EventWaitHandle eventWaitHandle = null;
  24:              string eventName = string.Format("{0}-{1}", Environment.MachineName, name);
  25:   
  26:              InstanceProxy.IsFirstInstance = false;
  27:              InstanceProxy.CommandLineArgs = Environment.GetCommandLineArgs();
  28:   
  29:              try
  30:              {
  31:                  // try opening existing wait handle
  32:                  eventWaitHandle = EventWaitHandle.OpenExisting(eventName);
  33:              }
  34:              catch
  35:              {
  36:                  // got exception = handle wasn't created yet
  37:                  InstanceProxy.IsFirstInstance = true;
  38:              }
  39:   
  40:              if (InstanceProxy.IsFirstInstance)
  41:              {
  42:                  // init handle
  43:                  eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
  44:   
  45:                  // register wait handle for this instance (process)
  46:                  ThreadPool.RegisterWaitForSingleObject(eventWaitHandle, WaitOrTimerCallback, callback, Timeout.Infinite, false);
  47:                  eventWaitHandle.Close();
  48:   
  49:                  // register shared type (used to pass data between processes)
  50:                  RegisterRemoteType(name);
  51:              }
  52:              else
  53:              {
  54:                  // pass console arguments to shared object
  55:                  UpdateRemoteObject(name);
  56:   
  57:                  // invoke (signal) wait handle on other process
  58:                  if (eventWaitHandle != null) eventWaitHandle.Set();
  59:   
  60:   
  61:                  // kill current process
  62:                  Environment.Exit(0);
  63:              }
  64:   
  65:              return InstanceProxy.IsFirstInstance;
  66:          }
  67:   
  68:          /// <summary>
  69:          /// Updates the remote object.
  70:          /// </summary>
  71:          /// <param name="uri">The remote URI.</param>
  72:          private static void UpdateRemoteObject(string uri)
  73:          {
  74:              // register net-pipe channel
  75:              var clientChannel = new IpcClientChannel();
  76:              ChannelServices.RegisterChannel(clientChannel, true);
  77:   
  78:              // get shared object from other process
  79:              var proxy =
  80:                  Activator.GetObject(typeof(InstanceProxy), 
  81:                  string.Format("ipc://{0}{1}/{1}", Environment.MachineName, uri)) as InstanceProxy;
  82:   
  83:              // pass current command line args to proxy
  84:              if (proxy != null)
  85:                  proxy.SetCommandLineArgs(InstanceProxy.IsFirstInstance, InstanceProxy.CommandLineArgs);
  86:   
  87:              // close current client channel
  88:              ChannelServices.UnregisterChannel(clientChannel);
  89:          }
  90:   
  91:          /// <summary>
  92:          /// Registers the remote type.
  93:          /// </summary>
  94:          /// <param name="uri">The URI.</param>
  95:          private static void RegisterRemoteType(string uri)
  96:          {
  97:              // register remote channel (net-pipes)
  98:              var serverChannel = new IpcServerChannel(Environment.MachineName + uri);
  99:              ChannelServices.RegisterChannel(serverChannel, true);
 100:   
 101:              // register shared type
 102:              RemotingConfiguration.RegisterWellKnownServiceType(
 103:                  typeof(InstanceProxy), uri, WellKnownObjectMode.Singleton);
 104:   
 105:              // close channel, on process exit
 106:              Process process = Process.GetCurrentProcess();
 107:              process.Exited += delegate { ChannelServices.UnregisterChannel(serverChannel); };
 108:          }
 109:   
 110:          /// <summary>
 111:          /// Wait Or Timer Callback Handler
 112:          /// </summary>
 113:          /// <param name="state">The state.</param>
 114:          /// <param name="timedOut">if set to <c>true</c> [timed out].</param>
 115:          private static void WaitOrTimerCallback(object state, bool timedOut)
 116:          {
 117:              // cast to event handler
 118:              var callback = state as EventHandler<InstanceCallbackEventArgs>;
 119:              if (callback == null) return;
 120:   
 121:              // invoke event handler on other process
 122:              callback(state,
 123:                       new InstanceCallbackEventArgs(InstanceProxy.IsFirstInstance,
 124:                                                     InstanceProxy.CommandLineArgs));
 125:          }
 126:      }
 127:  }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

For testing purposes I added form with grid that allows starting processes with console arguments:

single instance manager

How can we use this manager (for example in WPF app):

   1:  using System;
   2:  using System.Reflection;
   3:  using System.Windows;
   4:   
   5:  namespace SingleInstanceApplication.WpfApp
   6:  {
   7:      /// <summary>
   8:      /// Interaction logic for App.xaml
   9:      /// </summary>
  10:      public partial class App
  11:      {
  12:          /// <summary>
  13:          /// Raises the <see cref="E:System.Windows.Application.Startup"/> event.
  14:          /// </summary>
  15:          /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs"/> that contains the event data.</param>
  16:          protected override void OnStartup(StartupEventArgs e)
  17:          {
  18:              // register single instance app. and check for existence of other process
  19:              if (!ApplicationInstanceManager.CreateSingleInstance(
  20:                      Assembly.GetExecutingAssembly().GetName().Name,
  21:                      SingleInstanceCallback)) return; // exit, if same app. is running
  22:   
  23:              base.OnStartup(e);
  24:          }
  25:   
  26:          /// <summary>
  27:          /// Raises the <see cref="E:System.Windows.Application.Activated"/> event.
  28:          /// </summary>
  29:          /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
  30:          protected override void OnActivated(EventArgs e)
  31:          {
  32:              base.OnActivated(e);
  33:   
  34:              var win = MainWindow as MainWindow;
  35:              if (win == null) return;
  36:   
  37:              // add 1st args
  38:              win.ApendArgs(Environment.GetCommandLineArgs());
  39:          }
  40:   
  41:          /// <summary>
  42:          /// Single instance callback handler.
  43:          /// </summary>
  44:          /// <param name="sender">The sender.</param>
  45:          /// <param name="args">The <see cref="SingleInstanceApplication.InstanceCallbackEventArgs"/> instance containing the event data.</param>
  46:          private void SingleInstanceCallback(object sender, InstanceCallbackEventArgs args)
  47:          {
  48:              if (args == null || Dispatcher == null) return;
  49:              Action<bool> d = (bool x) => 
  50:              {
  51:                  var win = MainWindow as MainWindow;
  52:                  if (win == null) return;
  53:   
  54:                  win.ApendArgs(args.CommandLineArgs);
  55:                  win.Activate(x);
  56:              };
  57:              Dispatcher.Invoke(d, true);
  58:          }
  59:      }
  60:  }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

[As you can see “App” has “SingleInstanceCallback” that is fired by manager, also you can see function overload for “Window.Actvate” (see this post about this extention)]

VS2010 Sources for this project can be downloaded from here (blog) or here (codeplex).
DLL + PDB Assembly with Library can be downloaded from here (blog) or here (codeplex).
image Project’s site at Codeplex: …

 Remarks: Any comments/improvements will be accepted with pleasure. Of course, you must understand that this code is a contribution and I’m not responsible for any damage that may be caused by using it. All rights reserved ®.

This solution can be used in WPF and in WinForms (with some improvements).

Many times UI programmer needs to activate window, the activation can be done by using “Activate()” function in window. The problem is that this function will not show window if it is minimized. In that case you can use this workaround:

using System;
using System.Windows; 

namespace Test
{
       public partial class MyWindow
       {
              /// <summary>
              /// Gets Previouse Window State
              /// </summary>
              public WindowState PreviouseWindowState { get; private set; }  

              /// <summary>
              /// Constructor
              /// </summary>
              public MyWindow()
              {
                     InitializeComponent();

 

                     // store 1st value
                     PreviouseWindowState = WindowState;

 

                     // attach to event (used to store prev. win. state)
                     LayoutUpdated += Window_LayoutUpdated;
              }  

              /// <summary>
              /// Occures on layout change
              /// </summary>
              /// <param name="sender"></param>
              /// <param name="e"></param>
              private void Window_LayoutUpdated(object sender, EventArgs e)
              {
                     PreviouseWindowState = WindowState;
              }  

              /// <summary>
              /// Activates Window
              /// </summary>
              /// <param name="restoreIfMinimized">if [true] restore prev. win. state</param>
              /// <returns></returns>
              public bool Activate(bool restoreIfMinimized)
              {
                     if (restoreIfMinimized && WindowState == WindowState.Minimized)
                     {
                           WindowState = PreviouseWindowState == WindowState.Normal
                                                                     ? WindowState.Normal : WindowState.Maximized;
                     }
                     return Activate();
              }
       }
} 

As you can see I added new overloaded function “Activate(bool)” that allows activation of minimized window, thanks to new property “PreviouseWindowState” that stores previous value of “WindowState” when “Window_LayoutUpdated” in called.

Source Code: Window.cs

Remarks: Any comments/improvements will be accepted with pleasure. Of course, you must understand that this code is a contribution and I’m not responsible for any damage that may be caused by using it. All rights reserved ®.

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


GUI Standards Document

בפרויקטים גדולים של מערכות תוכנה עם ממשקי משתמש רבים קיים צורך בכתיבת מסמך סטנדרטים בתחילת הפרויקט. מסמך זה משמש את כל הגורמים המעורבים בעיצוב-פיתוח GUI: מנתחי מערכות (System Analysts), מעצבי מודולים (SW Designers) ומתכנתים (האנשים שבפועל בונים GUI ומקודדים לוגיקת קליינט).

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

תרשים עם פעולות שיכולות לעזור בכתיבת המסמך והטמעתו:

  1. קבל את התחייבות הארגון לעבור דרך תהליך הסטנדרטיזציה: במילים אחרות קבל OK של הממונים שלך. חשוב שגם האנשים שיהיו צרכני המסמך יבינו את חשיבותו (אף אחד לא אוהב לבזבז זמן על משהו שלא ישמש אף אחד);
    -
  2. גייס תומכים לתהליך הסטנדרטיזציה: גייס את דעת הקהל. יתכן מצב שמספר עובדים לא יקבלו בהבנה את המסמך, יהיו אמירות כמו: "למה אנו צריכים את הדברים האלה?", "אנו יודעים לעבוד גם ללא המסמך!", "עד עכשיו הסתדרנו ללא המסמך!" וכו'. – לא אציג כאן את דרכי השכנוע, מאמין שמי שלוקח על עצמו את התפקיד של מהנדס UI/UX ומוכן לכתוב את המסמך יידע לשכנע בצורה טובה.
    -
  3. אסוף מידע: בצע איסוף מידע ממשתמשי הקצה (לקוח), על סביבת העבודה (באתר לקוח), תהליכים עסקיים, זרימת עבודה ומשימות, אסטרטגיה ארגונית וכו'. [זמנים: 2-3 ימים בממוצע]
  4. הגדר סוגי הסטנדרטים הנחוצים: בד"כ קובעם סטנדרטים עבור: מודל ארכיטקטוני של קליינט (MVC, MVP OR MVVM), סוגי הפקדים עבור סוגים שונים של מידע (Data Models, Data Sources), תקן של תבניות מידע קבועות בפרויקט (Data Templates), כללי נווט בין מסכים (מפת המסכים), מבנה של מסך ראשי, הכוונה למבנה כללי של טפסים, סוג ה- GUI (Tabular, Single Window, MDI Window, Multiple Window). לווה כל בדוגמאות. [זמנים: 5-10 ימים בממוצע]
    -
  5. הגדר מספר מסכים שיעוצבו בהתאם לסטנדרטים: בד"כ לא ניתן להחיל עיצוב לפי סטנדרטים על כל המסכים במערכות גדולות, השתדל לתכנן לפחות 85% מהמסכים בהתאם לסטנדרט שקבעת. הדבר יאפשר שמירה על "עקרון העקביות" שמאוד חשוב.
    -
  6. לווה מסמך בדוגמאות: השתדל לתת כמה שיותר דוגמאות לעיצוב המסכים, כסה מספר מקסימאלי של סוגי הפקדים נתמכים בהתאם למקרי השימוש. ספק דוגמאות מסוג "עיצוב מומלץ" ו"עיצוב לא מומלץ". אנשים שיעצבו מסכים בהתאם למסמך יפנו יותר לדוגמאות מאשר לטקסט יבש.
    -
  7. בנה תבניות כלליות: בנה מספר תבניות מוכנות של מסכים, טפסים, פאנלים, מסגרות, סטים של פקדים וכו'.ברוב מערכות מידע יש דמיון בין טפסי המידע (Win-Forms), השוני הוא בכמות, סוג ומיקום הפקדים (כמובן יש גם שוני בהתנהגות המסכים). תבנית מוכנה יכולה לצמצם זמני עבודה, מעצב המסך יוכל להשמיש תבנית לצרכיו (לרוב ייעשה Drag-and-Drop וישנה את הפקדים, סגנון וסטנדרט יישמרו).
    -
  8. שתף ועדה טכנולוגית בהחלטות עיצוביות והצג בפניה את המסמך: הצג מסמך בפני פורום מקצועי-טכנולוגי. שתף פורום בהחלטות עיצוביות שנתקבלו בעת כתיבת המסמך. במידע ויהיו הערות לשינוי/תיקון דברים במסמך – עדיף שיהיו בשלב זה ולא בשלב שלאחר ההפצה של המסמך. [זמנים: 3-4 ימים בממוצע כולל DR]
    -
  9. הפץ מסמך בין גורמים רלוונטיים ובצע הדרכות: לאחר אישור הגורמים הרלוונטיים (אחרי שמסמך אושר בוועדה טכנולוגית) הפץ מסמך בין אנשים שיעצבו ויפתחו מסכים. מכוון שאנשים לא אוהבים לקרוא מסמכים עדיף לבצע הדרכה במקביל להפצה. ההדרכה לא יכולה לכסות את כל הנושאים ולא יכולה לתת תשובות לכל הבעיות שיצוצו, היא תאפשר הכנסה של אנשים לעניין המסמך והם ייחשפו לדברים עיקריים במסמך. [זמנים: כתיבה של מסמך: 1-3 שבועות בממוצע, הדרכות: 2-7 ימים בממוצע]
    -
  10. יישם והטמע סטנדרטים: זוהי מהות המסמך, אחרת זה יהיה עוד נייר מיותם בסדרה אינסופית של מסמכים שאף אחד לא מתייחס אליהם. החל מרגע ההפצה של המסמך כל מי שמעורב בעיצוב-פיתוח המסכים "אמור" להיצמד אליו, ז"א להשתמש באותו סט פקדים, באותן טכניקות, באותו סגנון (Look-and-Feel), באותם כללים של שמישות וכו'. [זמנים: 2-4 שבועות בממוצע]
    -
  11. וודא הטמעה של סטנדרטים: בצע ביקורות תוצרים (Design and Code Review). וודא שמסכים מעוצבים בהתאם לסטנדרט שנקבע. זה מתקשר לסעיף הקודם – תן משמעות לתקנים שאליהם התחייבת. [זמנים: אין הגבלה, מתבצע לאורך כל הפרויקט]
    -
  12. עדכן מסמך בהתאם לשינויים המתבקשים: מסמך סטנדרטים הנו ייצור חי. מפעם לפעם יתכנו שינויים בעיצוב המסכים שיידרשו שינוי בסטנדרט מסוים. במקרים מסוימים נגלה שמשהו מהמסך לא מתאים או לא עומד במבחן הזמן. לאחר שינוי המסמך דאג להפיצו בין גורמים רלוונטיים ובצע הדרכות (חזרה לסעיף 9 ולרוב גם ל- 8).

 

קווים מנחים בכתיבת המסמך

  • זכור למי מיועד המסמך: רמת הפירוט הטכני וכלל התכנים צריכים להיות מותאמים לאנשים בעלי רמה טכנית שונה. במידה ומסמך מיועד למנתחי מערכות וגם למפתחים, התאם לרמה למנתחים אשר לא בקיעים בפרטים הטכניים ספציפיים של פיתוח. אם מסמך מיועד למפתחי התוכנה אפשר לספק פירוט טכנולוגי יותר מורחב.
    -
  • עקביות: אחד העקרונות החשובים בעיצוב UI. ממשק התוכנה חייב להיות עקבי. המשתמש המודרני מצפה "להיכנס לעניינים" תוך זמן קצר. אם נשמור על עקרון העקביות בכל מסכי המערכת המשתמש יוכל לבצע פעולות בצורה אינטואיטיבית, על סמך הניסיון מתוכנות קודמות ו/או על סמך מה שהוא למד לעשות במסכים ראשונים במערכת החדשה. למשל: המשתמש התרגל לפתוח חלון מודאלי (Dialog-Window) עם פרטים מורחבים של רשומה ע"י לחיצה כפולה על שורה בטבלה (Data-Grid), אם מסך מסוים יאפשר פתיחת טופס בלחיצה אחת – לרוב זה יעצבן את המשתמש ופעולה שלעצמה אינה בטיחותית. המסמך חייב לכלול הסבר כיצד לשמור על עקביות, עקביות בכמה רבדים: מיקום כפתורי פעולה, יישור שדות הזנה, סוגי פקדים (בהתאם לסוגי מידע שהם מקבלים), מתי עושים קליק-כפול ומתי קליק-אחד, כיצד להציג הודעות שגיאה, כיצד להתריע על שגיאות וולידציה וכו'. תאר עקביות בסגנון (Styling) או בעיצוב הטפסים: שימוש בצבעים לרקעים, צבעי אזהרה/שגיאה, צבעי הפונטים, גדלים של פונטים ואייקונים. תאר כיצד לקבוע את פריסת הפקדים בטופס, תן המלצות לגבי החלוקה (טאבולארית – Tabular GUI, דף נגלל, אזורים מתקפלים וכו'). במידה ושפת הממשק הנה עברית התייחס לזרימת הטקסט הנכונה (Right-to-Left Flow Direction) – מאוד חשוב שמפתחים ידעו לקבוע מראש את זרימת המסך מימין לשמאל בשלבים מוקדים של פיתוח, אם יתחילו פיתוח הטפסים עם כוון LTR יהיה מאוד קשה לשנות את הזרימה אח"כ. זכור לבצע שלב 11 (וודא הטמעה של סטנדרטים) מפרק קודם – בצע DR-ים (Design Review) לתוצרים של אנשים, וודא שעקרון העקביות נשמר.
    -
  • קבע סטנדרטים והצמד אליהם: בהמשך לסעיף הקודם, לרוב צריך לקבוע סטנדרט של סוגי הפקדים (ספק דוגמאות לשימוש בסט הפקדים של הפרויקט – Controls' Toolbox), סטנדרט של סגנון (פורט בסעיף הקודם). סטנדרט של איכות (מאוד חשוב) – כיצד לוודא עיצוב ופיתוח המסכים מתבצע בהתאם לסטנדרטים שקבענו, ספק To-do List לביצוע בדיקות הנ"ל. קבע מודל עבודה – מיהם האנשים שיהיו מעורבים בעיצוב ופיתוח מסכים, מי האנשים שיעשו ביקורת לתוצרים, מיהם אנשי הקשר שלך (אתה לא יכול להתפצל לכמה אנשים כדי לתמוך בכולם).
    -
  • על תמציא גלגל מחדש: למד מניסיונם של אחרים, השתמש בסטנדרטים המקובלים בשוק התוכנה או במערכות דומות. ראה דוגמאות של מסמכי סטנדרטים ברגונך (במידה וקיימים), השתמש בדוגמאות ממקורות אחרים. אם מפתחים יישום לשימוש בסביבת המשרד – ניתן לחכות יישומי אופיס או יישומים אחרים המוכרים למשתמש שלך (רבים מכירים ממשקים של MS Office, רבים משתמשים בקיצורי סטנדרטיים, זכור לא לדרוס קיצורי דרך של מערכת הפעלה).
    -
  • דוגמאות: לווה מסמך בכמה שיותר דוגמאות מוחשיות. השתמש בצילומי מסך, מבנה טפסים, תבניות, שימוש בסגנונות. ספק דוגמאות מסוג "תעשה" ו"אל תעשה". לפי ניסיוני, רוב האנשים פשוט לא קוראים מלל (מתכנתים אף שונאים מלל, לעומתם מנתחי מערכות יעדיפו משהו כתוב), לכן דוגמאות גראפיות תהיינה מאוד יעילות.
    -
  • כללי נווט: הגדר כללי נווט ברורים בתוך המסכים והחוצה. באילו מקרים ייפתח חלון מודאלי ובאילו מקרים נעדיף למקם תוכן הטופס בתוך המסך. כיצד מנווטים בתוך המסך, קיצורי דרך של מקלדת, זרימת העבודה בתוך המסך, שימוש ב- Wizards. ספק מפת מסכים לדוגמא, המפה תכלול דוגמאות של "הכלה" (Screen Composition) ודוגמאות של נווט (Screen Navigation).
  • שפת הממשק: הכוון משתמשים לשפה משותפת, בנה מילון עסקי עבור UI, עדכן מילון מפעם לפעם. חשוב שכל מי שמעורב בעיצוב ופיתוח המסכים ישמור על עקביות גם בתגיות (Labels), בהודעות (Error/Info/Warning Messages). הנחה משתמשים להשתמש באותו סגנון בהודעות, כפתורי פעולה אחידים (האם להשתמש במילים כמו "שמור" או "שמירה", "פתח" או "פתיחה", "חפש" או "חיפוש"). מילון עסקי זוהי שפה ייחודית של ארגון, אבל גם כאן אני לא ממליץ להמציא גלגל מחדש, מילות צווי ברוב התוכנות הנן זהות. דאג להדריך "עורכי דין" להשתמש במלל קצר, אפקטיבי ופרודוקטיבי ("עורכי דין" או "בלשנים" – אנשים שמכניסים טקסטים ארוכים ומסורבלים בממשקי משתמש, בד"כ מנסחים הודעות בשפה גבוהה שלא באה מעולם המחשבים).
    -
  • סט פקדים (UI Widgets): הכן רשימת פקדים ופרט מקרים בהם יש להשתמש בפקד מסוג מסוים. סט יכול להכיל פקדים מיוחדים (Customized Controls), ייחודיים לפרויקט, אשר נבנו לפונקציונאליות עסקית ספציפית (למשל: גרפים מיוחדים, שעוני דשבורד, פאנלים עם תבניות מוכנות, Grid Tables מיוחדים, סיירי מדיה וכו'). ספק דוגמאות ויזואליות (Screen Snapshots) למקרי שימוש ולאופני שימושי. אין צורך לפרט על פקדים סטנדרטיים כגון: תוויות, תיבות טקסט, תיבות בחירה (קומבו), רשימות תקניות (List Box) ועוד פקדים שלרוב ידוע כיצד להשתמש בהם.
    -
  • סגנון של טפסים (Look-and-Feel): כפי שהסברתי בסעיפים קודמים, חושב להנחות מהו הסגנון של הממשק, מהם צבעי אזהרה, ידיעה, שגיאות. אם יש תקציב לגרפיקאי שיעשה את עיצוב הממשק, חושב להראות לאנשים מהו העיצוב הסופי המצופה. במקרה שמודל העבודה על המסכים "מעצב UI" + "מתכנת קליינט" (לרוב מקובל בעבודה עם WPF), יש לקבוע תחומי אחראיות לתוצרים ותחומי החפיפה; לרוב גרפיקאי יעצב תבניות, סגנונות, אייקונים ולוגואים (בהתאם למבנה המסך הראשי), המתכנת חייב לדעת לא "לפלוש" לאזורים של מעצב (למודל הנ"ל אקדיש פוסט נפרד). לרוב אנשים שמעורבים בעיצוב-פיתוח UI ירצו לדעת כיצד התוצרים שלהם ייראו בעיצוב הסופי, במקרים אלה אפשר לספק להם תבנית גרפית שאותה "ילבישו" על המסכים שלהם. ללא קשר לתוצרים של גרפיקה, חושב להסביר לאנשים כיצד לשמור על אחידות עיצובית כדי לתת Look-and-Feel אחידים לאורך כל המסכים.
    -
  • נגישות ושמישות (Accessibility and Usability): קבע כללים עבור נגישות ה- GUI בטפסים של הפרויקט. הסתמך על סביבת העבודה אצל לקוח: קהל היעד (האם יש מוגבלות פיזיות כלשהן אצל משתמשי הקצה), תצורת המחשב (גודל המסך, סוג המסך, איכות המסך, מערכת הפעלה, כוננים וכו'). קבעי כללים עבור שמישות. ציין כיצד לוודא שטופס שמיש וחסכוני מבחינת הפעולות (כיום מושג "GUI ארגונומי" מאוד נפוץ).
  • הדרכה: (סעיף 9 בתרשים) במהלך ההדרכה של צרכני המסמך מומלץ להראות כיצד בונים מסך. הסבר כיצד לחסוך פעולות מיותרות, הראה כיצד להשתמש בתבניות מוכנות, הראה כיצד ייראו למקם פקדים בהתאם לזרימת המסך/שפה. ציין נקודות חשובות במסמך שעליהם לא ניתן לדלג.
    -
  • בצע DR (Design Review): חשוב לקבל חוות דעת מגורמים מוסמכים לגבי המסמך לפני ביצוע הדרכות והפצה. בצע DR לעיצוב של מסכים של צרכני המסמך (סעיף 11 בתרשים עליון).
    -
  • עקרונות וקווים מנחים לעיצוב: -
  1. מבנה: הצע מבנה היררכי, קבץ פקדים לתוך מסגרות בהתאם פונקציונאליות משותפת, הוצא פקדים משותפים למסגרות שחופפות למסגרות נושאים. אסור שלמשתמש תהיה צריכה להיות תחושה שממשק מאיים ועמוס.
    -
  2. פשטות: זהה תהליכים כללים וראשיים, הגדר אזורי הפעלה לתהליכים אלה, השתמש במודל מופשט, סדר פקדים והיררכיה בצורה נוחה, הגדר קיצורי דרך של מקלדת לפעולות נפוצות.
    -
  3. שקיפות: הצג את מירב האופציות הזמינות באותו המסך (ללא עומס חזותי), אם עמוס - חלק למספר חוצצים/אזורים. אל תציע מיליון דרכים לביצוע של אותה פעולה, תרגיל משתמש שפעולה כלשהי מתבצעת במקום מסוים (שים לב שב- MS Word 2007 כל הפעולות מתבצעות רק דרך Ribbon ולא כמו ב- MS Word 2003 ניתן היה לבצע פעולה גם דרך סרגל כלים וגם דרך תפריטים).
    -
  4. משוב: למשתמש צריכה להיות תחושה שבכל שלב הוא יודע מה אמור לקרות, הוא מצפה לתגובות מסוימות של הממשק. ספק משוב רלוונטי כתוצאה מפעולת המשתמש, אל תציג הודעה עם תוכל מבלבל או לא קשור לפעולה שבעקבותיה הוצגה ההודעה. ספק חיווי ברור למרחש, גם אם זה מוריד מ"סקסיות המסך".
    -
  5. גמישות: בנה ממשק גמיש וסלחני. אל תטריח משתמש בפעולות מיותרות. השתדל לספק לו שירות מודרני שיקל על עבודתו (כמו למשל השלמות אוטומטיות של טקסטים וגיבוי אוטומטי). תאפשר לבצע שגיאות בלי להציג הודעות אימה (כמה דוגמאות לכותרות של שגיאות מפחידות ומיותרות: Fatal Error, Unrecoverable Error, Unknown Error). למרות שזה לא תמיד קל מבחינה תכנותית, השתדל לתת אופציה של Undo-Redo (תבנית Memento).
    -
  6. שימוש חוזר: עשה שימוש חוזר ברכיבי ממשק (גם פנימיים וגם חיצוניים). הדבר יאפשר תחזוקה קלה ומשתמש יתרגל לאותו סגנון העבודה, יכיר מסכים חדשים ביתר קלות.

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

 

דוגמא למבנה של מסמך

  1. תוכן עניינים
  2. הסבר על מסמך (כולל מדריך לשימוש נכון במסמך - אופציונאלי)
  3. מילון מונחים (מושגים טכניים שנפגשים במסמך - אופציונאלי)
  4. מבנה של חלון ראשי (תשתית)
  5. שירותי תשתית UI (השירותים ברמת GUI שכל מודול יכול לצרוך מתשתית, כמו: שירותי הדפסה, איות, עזרה, חיפוש, סרגלי כלים, תפריטים וכו')
  6. מפת מסכים (לרוב בתחילת הפרויקט לא ידוע אילו מסכים יהיו, המפה תכלול מסכי תשתית וחלק מהמסכים הראשיים, עיקרה לתת הנחייה כיצד לבנות מפות פר מודול)
  7. רשימת סטנדרטים (פירוט מלא + דוגמאות)
  8. רשימת GUI Widgets (סט פקדים של הפרויקט + דוגמאות שימוש)
  9. סגנון גראפי (ראה הסבר למעלה לגבי Look-and-Feel)
  10. רשימת תבניות מוכנות (כמובן מלווה בדוגמאות)
  11. מילון עסקי עבור UI (רשימה עם טקסטים עבור כפתורים, תוויות והודעות)
  12. מדריך לבניה נכונה של מסך (עם דוגמא ממשית מתוך הפרויקט)
  13. משאבים משותפים (מקשי קיצורי דרך גלובאליים, טבלאות מערכת, גלריית אייקונים/תמונות, מילוני לוקליזציה, הודעות שגיאה, לוגרים ועוד)
  14. דוגמאות "עשה" ו"לא עשה" (צילומי מסך עם הסברים)
  15. רשימת טיפים ועקרונות מנחים
  16. רשימה של אנשי קשר ואחראים (לפני סגירת המסמך קבע מיהם האנשים שירכזו את נושא ה- UI ויהיה בקשר איתך)
  17. מקורות

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


בהצלחה ;-)


מקורות מידע נוספים:

http://www.ambysoft.com/essays/userInterfaceDesign.html

http://www.fltk.org/hig.php

http://www.humanfactors.com/downloads/aug04.asp

http://msdn.microsoft.com/en-us/library/aa217660(office.11).aspx

http://www.pbdr.com/guistd/index.htm

http://mip-site.lsec.dnd.ca/qsd_current_version/sw_eng/di/ui_guidance.htm

http://www.classicsys.com/css06/cfm/article.cfm?articleid=20


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

“Class to Table” = “Entity to SQL”

Recently, I deal with UML design in EA, also I design DB Entities for DBML (Linq2Sql). In regular way, programmer creates DB table and imports it into VS solution as entity class for DBML. But, sometimes we need to create DB table from existing class. I’m pretty sure that there are some free tools that can do this job, but as many code freaks I prefer to develop my own tools (mostly without looking for existing solutions).

I want to share my community contribution at http://class2table.codeplex.com/ with small application that allows generation/creation of DB tables from any .Net type. User loads assembly file, selects reflected type in combo, picks desired properties, then he can generate SQL script or to create table directly in SQL DB.

Class2Table

Remarks: This is “Quick & Dirty” application, I’ve made it as temp. solution. Any comments/improvements will be accepted with pleasure. Of course, you should understand that it is a free-beta-version and I’m not responsible for any damage that may be caused by using this application. All rights reserved ®.

Application   EXE Files on Codeplex
Application   Sources on Codeplex


 

Intelligent Mass Production Robotics

AI & IP in Mass Production:

Technorati Tags: ,,,,
Posted by Maxim | 2 comment(s)
תגים:, , ,

Interesting video about “High-Speed Robot Hand”:

I got some spooky feeling that our (humans’) doom-day is getting closer.

Technorati Tags: ,,

image

הנכם מוזמנים להצביע בעד ההרצאות שלי באתר של כנס המפתחים שאמור להתקיים ב- 14/09/2009 במשרדי מיקרוסופט ברח’ שנקר 13 בהרצליה.

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

---

ההרצאה הראשונה הנה בנושא: “3D in Silverlight” או “תלת מימד בסילברלייט”

בהרצאה זו אני הולך לדון בנושא של Rich Client Application for Internet עם שילוב של יכולות תלת ממד. נכון להיום, סילברלייט עדיין לא תומך באופן מלא בסצינות/אובייקטים תלת ממדים כמו WPF. בהרצאה אציג את הספריה Kit3D (קוד פתוח) כחלופה האפשרית לתצוגה של סצנות עם אובייקטים תלת ממדיים בשיטה הדומה ל- WPF. אציג מספר דוגמאות שממשות תלת ממד אמיתי בסילברלייט. כמו כן, אציג את היכולות של גרפיקה תלת ממדית בטכנולוגיה המתחרה של סילברלייט – Adobe Flash (גם פלאש עדיין לא תומך באופן מלא בתלת מימד). יכולות גרפיות לרידור אובקייטים תלת ממדיים פותחות אינסוף אפשרויות בפני המפתחים: משחקי תלת ממד מבוססי סילברלייט, סימולטורים, גראפים ועוד.

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

לחצו על התמונה על מנת לראות דוגמא ל- Mockup של סימולטור Netcasting של משחקים קבוצתיים כמו כדורגל, כדורסל, כדורעף ועוד (בתוך היישום לחצו על סמל עם מגרש - court):


(ניתן להתשמש ב- Sliders או עכבר לשינוי מיקום המצלמה, סיבוב המגרש ו- Zoom)

בהרצאה אציג דוגמא נוספת (יותר מתוכמת ועם אנימציות) של יישום תלת ממדי עם אובייקטים מיובאים מתוכנת 3ds Max 2009.

---

ההרצאה השניה הנה בנושא: “GUI Design for .Net Developers” או “עיצוב ממשק משתמש למפתחי דוט-נט”

הרצאה זו תעסוק בהיבטים הפרקטיים של עיצוב, פיתוח ותחזוקה של ממשקי משתמש – GUI מהצד של מפתחי הדוט-נט. כמו ההרצאה הראשונה, הרצאה זו הנה מקצועית ודנה במספר פתרונות לבעיות בפיתוח של ממשקי משתמש ע”י אנשים שלא קיבלו השכלה פורמאלית בתחום. יוזכרו כל ה- buzzwords כמו: WPF, Silverlight, CAB, WinForms מגרסאות 2.0, 3.0 ו- 3.5. יוצגו דוגמאות של תהליכי עבודה, דוגמאות קוד, ממשקים לדוגמא (טובים, גרועים וסקסיים). אדבר על הקשיים של עיצוב ממשקים ללא התערבות של גורמים כמו גראפיקאים, יועצים, מנגישים, ארגומומים ויתר האנשים שנושמים את UI על בסיס יומי. אדבר על המפתחים שעוסקים ב- GUI לפי דרישות התפקיד ועל הבעיות הנפוצות שהם נתקלים בהן, כמו כן אציע מספר פתרונות יצירתיים לבעיות אלו. אני מכיר המון פרויקטים בתחום התוכנה שבהם אחד המרכיבים בהצלחה או כישלון הפרויקט הנו UI.
בנוסף, אדבר על השיקולים בבחירת טכנולוגיה ל- GUI, אציג מספר דוגמאות לבחירה ומימוש מוצלחים (ופחות) של טכנולוגיה עם דגמאות. כמו למשל ההתלבטות בבחירה בין WPF ל- WinForms לאפליקציות בנקאיות/פיננסיות מרובות טפסים עם התממשקות למערכות חיצוניות שונות. אדבר על דרכים לחיסכון בבניה של פקדים ועל הספריות Open Source החנמיות ל- GUI. גם פה הרוב יהיה עם קוד, בלי שווק, הכל תכלס, הכל ממבט של מפתח דוט-נט.

ראו תצלום מסך של GUI מתוך אפליקציה “Media Manager” שפיתחתי ב- WPF עובר “שגב מערכות” (אציג כדוגמא בהרצאה):

Media Manager Search Results 
(לחצו על התמונה להגדלה)

---

לדעתי החומר המוצע מאוד מעניין. מקווה שתצביעו ותשפיעו ;-)

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

 

 

img_frm_back_top_logo

 


לחברה דינאמית וצעירה דרוש/ה מתכנת/ת לעבודה במשרה מלאה

דרישות התפקיד:
שליטה בסביבת פיתוח 2.0 .Net – חובה
שליטה בשפת תכנות #C – חובה
ניסיון מעשי ב- WinForms 2.0 – חובה

הערות:
היכרות עם שרת MS SQL 2005/8 – יתרון
הכרות עם שפת VB.Net – יתרון
הכרות עם סביבות פיתוח .Net 3.0/3.5 – יתרון
יכולת למידה/עבודה עצמאית – יתרון

נא לשלוח קו"ח לדוא"ל: avshi@segevsystems.tv



העבודה מעניינת, באווירה כפרית של קיבוץ “גליל ים” הנמצא במרכז הרצליה.
פרטים על החברה ניתן למצוא באתר:
http://www.segevsystems.tv.

 

Technorati Tags: ,,,,,

Design Sales (Banner)

Import 3D Model to WPF from any 3D Editor

Many 3D editors can export 3D scenes as OBJ files, these files can be easily imported into WPF project and being used to build complex 3D scenes.
See how easy to import 3D scene from 3D editors (for example Blender or 3ds Max):

Blender:
blender - file - export 
blender - file - export - save as

3ds Max:
3ds max - file - export 
3ds max - file - export - save as 
After the export we get two files “scene_objects.obj” (contains definition of scene objects) and “scene_objects.mtl” (contains definition of objects’ materials).

Now we can add these files to WPF project:

Blend:
Open/cerate WPF project and add OBJ and MTL files into objects’ tree.
blend - import obj 
blend - import obj - select files 
Open target window, drag and drop added OBJ file into it.
blend - window - import obj 
The Blend generates Viewport3D with all required objects automatically.
blend - window - viewport 3d 
Now we can “play” with 3D scene: change objects’ parameters, materials, transformations, lights, animations and etc.
blend - run project

The example project with code can be downloaded from here download .

PS
I’m not responsible for any damage that may be caused by using this post or its content. Any materials in this post were provided AS IS without any changes and other meanings.

See posts about 3rd party tools for XAML: Blender2Xaml and Max2Xaml.

Silverlight is great technology with powerful graphic capabilities, allows us to build RIAs with animated 2D graphics, scalable controls, media playback, uses GPU acceleration, and much more. The Silverlight application can be developed in same environment as WPF (Blend, Visual Studio, etc), has common principles of design as WPF (XAML, Namespaces, Syntax, etc). But, still it is different and targeted for cross-platform rich-client internet applications, the project from WPF can’t be ported easily to Silverlight (I’ll not open a discussion about why we can’t easily convert projects from WPF to Silverlight). I like both technologies, and mostly the 3D graphic capabilities of WPF, that is still missing in Silverlight (the 3rd version will contain 3D transformations, but is still far away from 3D capabilities of WPF).

I want to present cool library for Silverlight - “Kit3D”, that allows presentation of 3D scenes (almost like in WPF).

From project’s homepage:

Kit3D is a 3D graphics engine for Microsoft Silverlight. There is a JavaScript version that runs on the 1.0 bits of Silverlight, however moving forward the engine will only be actively developed in C#. The library has been refactored to match the System.Windows.Media.Media3D namespace from WPF so that it closely matches development for WPF3D syntax.
For some examples of the library in action, see
http://www.markdawson.org/Kit3D.
PROJECT STATUS:
- This project is still very early on in its lifecycle, the following areas are where energy will be focused in the future:
- Bug fixes & Unit Testing - currently no unit tests for the SL code, I need to look into how to use the Silverlight unit testing framework, since unit testing frameworks like xUnit, nUnit cannot be used.
- View frustum culling - stops models that go outside the visible area of the viewport from causing rendering artifacts. Right now if you move models around outside of the visible screen space you may see visual artifacts flash on the screen as objects go behind the camera. This feature will also help improve performance for a large number of models.
- Implement more WPF3D features
DEVELOPMENT REQUIREMENTS:
- You will need a full version of Visual Studio to be able to compile the source code, since the Express versions of Visual Studio do not yet support the Silverlight Tools install.
- Need to install the Silverlight 2 dev tools from
www.silverlight.net
FUTURE DIRECTION:
Right now this project is focused on getting the core 3D engine up to scratch, however the longer term aim is to build on-top of the library with higher level constructs so that when Silverlight does release native 3D at some point in the future this library will still have value on-top of that.
PEOPLE USING KIT3D:
This is really cool - check out the video running on the cubes, also if you click on some of the cubes the layers rotate, awesome:
http://sildev.net/3DCubes/index.html.

Some cool samples by Sildev (the images are clickable):

3D Monkey

3D Cube with Video Texture

Animated 3D Scene

Summary: Current (alpha) version of “Kit3D” doesn’t support the XAML code, doesn’t have all 3D features that are available in WPF; the 3D meshes are translated to collection of 2D polygons that are rendered by Silverlight without using GPU acceleration (as WPF does). The “Kit3D” is nascent and will be improved in future, until Microsoft will add “Real” 3D support.

Silverlight Spy Snapshot

As we can see in this snapshot, the 3D Tiger is made from many polygons that are interpolated (transformed) in real-time by Silverlight render engine (see this link with some 3D examples). [The snapshot was taken from “Silverlight Spy” application]

The Kit3D is cool library that allows creation of 3D scenes in same way as I do it in WPF, see here my 3D model for Handball court that will be used for online game simulation in real-time (net casting), see here the mock-up for future application.

[use sliders or mouse to move/rotate/scale the court]

netcasting

PS
I’m writing some post about how to use this great library…

In resumption to my previous post “How to import 3D model to WPF from 3D Max” I want to present the “XAML exporter for Blender” (Blender is an open-source cross-platform 3D designer).

if(Blender.Name == Blend.Name)
{
     Debug.WriteLine(“Wiiiiii !!!! :)”);
}

This post will guide you how to use this feature thru simple example.

Software requirements for this guide: Blender 2.48a or later, Microsoft Expression Blend 2.0 (Final Release).
SDK and Framework requirements: Microsoft .Net 3.0 or 3.5.

Let’s start:

(1) Download ZIP File from here and extract it into “[X]:\[*Blender*]\.blender\scripts” directory on your hard drive (to apply changes, you have to restart Blender, if you’ve copied file when it was open).

(2) Open/create scene with 3D objects in Blender. Select objects for exports and press on “File” menu.

image

  (3) Go to “Export” sub-menu and click on “Xaml (.xaml)…”.

 image

(4) Enter file path for export and press on “Export Xaml” button.

 image

(5) Open created “xaml” file in any text editor (I prefer free “Notepad++”).

image

As we can see it contains 3D models under “Model3DGroup”, each model has definitions for “Geometry”, “*Material”, “*Back Material” and “*Transform” (* –> means that these are optional and depend on 3D object properties in Blender’s scene).

(6) Create/open WPF project in Blend.

 image

(7) Add item “Resource Dictionary” to project-tree.

 image

image

(8) Open created dictionary (XAML view), Copy-Paste XAML code from exported file into dictionary.

image

(9) The pasted “Model3DGroup” is an item in dictionary, all items must have Key-Name; add “x:Key=”modelGrp”” and remove “x:Name=”…”” tags from all nodes (dictionary cannot contain definitions with this tag). Save file and rebuild project [Ctrl]+[Shift]+[B].

   image

(10) Open “Window1.xaml” in Blend editor (Design or Spitted view), go to “Resources” tab and links saved dictionary file to opened window (right-click on Window item to open context menu).

 image

(11) Add 3D objects into main grid: “ViewPort3D” with “OrthographicCamera” + two 3D models (“ModelVisual3D”), one for “DirectionalLight” and another for our 3D objects from Blender (exported XAML contains “Model3DGroup” that can be used for 3D model content in WPF).

image

(12) Select 3D model object that was prepared to contain exported objects, go to “Properties” tab –> “Miscellaneous” –> “Content” and attach to local resource “modelGrp” (linked to dictionary).

image

After attachment we’ll see the result (maybe it will require some adjustments):

image

(13) Use object “Properties”  tab to fix/adjust scene parameters/objects.

 image

Many times we’ll prefer to adjust camera’s properties  (it is much easier then changing/transforming 3D models). Also, we can “play” with light properties.

(14) Run [F5] project to see final result.

image

The example project with code can be downloaded from here download .

Summary: It is very easy to port 3D models from Blender into XAML, the “XAML exporter for Blender” is a plug-in (script file written in Python) that converts complex scene parameters (e.g.: mesh points, texture coordinates, etc) into readable XAML file, it isn’t perfect and has some minor bugs and hopefully will be fixed in future.

PS
I’m not responsible for any damage that may be caused by using this post or its content. Any materials in this post were provided AS IS without any changes and other meanings.

keys_notificator_logo

I’m inviting you to take a part in testing of “Keys Notificator”.
This is small and useful program for keyboard monitoring that can be used to monitor common keys as [Shift], [Ctrl], [Alt], [Caps Lock], [Scroll Lock] and [Num Lock]. Very useful to alert users about change in keyboard layout like language ([Alt] + [Shift] ENG <=> HEB) or capital letters.

The “Keys Notificator” is an open-source project and is a part of my community contribution under GNU General Public License. The published/released version is “Beta” version that will be improved and extended in future. Any .NET developer can take a part in project development.

The application binaries (EXE) can be downloaded from here .

The project source code can be downloaded from here .

 

(I’m planning to write detailed and more technological post about the project in near future)

Thanks :)

 

PS
I’m not responsible for any damage that may be caused by using this post or its content. Any materials in this post were provided AS IS without any changes and other meanings.

Recently I’ve required to add Mouse-Wheel support in some of our Silverlight projects. Quickly discovered that unfortunately this feature isn’t supported in built-in events of Silverlight (at least in versions 1.0 and 2.0). After short search I found this post with sample code that solves this problem by attaching handlers to mouse events on html page.

I made some changes in “MouseWheelHelper” class and added “UIElementExtender” class that extends classes that derived from “UIElement” class in order to provide Mouse-Wheel support.

Here small example that uses “MouseWheelHelper” and “UIElementExtender”:
(use mouse wheel to zoom-in/out, also you can change image by pasting new url into texbox)

Some code samples:

Attach even handler “HandleMouseWheel” to event from HTML-Side (each web-browser has different event for mouse-wheel):

if (HtmlPage.BrowserInformation.UserAgent.Contains("Chrome"))
   
HtmlPage.Window.AttachEvent("onmousewheel", HandleMouseWheel);
else if (HtmlPage.BrowserInformation.UserAgent.Contains("Firefox"))
   
HtmlPage.Window.AttachEvent("DOMMouseScroll", HandleMouseWheel);
else
   
HtmlPage.Document.AttachEvent("onmousewheel", HandleMouseWheel);

“HandleMouseWheel” event handler (each web-browser has specific property for mouse-wheel-delta, method corrects some values):

private void HandleMouseWheel(object sender, HtmlEventArgs args)
{
   
double delta = 0;
   
ScriptObject eventObj = args.EventObject;

   
if (eventObj.GetProperty("wheelDelta") != null)
    {
        delta = ((
double) eventObj.GetProperty("wheelDelta"));
        if (HtmlPage.Window.GetProperty("opera") != null)
            delta = -delta;
        else if (HtmlPage.BrowserInformation.UserAgent.Contains("Chrome"))
            delta /= 140;
        else
            delta /= 120;
    }
    else if (eventObj.GetProperty("detail") != null)
    {
        delta = -((
double) eventObj.GetProperty("detail"));
        if (!HtmlPage.BrowserInformation.UserAgent.Contains("Macintosh"))
            delta /= 2;
    }
     if (delta == 0 || Moved == null) return;
       
    var
wheelArgs = new MouseWheelEventArgs(delta);
     if (Moved != null) Moved(this, wheelArgs);
       
    if
(wheelArgs.Handled) args.PreventDefault();
}

Method-Extension for “UIElement”:

public static void RegisterMouseWheelHandler(this UIElement sender, EventHandler<MouseWheelEventArgs> handler){ /*...*/  }

Use of Method-Extension:

this.RegisterMouseWheelHandler(OnMouseWheel);
/* ... */
// "MouseWheel" event handler, controls "zoom" of Image control
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
    if (e == null) return;
    e.Handled = true;
    zoomDelta += e.Delta * 12;
    img.Margin = new Thickness(zoomDelta);
}

Source code for “MouseWheelHelper” can be downloaded from here .
Source code for example project can be downloaded from here .

PS
I’m not responsible for any damage that may be caused by using this post or its content. Any materials in this post were provided AS IS without any changes and other meanings.

I want to present very useful feature “XAML exporter for 3D Studio Max”. This feature contains number of MAX-Script files with code that allows exporting 3D scenes from 3D Studio Max to XAML files. “Max2Xaml” Project on Codeplex website: http://max2xaml.codeplex.com.

I’ll try to present a simple guide for this feature with some useful example.

Software requirements for this guide: 3D Studio Max 2007 or later (I use 3D Studio Max 2009), Microsoft Expression Blend 2.0 (Final Release).
SDK and Framework requirements: Microsoft .Net 3.0 or 3.5.

Let’s start:

(1) Download ZIP File from here and extract it to some directory on your hard drive.

image001

(2) Open/build scene with 3D objects in 3ds Max.

image002

(3) Ensure that each object has definition of material (this required by “Max2Xaml”).

image003

(4) Go to “MAXScript” sub-menu and click on “Run Script … ”.

image004

(5) Select “Main.ms” script file from extracted directory and click on “Open”.

image005

(6) Click on “Export” in dialog-box.

image006

(7) Type file name (with “xaml” extension) and click on “Save”.

image007

(8) This is “MAXScript” Editor window with XAML output of current scene:

image008

The output contains XAML code for “ResourceDictionary” that contains data for definitions of all scene models/objects,

image009

materials,

image010

and other data.

image011

(9) Open/create new WPF project in Blend.

image012

(10) Add existing item to project tree.

image013

(11) Selected created XAML file and click “Open”.

image014

(12) After addition of new resource dictionary merge it with resource dictionary in target window.

image015

(13) Add “Viewport3D” object into main grid (this object is used to display 3D scenes/objects).

image016

(14) Added “Viewport3D” already contains default camera. Add “ModelVisual3D” objects for each 3D model from the scene.

image017

(15) Link each model’s geometry to resource from merged dictionary.

image018

image019

(16) Material of each model can be linked to resource from merged dictionary.

image020

(17) Probably we’ll not see the 3D models.

image021

(18) We can adjust camera’s position and other parameters, and then we’ll see the models.

image022

(19) If models are black or still invisible, add new “ModelVisual3D” with light (can be “DirectionalLight”) that will “radiate” on scene objects.

image023

(20) After some adjustments of camera and light we’ll see imported models from 3ds Max.

image024

The example project with code can be downloaded from hereimage025.

Summary: Some WPF projects require complex 3D models in 3D scenes, these complex models can be made in 3D modeling software like 3ds Max and imported into WPF. This post shows how to port 3D models from 3ds Max to WPF. See next post(s) with guide for porting 3D models from “Blender” to WPF.

PS
I’m not responsible for any damage that may be caused by using this post or its content. Any materials in this post were provided AS IS without any changes and other meanings.

More Posts Next page »