locked
How to put text from SIP ? RRS feed

  • Question

  • Hi Gurus

    I created a textbox window (non-MFC way).
    Are there code examples that would show us how to allow SIP input texts into that text box I created ?
    Also is there a way to set up such that on opening the application in the text box, it contains "Enter here"
    and when the user clicks the box, the "Enter here" text disappears and allowing user to type his/her strings
    inside the text box with the SIP buttons/keyboard.


     

    // Create a text box and store the handle

    hText = CreateWindow(

    TEXT(

    "Edit"), // The class name

    TEXT(

    ""), // Default text.

    WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER,

    // the styles

    0,

    // left

    0,

    // top coord

    0,

    // width

    0,

    // height

    hWnd,

    // parent window handle

    (HMENU)ID_TEXT,

    // the ID

    gInst,

    // the app instance

    NULL);


    Sunday, May 3, 2009 4:30 AM

Answers

  • Hi,

    There are a number of APIs designed for use with the Software Input Panel (SIP) and the Input Methods (IMs) it controls.

    To get started take a look at APIs such as SHSipPreference (documented on MSDN at http://msdn.microsoft.com/en-us/library/aa458034.aspx ).

    Within a handler for the WM_SETFOCUS message you could call

    SHSipPreference(m_hWnd, SIP_UP);

    to force the SIP to appear, and likewise within a WM_KILLFOCUS message handler you could call

    SHSipPreference(m_hwnD, SIP_FORCEDOWN);

    to hide it again

    There are also other APIs such as SHHandleWMActivate and SHHandleWMSettingChange (http://msdn.microsoft.com/en-us/library/aa458055.aspx ) which can help improve the end user's experience. For example making sure the SIP pops back to the expected state when they switch to another application and return.

    Hope this helps,
    Christopher Fairbairn
    Visit my blog at http://www.christec.co.nz/blog/
    • Marked as answer by warrentang Friday, May 8, 2009 2:37 AM
    Tuesday, May 5, 2009 12:25 AM
  • // global declarations
    WNDPROC wndProcOriginal = NULL;
    LRESULT CALLBACK	WndEditSubClassProc(HWND, UINT, WPARAM, LPARAM);
    
    // in your WM_CREATE or WM_INITDIALOG handler
    // IDC_EDIT1 is the resouce identifier for the edit control
    HWND hwnd = GetDlgItem(hDlg, IDC_EDIT1);// comment this if you have dynamically created a edit control using 'CreateWindow'
    // get the window procedure address of the edit control
    wndProcOriginal = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
    // set the new subclass window procedure
    SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndEditSubClassProc);
    // set your nice little text in the edit control
    SetDlgItemText(hDlg, IDC_EDIT1, L"Enter text");
    
    // in your WM_CLOSE handler
    HWND hwnd;
    hwnd = GetDlgItem(hDlg, IDC_EDIT1);
    // set the edit control back to the original
    SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wndProcOriginal);
    
    
    // subclass procedure definition
    // you can handle additional messages here and do whatever you feel like
    LRESULT CALLBACK	WndEditSubClassProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp) 
    {
    	if( uMsg == WM_LBUTTONUP )
    		SetWindowText(hWnd, L"");
    	return CallWindowProc(wndProcOriginal, hWnd, uMsg, wp, lp);
    }
    
    
    • Marked as answer by warrentang Friday, May 8, 2009 2:38 AM
    Tuesday, May 5, 2009 12:28 AM

All replies

  • The sip text input goes to the edit control anyway. In order to get "Enter here" functionality you should subclass the edit control, then handle the WM_* mouse messages or WM_* key messages or focus related messages. I guess you got the point....
    Sunday, May 3, 2009 7:02 AM
  • Hi Saju

    Thanks for the reply.
    But I need more help on how implement it. I'm new to WM.
    Monday, May 4, 2009 4:02 PM
  • Hi,

    There are a number of APIs designed for use with the Software Input Panel (SIP) and the Input Methods (IMs) it controls.

    To get started take a look at APIs such as SHSipPreference (documented on MSDN at http://msdn.microsoft.com/en-us/library/aa458034.aspx ).

    Within a handler for the WM_SETFOCUS message you could call

    SHSipPreference(m_hWnd, SIP_UP);

    to force the SIP to appear, and likewise within a WM_KILLFOCUS message handler you could call

    SHSipPreference(m_hwnD, SIP_FORCEDOWN);

    to hide it again

    There are also other APIs such as SHHandleWMActivate and SHHandleWMSettingChange (http://msdn.microsoft.com/en-us/library/aa458055.aspx ) which can help improve the end user's experience. For example making sure the SIP pops back to the expected state when they switch to another application and return.

    Hope this helps,
    Christopher Fairbairn
    Visit my blog at http://www.christec.co.nz/blog/
    • Marked as answer by warrentang Friday, May 8, 2009 2:37 AM
    Tuesday, May 5, 2009 12:25 AM
  • // global declarations
    WNDPROC wndProcOriginal = NULL;
    LRESULT CALLBACK	WndEditSubClassProc(HWND, UINT, WPARAM, LPARAM);
    
    // in your WM_CREATE or WM_INITDIALOG handler
    // IDC_EDIT1 is the resouce identifier for the edit control
    HWND hwnd = GetDlgItem(hDlg, IDC_EDIT1);// comment this if you have dynamically created a edit control using 'CreateWindow'
    // get the window procedure address of the edit control
    wndProcOriginal = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
    // set the new subclass window procedure
    SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndEditSubClassProc);
    // set your nice little text in the edit control
    SetDlgItemText(hDlg, IDC_EDIT1, L"Enter text");
    
    // in your WM_CLOSE handler
    HWND hwnd;
    hwnd = GetDlgItem(hDlg, IDC_EDIT1);
    // set the edit control back to the original
    SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wndProcOriginal);
    
    
    // subclass procedure definition
    // you can handle additional messages here and do whatever you feel like
    LRESULT CALLBACK	WndEditSubClassProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp) 
    {
    	if( uMsg == WM_LBUTTONUP )
    		SetWindowText(hWnd, L"");
    	return CallWindowProc(wndProcOriginal, hWnd, uMsg, wp, lp);
    }
    
    
    • Marked as answer by warrentang Friday, May 8, 2009 2:38 AM
    Tuesday, May 5, 2009 12:28 AM
  • Hi Chris, Saju

    Thanks for the response.
    Chris I'll look into what you said in a bit

    Saju,
    I used CreateWindow().  With that, using your example, I would not use this as advised since I have hText as the hwnd
    HWND hwnd = GetDlgItem(hDlg, IDC_EDIT1);

    But how do I use this : SetDlgItemText(hDlg, IDC_EDIT1, L"Enter text") since I have hDlg defined; I don't have a dialog box created
    and I don't create/need a dialog box.

    Is there a workaround ? 







    Tuesday, May 5, 2009 7:44 PM
  • Hi Saju, Chris

    How do I also associate what's entered into the text box by SIP with a button I am going to create with it, much like what Google has it
    on their front page (textbox and Google search button) ?

    many thanks.
    Tuesday, May 5, 2009 8:35 PM
  • just use the edit control's window handle you get from CreateWindow() ....

    you can just call the function SetWindowText(  hEdit, L"Enter Text" ); where hEdit is the handle you got when you create the edit control.


    Tuesday, May 5, 2009 9:58 PM
  • I guess.. you want to get the text what is on the edit control ???

    if so.. then use the GetWindowText(.... ) function in the button's command handler....

    Tuesday, May 5, 2009 9:59 PM
  • Saju
    Thank you for your generous help.

    I took your suggestion/solution with textbox and the test button but I have this issue.  
    I still have trouble trying to associate a textbox with a pushbutton such that when user types in a string and press this button,
    it'll do some search with parameters put in the textbox.

    The textbox/button works like your solution above. However, sometimes the clicks don't seem to invoke the  case ID_TEST_BUTTON
    but falls to DefWindowProc(hWnd, msg, w, l).

    I created windows for the main window and its button
    The only pushbutton I have is this for this main window:

    wProcOld = NULL;  // global variable 


    // In another function to create windows
    // Create Edit text box and store handle for TEST Button                                                       
      hText = CreateWindow(
                TEXT("Testedit"),        
                TEXT(""),         
                WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, 
                0,            // left
       0,            // top
                0,            // width
       0,            // height
                hWnd,           // parent window handle
                (HMENU)ID_TEST,        // the ID TEXT
                hInst,          // the app instance
                NULL);           

      // For Edit text box control
      // edit control proc
      wProcOld = (WNDPROC)GetWindowLong(hText, GWL_WNDPROC);
      // subclass window  SetWindowLong(hText, GWL_WNDPROC, (LONG)editProc);
      // set initial edit text
      SetDlgItemText(hWnd, ID_TEXT, L"Enter here.");

      // Create Test Button
      hLabel = CreateWindow(
                L"BUTTON",                 
                L"TEST",      // button
                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,  
                0,           // X
                0,           // Y
                0,           // Width
                0,           // Height
                hWnd,          // Parent HWND
                (HMENU)ID_TEST_BUTTON,      // test ID 
                hInst,         // the app instance
                NULL);


    In WndProc, the callback for main window, I have

    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
    {

     switch (message) {
    :

     case WM_COMMAND:
       switch(LOWORD(w))
       {
               case ID_TEST_BUTTON:
        {
               :
               :
        }
        break;
       }
       break;
       
      default:
       return DefWindowProc(hWnd, msg, w, l);
     }

     return TRUE;
    }


    Issue: Every time I tried clicking the button, it sometimes trigger the search, other times it doesn't even though I pressed the button 5 - 10 times
    consecutively. I also notice that if I type in 3 letters for example, it would not start until after 3 clicks.
    I know it's hard to describe the problem here.
    I wonder if there's some WM messages that I'm missing.
    I don't have WM_CREATE since I have another custom WM message to ShowWindow
    I don't have WM_PAINT since I have another custom WM message that forces repaint using InvalidateRect(hWnd, NULL, TRUE);
    I wonder if there's something in WM_COMMAND that I'm not doing it right.

    No MFC nor .NET solutions I am allowed to use.

    Advance thanks for your help again.

    Wednesday, May 6, 2009 7:55 PM
  • Hi chz013,
        All I gave you is a generic code and a way to demonstrate the idea what you were trying to achieve. Now you using that in your code rather than trying to understand it, you will have bugs straight away.. because now everytime you click on the edit control the edit control will clean up the text you entered in the edit control. You dont want that, do you ? You can stop the subclassing anytime you like. You need to run through the subclass procedure only once ( that is whenever your window containing your edit control is displayed and till the moment the user clicks on it, at this point you should stop the subclassing ). 

        I am not sure why you have the other inconsistant behaviour with the button, I guess it must have to do with your other message handlers. More details needed if I have to comment more.

    Thursday, May 7, 2009 10:50 AM