5 Replies - 790 Views - Last Post: 21 February 2013 - 09:06 AM Rate Topic: -----

#1 Kain6622  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 250
  • Joined: 18-March 10

C++ Static libraries with Dialog boxes problem

Posted 20 February 2013 - 04:04 PM

Hi there,

I'm currently working on a framework using static libraries and have hit a problem concerning dialog boxes within static libraries. Basically I have a set up screen to which the user chooses the resolution for the project at startup but when calling the dialog to open I get the error 'The specific resource type cannot be found in the image file'. I've done some searching on google to see if I could find a solution to the problem and the only things I could find where along the lines of the application instance can't be put into the static library... but the issue is that the static library also hold the instance to the application and all code related to the windows side of things, the only part of the program that does work currently is the dialog but I'm unsure what is causing the problem and am hoping someone might be able to help me resolve this issue. The coding for the dialog is as follows:

// File cSettings.h
#ifndef __CSETTINGS_H__
#define __CSETTINGS_H__

// Includes
#include <DXGI.h>
#include <tchar.h>
#include <vector>
#include <string>
#include "resource.h"

class cSettings{
public:
	cSettings();
	~cSettings();

	void						ShowDlg(HINSTANCE hInst);
	DXGI_MODE_DESC				Display(){return m_Display;}
	BOOL						IsFullscreen(){return m_Fullscreen;}
	BOOL						VSyncEnabled(){return m_vSync;}
	void						ConfirmSettings(HWND hWnd);
	void						CleanUp();
	BOOL CALLBACK				DlgProc(HWND, UINT, WPARAM, LPARAM); // Message processor for the dialog
	
	DXGI_ADAPTER_DESC			GetAdapterDesc(){return adapterDesc;}
	std::vector<DXGI_MODE_DESC> GetModes(){return vModes;}
	HWND						GetHandle(){return DlghWnd;}

	static cSettings* GetSettings()
	{ 
		return m_pSettings; 
	}

private:
	// Private functions
	void						GetAdapters();
	void						GetOutputs();
	void						GetDisplayModes();

	// Private variables
	IDXGIAdapter*				pAdapter;
	std::vector<IDXGIAdapter*>  vAdapters;
	std::vector<IDXGIOutput*>	vOutputs;
	std::vector<DXGI_MODE_DESC> vModes; 
	DXGI_ADAPTER_DESC			adapterDesc;		// contain information of the graphics adapter
	HWND						DlghWnd;

	// variable of the final settings	
	DXGI_MODE_DESC				m_Display;			// contain the select width, height and format
	BOOL						m_Fullscreen;			// is the app to run in fullscreen
	BOOL						m_vSync;				// is VSYNC enabled

protected:
	static cSettings*			m_pSettings;
};

// Functions
inline cSettings* Settings()
{ 
	return cSettings::GetSettings(); 
}

#endif


// File: cSettings.cpp

// Includes
#include "stdafx.h"
#include "cSettings.h"

cSettings* cSettings::m_pSettings = NULL;

BOOL CALLBACK DlgProcWrap(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
	// Check we have a valid main window
	assert( Settings() );

	// if so return the windoow classes wndProc function
	return Settings()->DlgProc( hDlg, msg, wParam, lParam );
};

cSettings::cSettings(): DlghWnd( NULL ){
	if( m_pSettings )
	{
		throw cError(L"Window object already instantiated!\n" );
	}

	m_pSettings = this;
	ShowDlg(AppInstance());
}

cSettings::~cSettings(){
	DestroyWindow( DlghWnd );
	m_pSettings = NULL;
}

void cSettings::ShowDlg(HINSTANCE hInst){
	GetAdapters();
	GetOutputs();
	GetDisplayModes();
	
	HRESULT hr = DialogBox(AppInstance(), MAKEINTRESOURCE(IDD_DIALOG1), GetHandle(), reinterpret_cast<DLGPROC>(DlgProcWrap));

	DWORD err = GetLastError();
	LPVOID lpMsgBuf;
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
				  FORMAT_MESSAGE_FROM_SYSTEM | 
				  FORMAT_MESSAGE_IGNORE_INSERTS,
				  NULL, 
				  GetLastError(), 
				  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
				  (LPTSTR) &lpMsgBuf, 
				  0, 
				  NULL);

	MessageBoxW( NULL, (LPCTSTR)lpMsgBuf, L"Error", MB_OK | MB_ICONINFORMATION );
	// Free the buffer.
	LocalFree( lpMsgBuf );

	if( FAILED(hr)){
		MessageBox(NULL, L"Problem with Dialog", L"Error", MB_OK);
	}
}

void cSettings::GetAdapters(){
	IDXGIFactory * pFactory = NULL;

	CreateDXGIFactory(__uuidof(IDXGIFactory) ,(void**)&pFactory);

	for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND;  ++i){
		vAdapters.push_back(pAdapter);
	}

	if(pFactory)
    {
        pFactory->Release();
    }

	vAdapters[0]->GetDesc(&adapterDesc);
}

void cSettings::GetOutputs(){
	UINT i = 0;
	IDXGIOutput * pOutput;
	while(vAdapters[0]->EnumOutputs(i, &pOutput) != DXGI_ERROR_NOT_FOUND)
	{
		vOutputs.push_back(pOutput);
		++i;
	}
}

void cSettings::GetDisplayModes(){
	UINT Modes = 0;
	DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;

	// Get the number of elements
    vOutputs[0]->GetDisplayModeList( format, 0, &Modes, NULL);

	vModes.resize(Modes); 

    // Get the list
	vOutputs[0]->GetDisplayModeList( format, 0, &Modes, vModes.data());
}

void cSettings::ConfirmSettings(HWND hWnd){
	HWND List = GetDlgItem(hWnd, IDC_RESOLUTION);
	int lbItem = 0;
	lbItem = SendDlgItemMessage(hWnd, IDC_RESOLUTION, LB_GETCURSEL, 0, 0);
	this->m_Display = vModes[lbItem];
	this->m_Fullscreen = IsDlgButtonChecked(hWnd, IDC_FULLSCREEN );
	this->m_vSync = IsDlgButtonChecked(hWnd, IDC_VSYNC );

	CleanUp();
}

void cSettings::CleanUp(){
	// Release all adapter information
	UINT i = 0;
	for( i; i < vAdapters.size(); i++ )
		vAdapters[i]->Release();

	for( i = 0; i < vOutputs.size(); i++ )
		vOutputs[i]->Release();

	vAdapters.clear();
	vOutputs.clear();
	vModes.clear();
}

BOOL CALLBACK cSettings::DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
	WCHAR s[128];
	
	switch(msg)
	{
	case WM_INITDIALOG:
		// Here we initialize our dialog to display the info
		SetDlgItemText(hWnd, IDC_ADAPTERNAME, (LPCWSTR)this->GetAdapterDesc().Description);
		SetDlgItemInt(hWnd, IDC_DEDMEM, (this->GetAdapterDesc().DedicatedVideoMemory)/1024/1024, false);
		SetDlgItemInt(hWnd, IDC_SHAREDMEM, this->GetAdapterDesc().SharedSystemMemory/1024/1024, false);
		for(int i = 0; i < this->GetModes().size(); i++ ){
			swprintf( s, TEXT("%i, %i, 32-Bit"), this->GetModes()[i].Width, this->GetModes()[i].Height);
			SendDlgItemMessage(hWnd, IDC_RESOLUTION, CB_ADDSTRING, (WPARAM)i, (LPARAM)s);
		}
		return TRUE;

	case WM_DESTROY:
		EndDialog(hWnd, 0);
		return TRUE;

	case WM_COMMAND:
		switch(wParam)
		{
		case IDOK:
			this->ConfirmSettings(hWnd);
			EndDialog(hWnd, 0);
			return TRUE;
		case IDCANCEL:
			EndDialog(hWnd, 0);
			return TRUE;
		}
		break;
	}

	return FALSE;
}


Within the Application class I make a call to a setup function which creates a new instance of the cSettings class which in turn calls the function to show the dialog, but the dialog return -1 with the message posted above constantly no matter how I try to adjust the code to find the underlying issue.

Please help.
Regards
Dave

Is This A Good Question/Topic? 0
  • +

Replies To: C++ Static libraries with Dialog boxes problem

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3535
  • View blog
  • Posts: 10,944
  • Joined: 05-May 12

Re: C++ Static libraries with Dialog boxes problem

Posted 20 February 2013 - 06:05 PM

You mentioned linking in a static library that you made no mention of linking in the .res file that contains the dialog template IDD_DIALOG1. Did you link in a .res, or compile a .rc into a .res file to be linked in?

