Thread: Dialog doesn't respond to tab key

  1. #1
    Registered User
    Join Date
    Aug 2004
    Posts
    5

    Question Dialog doesn't respond to tab key

    I've got a VC++.net dialog with 2 edits, 3 buttons, and some static text. None of the controls are grouped. Each non-static control has WS_TABSTOP, and I've set the Tab Order. The tab key works fine when I do "Test Dialog" in the Resource Editor, but when the program displays the dialog, the tab key is ignored.

    I've searched the forum on this topic, and found a few related posts, but none answered this question. Any ideas will be appreciated.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You need to use IsDialogMessage() in your message loop.

    gg

  3. #3
    Registered User
    Join Date
    Aug 2004
    Posts
    5
    Thanks, but I don't think there's a way to do that in this case, because this dialog is in a .dll that's a plugin for another program, and I don't have access to that program's message loop.

    Any further suggestions or other ideas?

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Well, there are ways around plugin archtectures like that - if it's a well known plugin system, perhaps others can help. What is this a plugin for?

    - ask for suggestions from the original application developers
    - use your own message loop (how this is done will depend on the plugin architecture)

    gg

  5. #5
    Registered User
    Join Date
    Aug 2004
    Posts
    5
    It's a plugin module for SynthEdit, the modular software synth program by Jeff McClintock. If it's an application-specific thing, I'll ask him about it. I just thought it might be a more generic Windows issue.

    The way the SynthEdit SDK is set up, a plugin doesn't have its own message loop. It's just a .dll with functions that get called -- event handlers for tasks like processing a block of audio samples, responding to a MIDI message, and so on. There's a base class with virtual functions for all of the calls that the host program can make to a plugin, and you override them as needed to build a particular module's functionality.

    For this module, the function I'm overriding is called whenever a change occurs in an input signal. At that point, I determine which input has changed. For one particular control voltage input, I need to put up a dialog to get some info from the user of the synth before proceding. I'm just using GetForegroundWindow() as the dialog's parent window.

    I've noticed that it's not just the tab key; the dialog also doesn't respond to the enter key to push the default button.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> I need to put up a dialog to get some info from the user of the synth before proceding.
    If you need the info from the dialog before proceding the you need to provide a message loop to run the dialog until you have that info.

    If you use a function like DialogBox() it will provide the message loop for you.

    gg

  7. #7
    Registered User
    Join Date
    Aug 2004
    Posts
    5
    I need to get control back while the dialog is being displayed, so I'm using CreateDialog(), to create a modeless dialog, rather than DialogBox().

    I've been experimenting with putting in an explicit message loop that runs until the dialog is destroyed:

    Code:
    hDlg = CreateDialog( g_hInstance,	
    		MAKEINTRESOURCE( IDD_DIALOG1 ),	
    		GetForegroundWindow(),
    		DialogProc );
    
    // store GuiModule's this ptr in hidden control so DialogProc can
    // access member functions and data
    SetDlgItemInt( hDlg, IDC_EDIT3, (UINT)this, FALSE );
    
    // customize dialog depending on situation
    SetDlgItemText( hDlg, IDC_VSTNAME_EDIT, VSTName );
    if( isRegistered )
    {
    	ShowWindow( GetDlgItem( hDlg, IDC_TRYDEMO_BUTTON ), SW_HIDE );
    	ShowWindow( GetDlgItem( hDlg, IDCANCEL ), SW_HIDE );
    	ShowWindow( GetDlgItem( hDlg, IDC_DAYSLEFT_EDIT ), SW_HIDE );
    	ShowWindow( GetDlgItem( hDlg, IDC_DEMO_EDIT1 ), SW_HIDE );
    	ShowWindow( GetDlgItem( hDlg, IDC_DEMO_EDIT2 ), SW_HIDE );
    	SetDlgItemText( hDlg, IDOK, "OK" );
    	SetDlgItemText( hDlg, IDC_REGISTRATION_EDIT, "Registered to:" );
    	SetDlgItemText( hDlg, IDC_USERID_EDIT, userID );
    	SendDlgItemMessage( hDlg, IDC_USERID_EDIT, EM_SETREADONLY, TRUE, 0 );
    	SetDlgItemText( hDlg, IDC_LICENSEKEY_EDIT, licenseKey );
    	SendDlgItemMessage( hDlg, IDC_LICENSEKEY_EDIT, EM_SETREADONLY, TRUE, 0 );
    }
    else
    {
    	SetDlgItemText( hDlg, IDC_REGISTRATION_EDIT, "Enter registration information below:" );
    	char daysStr[10];
    	itoa( demoDaysLeft, daysStr, 10 ); 
    	SetDlgItemText( hDlg, IDC_DEMO_EDIT1, "Demo period:" );
    	SetDlgItemText( hDlg, IDC_DAYSLEFT_EDIT, daysStr ); 
    	SetDlgItemText( hDlg, IDC_DEMO_EDIT2, "Days left" );
    	if( demoDaysLeft == 0 )
    	{
    		HWND hTryButton = GetDlgItem( hDlg, IDC_TRYDEMO_BUTTON );
    		EnableWindow( hTryButton, FALSE );
    	}
    }
    	
    ShowWindow( hDlg, SW_SHOW );
    HWND hUserEdit = GetDlgItem( hDlg, IDC_USERID_EDIT );
    SetFocus( hUserEdit );
    
    // grab messages while dialog active
    BOOL bRet;
    MSG msg;
    while ( IsWindow( hDlg ) 
    	&& ( bRet = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ) 
    { 
    	if ( bRet != -1 )
    	{
    		if( ! IsDialogMessage( hDlg, &msg ) )
    		{
    			TranslateMessage(&msg); 
    			DispatchMessage(&msg); 
    		}
    	} 
    }
    This works great, except for one problem: if the host program is exited while this loop is running, another function in the module is called in another thread. All module windows, including the dialog, are closed/distroyed in an orderly way, and the above loop exits when IsWindow(hDlg) fails. So far, so good, but the host program then crashes. I've tried adding
    Code:
    if( WndCount == 0 ) ExitThread( 0 );
    after the loop, but that didn't help. So I'm still stuck at the moment.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I don't see any reason why you can't use the DialogBox() function. In the code you posted, you can perform all the initialization between CreateDialog() and the message loop within the WM_INITDIALOG message within your DialogProc().

    As for the crash - you can try using NULL as your parent window (just something to try...).
    It may be that the root cause of the crash is that you're "blocking" the return of the plugin call that created the dialog. If that's the case, then you'll have to get creative with a non-blocking, multi-threaded solution that allows the plugin call to return.

    If the plugin architecture supports a "we're shutting down" API then you'll want to tap into that of course.

    gg

  9. #9
    Registered User
    Join Date
    Aug 2004
    Posts
    5
    you can perform all the initialization between CreateDialog() and the message loop within the WM_INITDIALOG message within your DialogProc
    OK. Thanks. That's the point I was missing, and making things harder than they needed to be. Thanks!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 11-23-2007, 01:48 PM
  2. Virtual keys
    By Arkanos in forum Windows Programming
    Replies: 4
    Last Post: 12-12-2005, 10:00 AM
  3. Directional Keys - Useing in Console
    By RoD in forum C++ Programming
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM
  4. FAQ: Directional Keys - Useing in Console
    By RoD in forum FAQ Board
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM