none
GetWindowText call from subclassed window procedure in c# returns question marks instead of valid Hebrew/Arabic characters

    Question

  • Calling native GetWindowText on "edit field" from subclassed window procedure of this field in c# returns ???? instead of Hebrew characters. I am working on multilingual system (Windows 7) and am aware of Unicode issues, so I tried to define the call in proper way, even specifying marshaling attribute like

    [DllImport("user32.dll", EntryPoint = "GetWindowText", CharSet = CharSet.Unicode)]
    private extern static void GetWindowText(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);

    but corresponding code like

     GetWindowText(hWnd, stringBuilder, stringBuilder.Capacity);
    string str = stringBuilder.ToString();

    invariably fetches question marks on return.

    At the same time when I invoke this GetWindowText from inside c3 application, it returns valid Hebrew text.

    So it seems to be the specifics of where i am invoking this GetWindowText that makes the difference.

    When I subclass this edit field's window procedure, like:

              oldWndProc = SetWindowLong(editWnd, GWL_WNDPROC, newWndProc);

    where this newWndProc is defined like:

                private static IntPtr newWindowProc(IntPtr hWnd, int msg, int wParam, int lParam)
                {
                    IntPtr ret = CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam);
                    if (msg == WM_KEYUP)
                    {

                        GetWindowText(hWnd, stringBuilder, stringBuilder.Capacity);
                        string str = stringBuilder.ToString();

                        //do something important
                    }
                    return ret;
                }

    and calling GetWindowText, it returns string containing 0x3f

    However plain English content of this field gets obtained suceesfully.

    What could be the problem?

    Thanks in advance.





    • Edited by Tomer Mahlin Wednesday, February 05, 2014 3:50 PM
    Wednesday, February 05, 2014 1:50 PM

Answers

  • Hi Tomer

    basically as i understand "GetWindowText " should copy the text of the specified window's title bar (if it has one) into a buffer. Unfortunately I do not have any experience with this method (GetWindowText) yet :-) but I can understand your basic problem. 

    My first guess will be that the text get encoding according to the application and it's default setting. Therefor, from inside c sharp application, it returns different encoding then from subclassed window procedure of this field... (1) In this case you can try as first monitoring action to play with the culture and the character encoding (for example i would try first Windows-1255 and move to the next option...). It might be that you will find that in other encoding the behavior is opposite and the windows which id not work well is now the one that is working well.  

    as I mentioned I do not have any experience with GetWindowText method yet. It look like an interesting issue that i will be happy to give it some time on the weekend to check. (2)Can you upload a sample project (windows forms application) with this issue? It will help to help you faster :-) I mean a very basic application without anything except one use of hebrew that work and one use of Hebrew that do not work well.

    (3) Can I write in Hebrew or do you speak English only?
    It is much faster for me to explain in Hebrew.

    * The weekend is not so far by the way, we start the weekend on Friday (our weekend is Friay+Saturday and not Saturday + Sunday), and we are now at the end of Wednesday In Israel :-)


    [Personal Site] [Blog] [Facebook]signature

    Wednesday, February 05, 2014 5:03 PM

All replies

  • Hi Tomer

    basically as i understand "GetWindowText " should copy the text of the specified window's title bar (if it has one) into a buffer. Unfortunately I do not have any experience with this method (GetWindowText) yet :-) but I can understand your basic problem. 

    My first guess will be that the text get encoding according to the application and it's default setting. Therefor, from inside c sharp application, it returns different encoding then from subclassed window procedure of this field... (1) In this case you can try as first monitoring action to play with the culture and the character encoding (for example i would try first Windows-1255 and move to the next option...). It might be that you will find that in other encoding the behavior is opposite and the windows which id not work well is now the one that is working well.  

    as I mentioned I do not have any experience with GetWindowText method yet. It look like an interesting issue that i will be happy to give it some time on the weekend to check. (2)Can you upload a sample project (windows forms application) with this issue? It will help to help you faster :-) I mean a very basic application without anything except one use of hebrew that work and one use of Hebrew that do not work well.

    (3) Can I write in Hebrew or do you speak English only?
    It is much faster for me to explain in Hebrew.

    * The weekend is not so far by the way, we start the weekend on Friday (our weekend is Friay+Saturday and not Saturday + Sunday), and we are now at the end of Wednesday In Israel :-)


    [Personal Site] [Blog] [Facebook]signature

    Wednesday, February 05, 2014 5:03 PM
  • Thank you very much for cooperation in the first place. You may write Hebrew freely, i just got chosen English due to the terminology issues. Would be grateful for help in any language.

    I absolutely agree with you that this is codepage issue but can't figure out from where this stems and how to fix it.

    I pretty well acquainted with GetWindowText in regular Win32API/MFC environments, it has no magic in it, just sends WM_GETTEXT if control resides in the same process, and in case of edit field it just copies its content into provided memory address.

    Unfortunately this is very large product that I am tinkering with so I can't attach any pilot project. I am not free to change any cultural settings either, since this product is supposed to work in any environment, even not necessarily it has to mess with Hebrew/Arabic users

    Essentially this specific case takes place when, in code of ListView, from 'before label edit handler' (BeforeLabelEdit += HandleBeforeLabelEdit;) it happens when user tries to rename some list view item. From there I obtain edit field handler (this edit field gets created each time when user tries to edit ListView branch label and then invoke edit field procedure subclassing:

    private void HandleBeforeLabelEdit(object sender, LabelEditEventArgs e)
    {

       IntPtr editWnd = (IntPtr)NativeMethods.SendMessage(Handle,  NativeMethods.LVM_GETEDITCONTROL, 0, 0);

       
        NativeMethods.SubclassWindow(editWnd);

    }

    Please notice that in this point, when I call GetWindowText, it still returns valid Hebrew from edit field.

    Now here is the skeleton of code performing this subclassing:

    private static class NativeMethods
            private const int GWL_WNDPROC = -4;
            private const int WM_KEYUP = 0x101;

            private delegate IntPtr WinProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);         private static WinProc newWndProc = newWindowProc;
            private static IntPtr oldWndProc = IntPtr.Zero;
            private static StringBuilder stringBuilder = new StringBuilder(128);

            [DllImport("user32")]
            public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int value);

            [DllImport("user32")]
            public static extern int GetWindowLong(IntPtr hWnd, int value);

            [DllImport("user32.dll", EntryPoint = "GetWindowText", CharSet = CharSet.Unicode)]
            private extern static void GetWindowText(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);
    /*MarshalAs has been added to make sure that Unicode string  operations are involved, but this was of no avail, so just StringBuilder type may be defined as well */

            [DllImport("user32.dll")]
            private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

            public static void SubclassWindow(IntPtr editWnd)
            {

    /* GetWindowText still works good from here */

                GetWindowText(editWnd, stringBuilder, stringBuilder.Capacity);
                str = stringBuilder.ToString();
                oldWndProc = SetWindowLong(editWnd, GWL_WNDPROC, newWndProc);
            }
            private static IntPtr newWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
            {
                IntPtr ret = CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam);
                if (msg == WM_KEYUP)
                {

    /* GetWindowText works bad from here */

                    GetWindowText(hWnd, stringBuilder, stringBuilder.Capacity);
                    string str = stringBuilder.ToString();

                }
                return ret;
            }

    Now this call to GetWindowText from inside subclassed window procedure of edit field already returns set of '3f' in place of Hebrew.

    I played around with 'CharSet.ANSI' in GetWindowText definition but it evidently causes the same '3f' (question marks) to be returned from any point in code (quite predictable).

    Even more, the fact of window procedure subclassing occurs damaging by itself!!!!! On field editing, after any change, the Hebrew content previously existing in this field turns to question marks on finishing edit, only English content remains intact. And this can be well understood since control text change goes through the same subclassed window procedure.

    So my guts feeling is that the problem lays with how data type marshaling is carried out from calls inside subclassed window procedure, probably with 'unsafe' code I could get around this but unfortunately am not authorized to make the whole product 'unsafe.

    • Edited by Tomer Mahlin Thursday, February 06, 2014 6:36 AM
    Wednesday, February 05, 2014 6:27 PM
  • Ok... I moved to use 

    אהלן תומר

    * לא עברתי על ההודעה שלך עדיין, אני מגיב רק על נושא העלאת הפרוייקט.

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

    באופן תיאורטי השימוש ניראה מאוד פשוט וקל (רק עברתי בצורה מהירה על קישור אחר), אבל בהחלט יכול להיות שהנושא שאתה מעלה יחייב יותר עבודת  ניטור, ותמיד השלב הראשון בניטור זה שחזור הבעיה :-)



    [Personal Site] [Blog] [Facebook]signature

    Thursday, February 06, 2014 1:25 PM
  • Ok, I got stand alone project prepared, where the problem may be reproduced. Just start the application and try to edit one of items in left column by double clicking it. After editing is finished, the whole Hebrew found in this field turns to questiun marks (and GetWindowText works the same way , of course as one of this problem repercussions).

    Please try to download this simple project from shared:

    https://www.dropbox.com/s/qvf8p87ae7ro5u3/ListView_CSHARP.zip

    Thanks in advance.

    Thursday, February 06, 2014 6:35 PM
  • אהלן תומר

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

    בינתיים לילה טוב


    [Personal Site] [Blog] [Facebook]signature

    Thursday, February 06, 2014 9:05 PM
  • הורדתי את הפרויקט

    הרצתי אותו

    הכל רץ בלי בעיה

    רואים עברית טוב

    אבל אני לא מבין כלום מה עושים שם ומה כל הבלאגן שיש אז אולי מישה יסבירזה לא נראה כמו משהו שבכלל קשור לשאלה

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

    חבל על הזמן לעבור לפי מה שנראה לי

    תומר תבדוק את מה ששמת

    כדאי להחליף במשהו שמראה את הבעיה

    Friday, February 07, 2014 5:33 AM
  • אהלן יוסי,

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

    אסור להריץ קוד לא מוכר לפני שעוברים עליו לעומק (אלא אם ממש מכירים את מי שכתב אותו וסומכים עליו במאה אחוז). אם יש ספק כלשהו תמיד כדאי להריץ את הקוד במכונה וירטואלית שלא איכפת לכם אם היא תינזק!

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

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

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

    באפליקציית FORM מתחילה במתודה Main ולכן אני אשים נקודת עצירה Breckpoint בהוראה הראשונה במתודה (לוחצים על הפס השמאלי ב VS עם העבר עד שנוצר שם נקודה אדומה השורה מקבלת צבע אדום).
    עוד פרטים לגבי אופן העבודה של אפליקציית FORMS אפשר לקבל בבלוג הבא:
    http://ariely.info/Blog/tabid/83/EntryId/126/Closing-Main-Form-Without-exit-the-application.aspx

    טוב אני אתאר במהירות ובאופן כללי את הקוש שניתן לנו ומה הוא עושה (לא שורה שורה אלא כללית הדברים החשובים)

    האפליציה מתחילה לרוץ תוך יצירת מופע של המחלקה Form1 המוגדר כטופס ראשי של האפליציה (ראה קישור מעל לגבי מה זה טופס ראשי). נעבור למחלקה של הטופס כדי לראות מה קורה עם הגדרת מופע חדש (עלינו לבדוק את הבנאים למשל של המופע). שמים את הסמן על המילה Form1 ולוחצים F12 על מנת לעבור ישירות להגדרה של המחלקה (זה כלי של VS).

    במחלקה ניתן לראות שיש הדרה של 2 אלמנטים בהתחלה.
    System.Windows.Forms.ListView
    System.ComponentModel.Container
    אלו אלמנטים פשוטים של אפליקציית FORMS ולכן אני לא ארחיב עליהם או על השמוש בהם. אפשר לפתוח אתגוגל ולמצוא עוד חומר כיצד עובדים איתם. בעקרון ListView זה סוג של רשימה שעובדת טוב בצורה דומה לעבודה עם טבלאות ומאשרת הצגה גם בצורה של GRID.

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

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

    עתה מגיעה השורה המעניינת:

    listView1.BeforeLabelEdit += new System.Windows.Forms.LabelEditEventHandler(HandleBeforeLabelEdit);

    מה שקורה זה שאנחנו מצמידים ארוע DELEGATE חדש לאירוע של BeforeLabelEdit. ז"א בכל פעם שמישהו יתחיל לבצע עריכה של מה שיש באלמנט listView1 אז יופעל האירוע והמתודה HandleBeforeLabelEdit תרוץ. עוד רגע אני אחזור למתודה הזו מפני ששמתי לב שהאירוע בכלל לא ירוץ באפליקציה שלנו ולכן בקוד הנוכחי אין משמעות לשורה הזו.

    עתה יש לנו הדרות שונות של האלמנט listView1 וגם הוספה של כמה אלמנטים שלרשימה שתוצג בו. אבל! אין לנו בכלל הגדרה שמותר לערוץ את האלמנט :-) ברור מכאן שהקוד לא יגיע אף פעם להפעיל את האירוע עריכה כי אין עריכה בכלל. זה מראה שאו שהועתק חלק מיותר לקוד שלנו (וחבל כי זה יוצר לנו עבודה מיותרת) או שהחלק שזה חשוב לנו לשאלה אבל הקוד לא נבדק ולא ממש את האירוע.

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

    listView1.LabelEdit = true;

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

    * הערה: כשרוצים לשחזר בעיה לטובת ניטור לא צריך לבנות אלמנט כלכך מורכב! לשם מה היינו צריכים בכלל שימוש ב listView אם כל מה שרוצים זה להציג נתון חיצוני? לשם מה בכלל יש צורך בהפעלת אירוע על מנת לבצע את הפעולה במקום פשוט להפעיל את הפעולה? על אחת כמה וכמה לשם מה צריך 3 טורים מורכבים ב listView במקום נתון בודד פשוט. בשחזור בעיה צריך תמיד לפשט כמה שאפשר את הפרוייקט על מנת להישאר עם מינימום שקשור לבעיה בלבד.

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

    נעבור אם כן למתודה HandleBeforeLabelEdit: 

    מתודה זו עושה שימוש במתודה SendMessage של מחלקה חיצונית בשם BidiUtil (לתוצאה מבצעים המרה מפורשת ל IntPtr). את התוצאה שחוזרת מהמתודה אנחנ ו מעבירים אחרי כן למתודה SubclassWindow שגם היא של המחלקה החיצונית ומפעילים אותה. בואו נעבור לבדוק מה המתודות האלו עושות בפועל. נעבור לקובת של המחלקה BidiUtil

    כאן אנחנו כבר נכנסים לענין של ייבוא מתודות של user32.dll לאפליקציה שלנו. 5 מתודות שונות אנחנו מייבאים לפרויקט שלנו! לשם מה אנחנו צריכים לייבא את כל המתודות הללו ולהכביד על מי שמנסה לנטר את הבעיה שקשורה במתודה מסויימת?

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

    המתודה SendMessage אם כן היא מתודה שאנחנו מייבאים מה API של מערכת ההפעלה. אם לא מכירים את המתודות האלו אז זה זמן טוב לגוגל. במשפט אחד: המתודה SendMessage שולחת הודעת מערכת (system-provided messages) שצוינה לחלון או חלונות. היא מעבירה תהליך (handle) אל החלון, וממתינה על לסיום התהליך בחלון אליו נשלחה ההודעה. במקרה שלנו אנחנו עובדים עם החלון של הטופס הראשי של האפליקציה ומעבירים את המתודה את listView1.Handle.

    לאחר הרצת המתודה הזו, התוצאה כאמור מועברת אל המתודה SubclassWindow. מתודה זו מפעילה את המתודה SetWindowLong שייבאנו שוב מה user32.dll. כאמור יותר חומר בגוגל ובמשפט אחד: המתודה הזו משנה את המאפיינים של חלון מסויים. במקרה שלנו אנחנו עושים שימוש בתוצאה של המתודה הקודמת ז"א אנחנו עובדים על החלון של ה listView1 עדיין.

    במתודה זו אנחנו מבצעים את הפעולה הבאה:

    מפעילים את המתודה CallWindowProc (שוב מתודה שייבאנו מה user32.dll), מתודה זו מעבירה הודעה מסויימת אל הליך מסויים (Handle) של חלון מסויים. את התוצאה אנחנו מחזירים לאלמנט ret.

    עתה מבצעים בדיקה האם ההודעה שחזרה אלינו היא במקרה שווה ל WM_KEYUP (אירוע של עזיבת כפתור במקלדת).

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

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

    עד כאן להסבר מצומצם שלקח לי 7 דקות לעבור על הקוד ו 45 דקות לכתוב את ההודעה!
    אני הולך לשתות קפה :-)
    המשך יגיע...


    [Personal Site] [Blog] [Facebook]signature

    Friday, February 07, 2014 12:48 PM
  • תומר שבת שלום,

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

    1. שחזור הבעיה לשם ניטור

    כמו שכתב יוסי, מבחינתו הכל עובד ולכן אין מה לנטר :-)
    כמובן שזה לא המצב...

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

    2. זמן למידה/זמן השקעה על עזרה/ זמן משחקים בכלל

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

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

    הרעיון תמיד בפורום מבחינתי הוא שעבודת ההכנה יבצע מי שמבקש את העזרה ולא מי שנכנס לכמה דקות לעזור :-)
    אני לפעמים נכנס לפורום 15 פעמים ביום ועונה על 10 שאלות שונות אבל כל תשובה אני משקיע כמה דקות בודדות. בדרך כלל אני נכנס ביום העבודה בהפסקת הקפה למשל. לכן אני מתעלם בדרך כלל משאלות שאין עבודת הכנה.

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

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


    [Personal Site] [Blog] [Facebook]signature

    Friday, February 07, 2014 2:42 PM
  • תודה!!!!!!!!!

    אזה הסבר ענק

    אזה השקעה

    אם היה אפשר להצביע אלף פעמים הייתי מצביע אלף

    Friday, February 07, 2014 6:05 PM
  • שלום רבותי

    ככל הנראה אני הפכתי להיות קשה הבנה

    מכל ההתכתבות שלכם טפסתי רק שאתם לא רואים כל בעיה בדמו שלי.

    אנסה לחזור על מה שכתבתי כבר למעלה.

    כדי להדגים את הבעיה צריך להתחיל לערוך את המלל באחד השדות של ,ליסת-וייו, לדוגמה להוסיף אות אחד,לא משנה אנגלי או עברי.

    אחרי גם עריכה כל אותיות עבריות הופכות לסימני שאלה.

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

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

    The bottom line, as I wrote at the beginning of this thread - fact of subclassing of Window procedure of edit field affects adversely the processing of WM_GetText message.

    I tried this on 2 different machines with different cultural settings with the same result, do you mean that on your machine this problem doesn't take place?


    • Edited by Tomer Mahlin Saturday, February 08, 2014 8:25 PM
    Saturday, February 08, 2014 8:24 PM
  • תומר שבוע טוב,

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

    * אני רואה שאתה מנסה להגיע ל HANDLE של האלמנט אב של ה LISTVIEW.
    תוכל לנסות לעבוד בצורה פשוטה יותר, אולי במתודה שרצה באירוע פשוט בעזרת this.handle

                StringBuilder _MySB = new StringBuilder(256);
                ArielyUtilities.GetWindowText((IntPtr)this.Handle, _MySB, _MySB.Capacity); // 
                MessageBox.Show(_MySB.ToString(), "Yes I can", MessageBoxButtons.YesNo);
    הצלחתי לקרוא מידע מחלונות של התוכנה הנוכחית, כמו כן מחלונות של תוכנות אחרות (למשל NOTEPAD) ללא בנעיה כולל בעברית. כמו כן העברתי מידע וקיבלתי מידע חזרה גם מאלמטים של קונטרולים בחלונות. לא נתקלתי בשום בעיה הקשורה לשפה.

    [Personal Site] [Blog] [Facebook]signature

    Saturday, February 08, 2014 9:02 PM
  • Hello Guys.

    Thank you very much for cooperation and my apologies for writing English, unfortunately this editor doesn allow RTL paragraphs , so mixed Hebrew/English text appears ugly.

    First of all, indeed, the problem can't be reproduced with System local - Hebrew, only with System local - English.

    Second - this looks like shear bug in .Net framework.

    I played around a little with the stuff and found that:

    1.When CallWindowProc is defined with Unicode charset:

    [DllImport("user32.dll", CharSet = CharSet.Unicode)] 

    private extern static IntPtr SetWindowLong(IntPtr hwnd, int nIndex, IntPtr dwNewLong);

    Then in subclassed window procedure on receiving WM_GETTEXT and calling original window procedure the lParam contains Hebrew in Unicode, i.e. after:

    char[] chars = new char[128];

    Marshal.Copy(lParam, chars, 0, 128);

    'chars' array contains valid Hebrew characters, however marshalling screws the data on out and after editing, only first character remains in edit field, i.e. in ListView handler below e.Label contains only first character of original text.

           private void HandleAfterLabelEdit(object sender, LabelEditEventArgs e)
            {
                if (e.Label == null) return;
                byte[] buffer = new byte[e.Label.Length * sizeof(char)];
                System.Buffer.BlockCopy(e.Label.ToCharArray(), 0, buffer, 0, buffer.Length);

    2. However if CallWindowProc is defined without charset like:

    [DllImport("user32.dll", CharSet = CharSet.Unicode)] 

    private extern static IntPtr SetWindowLong(IntPtr hwnd, int nIndex, IntPtr dwNewLong);

    then in subclassed procedure lParam contains ????? instead of Hebrew, and indeed, this text appears in ListView branch after editing is finished.

    3. i tried various workarounds,  but didn't come up with working solution, so, probably I would be compelled to write stand alone plan 'c' DLL that performs the subclassing and corresponding processing and then will call it from c# as external DLL.


    Sunday, February 09, 2014 12:45 PM
  • היי תומר

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


    [Personal Site] [Blog] [Facebook]signature

    Sunday, February 09, 2014 1:42 PM
  • היי תומר שוב

    אני מניח שקראת את ההודעה האחרונה שלי שאומרת בקצרה שאצלי הכל עבד טוב ולא מצאתי בעיה בהצגת עברית. אני מבין שהגעת למסקנה שהדבר קשור לכך שאנחנו עושים שמוש במערכת הפעלה בעברית. כדאי לציין שכל המערכות הפעלה שלי הן באנגלית ורק אחרי ההתקנה אני מוסיף עברית. הבדיקה שלי נעשתה כאמור בשרת windows 2012 server. לשם בדיקה נוספת העתקתי כרגע את קובץ ה EXE שלי מתוך תיקיית ה Debug של הפרוייקט ישירות למכונה שיש לי בענן של מייקרוסופט. מדובר על מערכת הפעלה winows 2008r2 והכל רץ ועובד טוב. מידע נוסף על המערכת: זו מערכת הפעלה שהגיע מובנה עם פתיחת המוכנה הוירטואלית ב azure ולא מערכת שאני התקנתי מאפס. זו עמרכת הפעלה אנגלית שהוספתי לה אחרי ההתקנה את העברית. נקודה חשובה היא שהמערכת עובדת עם עברית בברירת המחדל עבור תוכנות שאינן UNICODE (זו הגדרה שיכולה להשפיע).

    אתה מעביר לנו חלקי קוד שניראים הגיוניים אבל בלי התמונה המלאה אני לא יכול להעריך מה קורה. הרעיון של לבדוק את ה System.Buffer.BlockCopy נשמע טוב לשם ניטור :-) שים לב דרך אב שבסעיף 2 וסעיף 2 שלחת לנו את אותו קוד עם CharSet = CharSet.Unicode אבל הכוונה ברורה (אני מקווה)

    אולי הנקודות הבאות יעזרו :-)

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

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

    * אני לא השתמשתי ב marshalling בכלל (אבל גם לא עבדתי בהליך דומה לשלך. מההתחלה לא מצאתי את ה HANDLE על ידי שמוש ב listView1.Handle אלא כמו שכתבתי מעל הישתמשתי ב this.Handle) בלי לראות פרוייקט מוכן שעובד לפי ההסברים בלבד אין הגיון שזה קשור לבעיה (מכיוון שאתה אומר שבמצבים מסויימים זה עובד) אבל מצד שני גישה דרך הקונטרול וגישה ישירה דרך ה sender של האירוע לא בהכרח זהים במיפוי לאותו מקום או לאותו סדר. דרך אגב באמצעות המתודות FindWindowEx וכן GetParent אפשר לנווט לנעלה ולמטה בהירארכיה של ה HANDLE-ים, כך שאם נמצאים במיקום לא מתאים אפשר להגיע אליו.

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

    ביצעתי גם משחקים ישירים ל ידי שליחת WM_GETTEXT וגם כאן לא נתקלתי בבעיות. למעשה ביצעתי עוד לפני השימוש במתודה GetWindowText מכיוון שזה היה לי יותר מוכר. עשיתי שימוש כל התהליכים Process.GetProcessById(processId).Threads מכאן ביצעתי סינון באמצעות המתודה EnumThreadWindows כדי לקבל את התהליכים שיש להם חלון והכנסתי את כל התוצאה לאוסף של HANDLE-ים. בשלב השני עברתי בלולאה על כל האיברים של האוסף ושלחתי הודעה באמצעות המתודה SendMessage תוך שימוש באלמנט StringBuilder כפרמטר. את כל התוצאות הצגתי ב MessageBox אחד לשם הבדיקה וכל החלונות באמת הופיעו טוב כולל אלו שבעברית.

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

    אני מקווה שזה ייתן עוד כיוון ואולי יוביל לפתרון :-)


    [Personal Site] [Blog] [Facebook]signature

    Sunday, February 09, 2014 2:41 PM
  • Thank you for detailed note.

    Since, the problem only occurs on systems with none Hebrew system local (I checked this thoroughly), I tried to follow your advice by playing around with thread CULUTRE, by setting it to Hebrew:

    Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("he-IL");

    This doesn't help, apparently this is immutable 'InstalledUICulture' that corresponds to system local (GetSystemDefaultUILanguage) who calls the shots and defines the code page conversion during marshaling..

    As for sending WM_GETTEXT, first of all it has exactly the same effect but after all I am interested primarily to subclass the field window procedure and make some important things there, no way around.

    Sunday, February 09, 2014 4:45 PM
  • בשביל לקרוא אנגלית אני לא צריך להיכנס לMSDN הישראלי.

    חבל.

    Sunday, February 09, 2014 4:55 PM
  • no way around.

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

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

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

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

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

    בכל מקרה אני מקווה שהצלחנו לתרום מעט :-)


    [Personal Site] [Blog] [Facebook]signature

    Sunday, February 09, 2014 7:30 PM
  • ואם תיגש ל MSDN העולמי אז מה? אני גם שם LOL :-)
    אני הישראלי היחיד אני חושב שגם מנהל בפורומים של MSDN העולמי

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

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

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


    [Personal Site] [Blog] [Facebook]signature

    Sunday, February 09, 2014 7:37 PM
  • אני, נמצא פה רק בגלל העברית.

    אלמלא השפה הזו, יש פורומים, בלי להעליב, פוריים יותר, ביניהם הMSDN העולמי.

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


    Monday, February 10, 2014 10:55 AM
  • ברור שזה נכון :-)

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

    אם הפורום טוב או לא, אם הוא פעיל או לא... אלו כבר שאלות אחרות :-)


    [Personal Site] [Blog] [Facebook]signature

    Monday, February 10, 2014 11:01 AM
  • Agree that each problem has its own solution and I came up with few workarounds, but in principle there exists severe problem with window procedure subclassing in .NET, at least to my humble understanding.

    I would only like to make it clear, when I speak of English system local in which the problem does exist, I mean

    that found on 'Adminstrative' tab, 'Current language for none Unicode programs.

    Many thanks for your cooperation and time.

    Sincerely yours.

    Monday, February 10, 2014 3:46 PM
  • that found on 'Adminstrative' tab, 'Current language for none Unicode programs.

    נשמע הגיוני. אז הלכתי לבדוק.

    בשרת הפיתוח המרכזי שלי windows server 2012 החלפתי את הגדרות

    Control Panel\Clock, Language, and Region\Language\Advanced settings

    Language

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

    בלי לפתוח את ה VS בכלל פשוט הרצתי את קובץ ה EXE מהפרוייקט של המשחקים שלי (פתחתי קודם גם קובץ Notepade שכמובן עתה לא רואים בו את העברית אבל הכותרת עדיין בעברית ואינה תלויה בשינויים שבוצעו).

    כפי שניתן לראות בתמונה הבאה עדיין הכל עובד טוב גם בלי הגדרות ברירת מחדל של עברית!

    מה שרואים בתמונה הבאה זה את קובץ ה Notepade שלא קשור לנושא בכלל. לקובת ה Notepade ש את השם "חתימה ל MSDN" ולכן הכותרת שלו היא "חתימה ל MSDN - Notepad" (סדר האותיות בפורום מעט מבלבד אבל הרעיון צריך להיות ברור). מעל קובץ ה Notepad רואים טופס בשם "טופס ראשון Yes". טופס זה הוא הוא הטופס הראשי של המאפליקציה שלי כמובן.

    בצד שמאל של הטופס אפשר לראות פעמיים את הכותרת של קובץ ה Notepad (פעם אני קורא ישירות במתודה MAIN ופעם דרך מחלקה נפרדת). כאמור אין בעיה לקרוא נתונים בעברית של תונות אחרות.

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

    Many thanks for your cooperation and time.

    Sincerely yours.

    בכיף :-)

    אני שמח לעזור כשאני יכול.

    גלישה מהנה


    [Personal Site] [Blog] [Facebook]signature

    Monday, February 10, 2014 5:56 PM
  • תומר, אנא סמן כ"תשובה" את אחת או יותר מן התשובות שעזרו לך.

    תודה.


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

    Tuesday, February 11, 2014 9:27 AM
  • הבעיה היא כללית ולא קשורה לספה מסויימת. המרה של נתונים מתבצעת על סמך local ברירת מחדל של המערכת. אם אתם כותבים בסינית וlocal הוא צרפתי אותה תופעה תקרה גם. אנו עובדים על פתרון שעוקף את הבעיה. נפרסם אותו ברגע שנבדוק עם כמה שיותר שפות.

    לצערי אף תשובה מאלה שפורסמו למעלה לא ממש עזרה. אתכם הסליחה.

    Tuesday, February 11, 2014 9:59 AM
  • כל הטענה שלך לחלוטין לא מובנת לי ואם צריך בשביל הקטע אני מוכן לבדוק בכל שפה שתבחר (כשיהיה לי זמן וכוח כ זה מחייב לבצע RESTART לשרת הפיתוח בכל החלפה).

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

    * אין מה להתנצל אם לא קיבלת תשובה שמתאימה לך (או הסברנו גרוע ולא הבנת את התשובה) בפורום :-)
    זה חלק מחסרונות הפלטפורמה עליהן דיברתי מעל בשרשור זה :-)


    [Personal Site] [Blog] [Facebook]signature

    Tuesday, February 11, 2014 2:28 PM
  • שלום ערן (שרביט) ,

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

    http://social.msdn.microsoft.com/Forums/he-IL/6a6aaac9-bd65-4542-a13f-60b86013c523/is-there-a-way-to-programmatically-get-unicode-character-classification-for-a-given-character-?forum=nethe)

    האם אנו נוכל להמשיך את שיחה בנושאים אלה ודומים בדוא"ל ?

    מראש תודה.

    Tuesday, February 11, 2014 7:19 PM
  • הי.

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

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

    תודה,

    ערן.


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

    Wednesday, February 12, 2014 11:06 AM
  • תודה ערן על ההתיחסות, אני אמשיך עם שמואל :-))).

    Wednesday, February 12, 2014 11:47 AM