This post has been edited by Skydiver: 20 February 2013 - 06:05 PM

Was This Post Helpful? 0
  • +
  • -

#3 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1327
  • View blog
  • Posts: 4,554
  • Joined: 19-February 09

Re: C++ Static libraries with Dialog boxes problem

Posted 20 February 2013 - 06:05 PM

Does the error tell you what part of the program is the problem?

You could pass the hinstance to the class, if that is the problem.

Also DlgProc does not need to be a callback function, since it is not used as such.
Was This Post Helpful? 0
  • +
  • -

#4 Kain6622  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 250
  • Joined: 18-March 10

Re: C++ Static libraries with Dialog boxes problem

Posted 21 February 2013 - 05:37 AM

Quote

Skydiver You mentioned linking in a static library that you made no mention of linking in the .res file that contains the dialog template IDD_DIALOG1. Did you link in a .res, or compile a .rc into a .res file to be linked in?


If I understand you correctly then the .RC file is part of the static library project not the project that includes and uses the static library. the resource.h file gets compiled with the static library but it seems it cannot compile the rc file into the static library. you mentions .res files bu i'm not sure if they are long supported in VS 2010 as I've tried to find a way to make a compiled resource script but find nothing for this IDE... (I've have used resEdit to create a .res file but I'm unsure how I use this in my static library as it doesn't seem to properly recognise the .res format in the newer version of VS).


Quote

#define Does the error tell you what part of the program is the problem?

You could pass the hinstance to the class, if that is the problem.

Also DlgProc does not need to be a callback function, since it is not used as such.


The error itself doesn't give much information apart from 'The specific resource type cannot be found in the image file', but this message gets triggered after trying to call the function DialogBox for display... but due to it being part of the static library I cannot check that the variables are valid but from looking around it seems that the .RC file cannot be compiled into the .LIB file which i think may be the main cause as they say that a resource script can only be stored within a DLL or an EXE file?

Passing hInstance into the class is already done through the function AppInstance() which returns a pointer to the application instance, so I don't think this is the issue here.

I'm not too sure where this has lead me, I'm thinking if there is a way to get a compile resource script .Res it might work with the static library but I'm unsure how this is done in visual studio 2010 or how we get a res file in work properly with in it?

I'm thinking I may need to have the resource file within the project that links the static library and somehow get those resources then into the static library to display the dialog, is this even possible?
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3535
  • View blog
  • Posts: 10,944
  • Joined: 05-May 12

Re: C++ Static libraries with Dialog boxes problem

Posted 21 February 2013 - 06:58 AM

I generally prefer to compile on the commandline using jam or make, so that I have fine control over things like this. So take what I say about what to do in the VS IDE with a grain of salt.

It sounds like you have access to the .RC file. Yes, .RC files cannot be compiled into a .LIB file. So you have to figure out how to get your primary executable to link in the compiled version of the .RC file (eg. the .RES file).

If the .RC file is static -- as in you'll never change it, then got to the command line, run rc.exe to compile the .RC file and generate a .RES file. Then go back to VS, and go to your Project Properties and look for the Linker options. I believe there is an option to link in additional dependencies, and you can add the .res file.

If the .RC file is something that you'll be changing, in VS, just add any random resources using the VS wizard. It doesn't matter what resource you add, as long as it is not given an ID of IDD_DIALOG1. Next in the solution explorer, find the .RC file auto-generated by VS, and edit it to #include the .RC file that is supposed to match up with your static library. VS will then take care of compiling the its .RC file, drag in your .RC, generate a .RES file and link it in without having to do anything with the Linker options like in the previous paragraph.

Be warned though that VS will not only autogenerate a .RC file, but it will also autogenerate a .H file that has resource ids in it. It is very likely that your .H file with the ids will collide filenames with the VS .H file. You may need to rename your files.
Was This Post Helpful? 1
  • +
  • -

#6 Kain6622  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 250
  • Joined: 18-March 10

Re: C++ Static libraries with Dialog boxes problem

Posted 21 February 2013 - 09:06 AM

Thank you very much, resolved the problem using the RC.exe as you stated and attaching it to the linker input options for additional dependencies, worked a treat. Application is working perfectly now. Thanks again for your assistance and the upgrading of my future knowledge :).
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1