WinAPI Combo Box wont show

Started by
16 comments, last by MystikReasons 7 years, 4 months ago

Hello

I have a problem with my combo box that I've created.

I've already asked in another forum, but they didn't knew the error.

Thats where I create the Combo Box and I call this Init function in the constructor.


void ComboBox::Initialize()
{
	wWindow wWindow;

	////////////////////////////////////
	//								  //
	//		Combobox Informations	  //
	//								  //    
	////////////////////////////////////	
	TCHAR Combobox_File[7][13] =
	{
		TEXT("New"), TEXT("Open"), TEXT("Add"), TEXT("Save		Ctrl+S"),
		TEXT("Save As..."), TEXT("Save All"), TEXT("Exit		Alt+F4")
	};
 
	// Create the parameters for FILE Combobox
	//
	// Uses the CreateWindow function to create a child window of 
	// the application window. The WC_COMBOBOX window style specifies  
	// that it is a combobox.
	int xPos = 100;					// Horizontal position of the window
	int yPos = 100;					// Vertical position of the window
	int nWidth = 200;				// Width of the window
	int nHeight = 200;				// Height of the window
	hWndParent = wWindow.getHwnd();	// Get the window from the Window Class

	// Create the Combobox_File
	hWndComboBox_File = CreateWindow(WC_COMBOBOX, TEXT(""),
										  CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
										  xPos, yPos, nWidth, nHeight, hWndParent, NULL, HINST_THISCOMPONENT,
										  NULL);

	TCHAR A[16];
	int k = 0;

	memset(&A, 0, sizeof(A));
	// Go trough every TEXT in the string
	for (k = 0; k <= 8; k += 1)
	{
		// Copies a string
		wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)Combobox_File[k]);

		// Add string to combobox
		SendMessage(hWndComboBox_File, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
	}

	// Send the CB_SETCURSEL message to display an initial item 
	// in the selection field  
	SendMessage(hWndComboBox_File, CB_SETCURSEL, (WPARAM)2, (LPARAM)0);

	return;
}

And here I create a instance of the Combo Box.


HRESULT wWindow::Initialize()
{
HRESULT hr;
ComboBox m_comboBox; // Create a instance for ComboBox
// Initialize all the combo boxes here

// Create the window class.
WNDCLASSEX wcex    = { sizeof(WNDCLASSEX) };

wcex.style         = CS_HREDRAW | CS_VREDRAW; // The class styles - CS_HREDRAW: Redraws the window if a movement changes the width of the client area.
// CS_VREDRAW: Redraws the window if a movement changes the height of the client area.

wcex.lpfnWndProc   = wWindow::WndProc; // A pointer to the windows procedure.
wcex.cbClsExtra   = 0; // The number of extra bytes to allocate the window-class structure.
wcex.cbWndExtra    = sizeof(LONG_PTR); // The number of extra bytes to allocate following the window instance.
wcex.hInstance     = HINST_THISCOMPONENT; // A handle to the instance that contains the window procedure for the class.
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // A handle to the class background brush.
wcex.lpszMenuName  = NULL; // Pointer to a null-terminated character string that specifies the resource name of the class menu.
wcex.hCursor       = LoadCursor(NULL, IDC_ARROW); // A handle to the class cursor, contains the cursor for the window.
wcex.lpszClassName = TEXT("DemoApp"); // The name of the class

// Register the window class.
RegisterClassEx(&wcex);

// Create the application window.
//
// Because the CreateWindow function takes its size in pixels, we
// obtain the system DPI and use it to scale the window size.
int dpiX = 0;
int dpiY = 0;
HDC hdc = GetDC(NULL);

if (hdc)
{
dpiX = GetDeviceCaps(hdc, LOGPIXELSX); // Get the pixels from width
dpiY = GetDeviceCaps(hdc, LOGPIXELSY); // Get the pixels from height
ReleaseDC(NULL, hdc);
}

// Create the window
m_hwnd = CreateWindow(TEXT("DemoApp"), // Class name.
 TEXT("CircuitSim"), // Window name.
 WS_OVERLAPPEDWINDOW |WS_HSCROLL | WS_VSCROLL, // Window style - WS_OVERLAPPEDWINDOW: The window is an overlapped window.
 CW_USEDEFAULT, // Use the default x position.
 CW_USEDEFAULT, // Use the default y position.
 static_cast<UINT>(ceil(640.f * dpiX / 96.f)), // Use the width, which we calculated with the pixels.
 static_cast<UINT>(ceil(480.f * dpiY / 96.f)), // Use the height, which we calculated with the pixels.
 NULL, // A handle to the parent window
 NULL, // A handle to a menu
 HINST_THISCOMPONENT, // A handle to the instance of the module
 this); // A pointer to a value to be passed to the window through the CREATESTRUCT structure

// Check if the window passed the following checks - S_OK: Operation sucessful
// E_FAIL: Unspecified failure
hr = m_hwnd ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
ShowWindow(m_hwnd, SW_MAXIMIZE); // Show the window - SW_MAXIMIZE: set the window to fullscreen
UpdateWindow(m_hwnd);
}

return hr;
}

Does anyone know the problem? :huh:

Best regards

MystikReasons

Advertisement
I don’t have the resources or time to look into it now, but as an aside you are not copying your strings correctly.

Your strings are “TCHAR” but you are using wcscpy_s, which copies “wchar_t”.
_tcscpy_s is meant to copy TCHAR values.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Thank you for your reply, I've changed it. ^_^

Just a quick guess, but you are passing NULL for the parent window in your combobox' CreateWindow function. That should probably be the handle of your main window. Otherwise you will have to specify the error more precisely.

Hello Prototype

No im passing a handle for the parentwindow


hWndParent = wWindow.getHwnd();	// Get the window from the Window Class

// Create the Combobox_File
	hWndComboBox_File = CreateWindow(WC_COMBOBOX, TEXT(""),
										  CBS_DROPDOWN |
										  CBS_HASSTRINGS |
										  WS_CHILD |
										  WS_OVERLAPPED |
										  WS_VISIBLE,
										  xPos,
										  yPos,
										  nWidth,
										  nHeight,
										  hWndParent, // HERE
										  NULL,
										  HINST_THISCOMPONENT,
										  NULL);

I dont get an error, it starts the program correct and it also shows the main window with my settings for it.

It seems like it doesn't get the message from the combo box but I dont know why.

EDIT: Also used the debugger to find the problem, but it works normally.

The program copies the strings and then sends via the function SendMessage.

Hello Prototype

No im passing a handle for the parentwindow

Sorry, my bad. So does the combo actually show and then, what's your WndProc look like? Perhaps you can display all incoming messages and see if you are missing something. You could also use tools like Spy++ (if that's still around:)) to monitor window messages.

HTH

Sorry, my bad. So does the combo actually show and then, what's your WndProc look like? Perhaps you can display all incoming messages and see if you are missing something. You could also use tools like Spy++ (if that's still around:)) to monitor window messages.

No the combo box doesn't show at all even if I call it in the Init function of the window.

Thats my WndProc.


LRESULT CALLBACK wWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	LRESULT result = 0;

	if (message == WM_CREATE)
	{
		LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
		wWindow *pWindow = (wWindow *)pcs->lpCreateParams;

		::SetWindowLongPtrW(
			hwnd,
			GWLP_USERDATA,
			PtrToUlong(pWindow)
		);

		result = 1;
	}
	else
	{
		wWindow *pWindow = reinterpret_cast<wWindow *>(static_cast<LONG_PTR>(
			::GetWindowLongPtrW(
				hwnd,
				GWLP_USERDATA)));

		bool wasHandled = false;

		if (pWindow)
		{
			switch (message)
			{
				case WM_COMMAND:
				{
					// If the user makes a selection from the list:
					//   Send CB_GETCURSEL message to get the index of the selected list item.
					//   Send CB_GETLBTEXT message to get the item.
					//   Display the item in a messagebox.
					if (HIWORD(wParam) == CBN_SELCHANGE)
					{
						int ItemIndex = SendMessage((HWND)lParam, (UINT)CB_GETCURSEL,
												   (WPARAM)0, (LPARAM)0);

						TCHAR  ListItem[256];

						(TCHAR)SendMessage((HWND)lParam,
										  (UINT)CB_GETLBTEXT,
										  (WPARAM)ItemIndex,
										  (LPARAM)ListItem);
						 
						// TODO:
						// Do something after that
					}

					wasHandled = true;
					result = 0;
				} break;

				// The WM_DISPLAYCHANGE message is sent to all windows when the display resolution has changed.
				case WM_DISPLAYCHANGE:
				{		
					InvalidateRect(hwnd, NULL, FALSE);
				} 
				wasHandled = true;
				result = 0;
				break;

				// Destroy the window
				case WM_DESTROY:
				{
					PostQuitMessage(0);
				} 		
				wasHandled = true;
				result = 1;
				break;
			}
		}

		if (!wasHandled)
		{
			result = DefWindowProc(hwnd, message, wParam, lParam);
		}
	}

	return result;
}

Yes I found Spy++, now I only have to find out how it works :rolleyes:

WS_CHILD | WS_OVERLAPPED

Try removing WS_OVERLAPPED. Also try calling InitCommonControlsEx.

@Amr0

How do I call the InitCommonControlsEx?

I only find this https://msdn.microsoft.com/en-us/library/windows/desktop/bb775507(v=vs.85).aspx but I dont know how to use it :rolleyes:

Can I make it this way?

Because I get an error.

Severity Code Description Project File Line Suppression State
Error LNK2019 Reference to non-resolved external symbol "__imp_InitCommonControlsEx" in function "WinMain".

INITCOMMONCONTROLSEX InitCtrlEx;

	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
	InitCtrlEx.dwICC = ICC_LINK_CLASS, ICC_PROGRESS_CLASS;
	InitCommonControlsEx(&InitCtrlEx);

	if (!InitCommonControlsEx(&InitCtrlEx))
	{
		int nResult = GetLastError();
		MessageBox(NULL,
			L"Could not initialize common controls class!",
			L"Initialization failure",
			MB_ICONERROR);
	}

EDIT: I call it in the WinMain function


INITCOMMONCOONTROLSEX icc;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_STANDARD_CLASSES;
InitCommonControlsEx(&icc);

That said, in my experience calling this function is rarely required in normal circumstances, so I doubt your problem is caused by this, because if it was, then CreateWindow() would return NULL instead of a window handle.... which you are not checking for.


hWndComboBox_File = CreateWindow(...);
if( !hWndComboBox)
    MessageBox("Failed to create combo box. Last error: " + GetLastError() );

And again, the WS_OVERLAPPED style is not valid for a child window if I'm not mistaken.

This topic is closed to new replies.

Advertisement