Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Problem Showing Enumerated Sound Devices in ComboBox [modified]

Problem Showing Enumerated Sound Devices in ComboBox [modified]

Scheduled Pinned Locked Moved C / C++ / MFC
tutorialc++jsonhelpquestion
8 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Paul Hasler
    wrote on last edited by
    #1

    Hi, I'm trying to work through the example code in the MSDN DirectSound Programming Guide to enumerate sound devices. When I run my app, the ComboBox which should list the available sound devices is for some reason empty. Below is the Callback Procedure I've used for the Direct Sound device enumeration.

    BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCSTR lpszDescription, LPCSTR lpszDriverName, LPVOID lpContext)
    {
    HWND hCombo = (HWND)lpContext;
    LPGUID lpTemp = NULL;

    if(lpGUID != NULL)
    {
    	if((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL)
    		return TRUE;
    	memcpy(lpTemp, lpGUID, sizeof(GUID));
    }
    ComboBox\_AddString(hCombo, lpszDescription);
    ComboBox\_SetItemData(hCombo, ComboBox\_FindString(hCombo, 0, lpszDescription), lpTemp);
    free(lpTemp);
    return TRUE;
    

    }

    FYI Inspecting lpGUID during debugging reveals that the first time the if(lpGUID != NULL) is reached, it's value is 0 so the statement evaluates to FALSE, and lpszDescription points to the 'P' of "Primary Sound Driver". The call to ComboBox_AddString processes ok without returning CB_ERR or CB_ERRSPACE. The process repeats for the other available devices, but once it's finished the ComboBox remains empty!?:confused: Below is my Callback procedure for the dialog containing the ComboBox. I've added a static text to display the total number of entries as a check, but this shows "Num Entries: 0" when I run the app. What am I missing here?

    BOOL CALLBACK DLG_AudioDeviceSelectionProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    HWND hCombo, hEntryCountText;
    int iCount;
    TCHAR szBuffer[32];

    switch(message)
    {
    case WM\_INITDIALOG:
    	hCombo = GetDlgItem(hDlg, IDC\_COMBO);
    	if(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,(VOID\*)&hCombo) != DS\_OK)
    	{
    		EndDialog(hDlg, TRUE);
    		return TRUE;
    	}
    	iCount = ComboBox\_GetCount(hCombo);
    	hEntryCountText = GetDlgItem(hDlg, IDC\_ENTRY\_COUNT);
    	wsprintf(szBuffer, TEXT("Num Entries: %i"), iCount);
    	SetWindowText(hEntryCountText, szBuffer);
    	
    case WM\_COMMAND:
    	switch(LOWORD(wParam))
    	{
    	case IDCANCEL:			
    	case IDOK:
    		EndDialog(hDlg, 0);
    		return TRUE;
    	}
    	break;
    }
    return FALSE;
    

    }

    I'm using MS VC++ 2010. I've worked through Petzold but I'm still essentially a Win API noob.

    modified on Monday, April 11, 2011 12:57 AM

    H 1 Reply Last reply
    0
    • P Paul Hasler

      Hi, I'm trying to work through the example code in the MSDN DirectSound Programming Guide to enumerate sound devices. When I run my app, the ComboBox which should list the available sound devices is for some reason empty. Below is the Callback Procedure I've used for the Direct Sound device enumeration.

      BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCSTR lpszDescription, LPCSTR lpszDriverName, LPVOID lpContext)
      {
      HWND hCombo = (HWND)lpContext;
      LPGUID lpTemp = NULL;

      if(lpGUID != NULL)
      {
      	if((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL)
      		return TRUE;
      	memcpy(lpTemp, lpGUID, sizeof(GUID));
      }
      ComboBox\_AddString(hCombo, lpszDescription);
      ComboBox\_SetItemData(hCombo, ComboBox\_FindString(hCombo, 0, lpszDescription), lpTemp);
      free(lpTemp);
      return TRUE;
      

      }

      FYI Inspecting lpGUID during debugging reveals that the first time the if(lpGUID != NULL) is reached, it's value is 0 so the statement evaluates to FALSE, and lpszDescription points to the 'P' of "Primary Sound Driver". The call to ComboBox_AddString processes ok without returning CB_ERR or CB_ERRSPACE. The process repeats for the other available devices, but once it's finished the ComboBox remains empty!?:confused: Below is my Callback procedure for the dialog containing the ComboBox. I've added a static text to display the total number of entries as a check, but this shows "Num Entries: 0" when I run the app. What am I missing here?

      BOOL CALLBACK DLG_AudioDeviceSelectionProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
      {
      HWND hCombo, hEntryCountText;
      int iCount;
      TCHAR szBuffer[32];

      switch(message)
      {
      case WM\_INITDIALOG:
      	hCombo = GetDlgItem(hDlg, IDC\_COMBO);
      	if(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,(VOID\*)&hCombo) != DS\_OK)
      	{
      		EndDialog(hDlg, TRUE);
      		return TRUE;
      	}
      	iCount = ComboBox\_GetCount(hCombo);
      	hEntryCountText = GetDlgItem(hDlg, IDC\_ENTRY\_COUNT);
      	wsprintf(szBuffer, TEXT("Num Entries: %i"), iCount);
      	SetWindowText(hEntryCountText, szBuffer);
      	
      case WM\_COMMAND:
      	switch(LOWORD(wParam))
      	{
      	case IDCANCEL:			
      	case IDOK:
      		EndDialog(hDlg, 0);
      		return TRUE;
      	}
      	break;
      }
      return FALSE;
      

      }

      I'm using MS VC++ 2010. I've worked through Petzold but I'm still essentially a Win API noob.

      modified on Monday, April 11, 2011 12:57 AM

      H Offline
      H Offline
      Hans Dietrich
      wrote on last edited by
      #2

      First of all, there is no break; after the case WM_INITDIALOG: block. If this doesn't fix the problem, then get count of the combo box after each AddString() - put a breakpoint on it to make sure it's incremented. If you still have problem, post here your code where you call AddString().

      Best wishes, Hans


      [Hans Dietrich Software]

      P 1 Reply Last reply
      0
      • H Hans Dietrich

        First of all, there is no break; after the case WM_INITDIALOG: block. If this doesn't fix the problem, then get count of the combo box after each AddString() - put a breakpoint on it to make sure it's incremented. If you still have problem, post here your code where you call AddString().

        Best wishes, Hans


        [Hans Dietrich Software]

        P Offline
        P Offline
        Paul Hasler
        wrote on last edited by
        #3

        Thank you for your response Hans. I added the break; after the case WM_INITDIALOG: block. Thank you, this was an oversight. Unfortunately it has not fixed the problem. I've now added a static int called iCount to the callback procedure where I call ComboBox_AddString(). I've used ComboBox_GetCount() to update iCount. I've also added some error handling to the ComboBox_AddString() call. When I put in a breakpoint here and debug, I see that iCount remains at 0 each time the code passes through. Below is my revised code.

        BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCSTR lpszDescription, LPCSTR lpszDriverName, LPVOID lpContext)
        {
        HWND hCombo = (HWND)lpContext;
        LPGUID lpTemp = NULL;
        static int iCount;
        if(lpGUID != NULL)
        {
        if((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL)
        return TRUE;
        memcpy(lpTemp, lpGUID, sizeof(GUID));
        }

        // Put data into ComboBox
        if(ComboBox\_AddString(hCombo, lpszDescription) == CB\_ERR | CB\_ERRSPACE)
        	{
        		MessageBox(hCombo, TEXT("Error Adding String To ComboBox"), TEXT("Error!"), MB\_OK);
        	}
        iCount = ComboBox\_GetCount(hCombo);
        ComboBox\_SetItemData(hCombo, ComboBox\_FindString(hCombo, 0, lpszDescription), lpTemp);
        free(lpTemp);
        return TRUE;
        

        }

        Is it something to do with the way I'm trying to pass the ComboBox handle to the DSEnumProc procedure when I initialize the dialog? I notice that the value of hCombo in the code below is different from the value in the code above when I debug.

        	hCombo = GetDlgItem(hDlg, IDC\_COMBO);
        	if(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,(VOID\*)&hCombo) != DS\_OK)
        	{
        		EndDialog(hDlg, TRUE);
        		return TRUE;
        	}
        

        Thank you again for your help Paul

        H 1 Reply Last reply
        0
        • P Paul Hasler

          Thank you for your response Hans. I added the break; after the case WM_INITDIALOG: block. Thank you, this was an oversight. Unfortunately it has not fixed the problem. I've now added a static int called iCount to the callback procedure where I call ComboBox_AddString(). I've used ComboBox_GetCount() to update iCount. I've also added some error handling to the ComboBox_AddString() call. When I put in a breakpoint here and debug, I see that iCount remains at 0 each time the code passes through. Below is my revised code.

          BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCSTR lpszDescription, LPCSTR lpszDriverName, LPVOID lpContext)
          {
          HWND hCombo = (HWND)lpContext;
          LPGUID lpTemp = NULL;
          static int iCount;
          if(lpGUID != NULL)
          {
          if((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL)
          return TRUE;
          memcpy(lpTemp, lpGUID, sizeof(GUID));
          }

          // Put data into ComboBox
          if(ComboBox\_AddString(hCombo, lpszDescription) == CB\_ERR | CB\_ERRSPACE)
          	{
          		MessageBox(hCombo, TEXT("Error Adding String To ComboBox"), TEXT("Error!"), MB\_OK);
          	}
          iCount = ComboBox\_GetCount(hCombo);
          ComboBox\_SetItemData(hCombo, ComboBox\_FindString(hCombo, 0, lpszDescription), lpTemp);
          free(lpTemp);
          return TRUE;
          

          }

          Is it something to do with the way I'm trying to pass the ComboBox handle to the DSEnumProc procedure when I initialize the dialog? I notice that the value of hCombo in the code below is different from the value in the code above when I debug.

          	hCombo = GetDlgItem(hDlg, IDC\_COMBO);
          	if(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,(VOID\*)&hCombo) != DS\_OK)
          	{
          		EndDialog(hDlg, TRUE);
          		return TRUE;
          	}
          

          Thank you again for your help Paul

          H Offline
          H Offline
          Hans Dietrich
          wrote on last edited by
          #4

          When you say (VOID*)&hCombo, what you're doing is passing the address of hCombo. But in your callback, you write

          HWND hCombo = (HWND)lpContext;

          So, you're doing one thing, but telling the compiler something else. Do you see what I mean? I could go further if you want.

          Best wishes, Hans


          [Hans Dietrich Software]

          P 1 Reply Last reply
          0
          • H Hans Dietrich

            When you say (VOID*)&hCombo, what you're doing is passing the address of hCombo. But in your callback, you write

            HWND hCombo = (HWND)lpContext;

            So, you're doing one thing, but telling the compiler something else. Do you see what I mean? I could go further if you want.

            Best wishes, Hans


            [Hans Dietrich Software]

            P Offline
            P Offline
            Paul Hasler
            wrote on last edited by
            #5

            Yes, I used (Void*)&hCombo and HWND hCombo = (HWND)lpContext as this was how it was written in the MSDN explanatory code snippets. I think I understand what you mean though. lpContext is a pointer which contains the address of hCombo when I pass it, so I need to dereference lpContext when I'm initializing the local hCombo in the callback, right? I've tried HWND hCombo = (HWND)*lpContext; but the IDE says "Error: expression must be a pointer to a complete object type". Is it incorrect to declare, dereference, cast and initialize all in the one statement? Thank you again. Paul

            H 1 Reply Last reply
            0
            • P Paul Hasler

              Yes, I used (Void*)&hCombo and HWND hCombo = (HWND)lpContext as this was how it was written in the MSDN explanatory code snippets. I think I understand what you mean though. lpContext is a pointer which contains the address of hCombo when I pass it, so I need to dereference lpContext when I'm initializing the local hCombo in the callback, right? I've tried HWND hCombo = (HWND)*lpContext; but the IDE says "Error: expression must be a pointer to a complete object type". Is it incorrect to declare, dereference, cast and initialize all in the one statement? Thank you again. Paul

              H Offline
              H Offline
              Hans Dietrich
              wrote on last edited by
              #6

              Actually, it would be simpler to just keep your callback code the same, and write (Void*)hCombo. A HWND will fit into a pointer-size variable, which is what lpContext is. So keep the callback like you had it before: HWND hCombo = (HWND)lpContext;

              Best wishes, Hans


              [Hans Dietrich Software]

              P 1 Reply Last reply
              0
              • H Hans Dietrich

                Actually, it would be simpler to just keep your callback code the same, and write (Void*)hCombo. A HWND will fit into a pointer-size variable, which is what lpContext is. So keep the callback like you had it before: HWND hCombo = (HWND)lpContext;

                Best wishes, Hans


                [Hans Dietrich Software]

                P Offline
                P Offline
                Paul Hasler
                wrote on last edited by
                #7

                Thanks Hans. It works. :-D I think I took MSDN's description of DirectSoundEnumerate too literally. It says:

                HRESULT DirectSoundEnumerate(
                LPDSENUMCALLBACK lpDSEnumCallback,
                LPVOID lpContext
                )

                Parameters lpDSEnumCallback Address of the DSEnumCallback function that will be called for each device installed in the system. lpContext Address of the user-defined context passed to the enumeration callback function every time that function is called. So I assumed lpContext had to be a pointer, but since it's just being passed straight on to the callback function anyway, I guess it doesn't have to be. Your help is greatly appreciated.:thumbsup: Best regards Paul

                H 1 Reply Last reply
                0
                • P Paul Hasler

                  Thanks Hans. It works. :-D I think I took MSDN's description of DirectSoundEnumerate too literally. It says:

                  HRESULT DirectSoundEnumerate(
                  LPDSENUMCALLBACK lpDSEnumCallback,
                  LPVOID lpContext
                  )

                  Parameters lpDSEnumCallback Address of the DSEnumCallback function that will be called for each device installed in the system. lpContext Address of the user-defined context passed to the enumeration callback function every time that function is called. So I assumed lpContext had to be a pointer, but since it's just being passed straight on to the callback function anyway, I guess it doesn't have to be. Your help is greatly appreciated.:thumbsup: Best regards Paul

                  H Offline
                  H Offline
                  Hans Dietrich
                  wrote on last edited by
                  #8

                  Good ol' MSDN. God's gift to consultants. :laugh: BTW, Petzold was how I learned Win32 too. If you get tired of dealing with all that wndproc stuff, check out MFC; it's a very thin wrapper over Win32, and makes a lot of things easier. Good luck. :thumbsup:

                  Best wishes, Hans


                  [Hans Dietrich Software]

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups