Hi there,
This is a strange one and has me totally stumped. I may need to post quite a bit of code which I usually don't do but I think I'll need to for this one. A brief description of what I'm trying to do follows.
I'm pulling data off the graphics adapter (card) and storing it in a vector that belongs to a class. Then I'm using that vector to load strings into a combo box and then backing it with the relevant data. The data is a width, a height, and a refresh rate all stored as unsigned integers.
Here's a snippet from the class definition:
Code:
Microsoft::WRL::ComPtr<IDXGIFactory4> mdxgiFactory;
Microsoft::WRL::ComPtr<ID3D12Device> md3dDevice;
DXGI_FORMAT mBackBufferFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
std::vector<UINT> mResolutionPair;
struct resData { UINT w = 0; UINT h = 0; UINT Hz = 0; };
std::vector<resData> comboResData;
mResolutionPair is where all the data goes. It takes 4 values at a time. Width, height, numerator, denominator. The numerator and denominator are divided to produce a refresh rate.
This is a part of the function that fills out the mResolutionPair vector:
Code:
// Call with nullptr to get list count.
output->GetDisplayModeList(mBackBufferFormat, flags, &count, nullptr);
std::vector<DXGI_MODE_DESC> modeList(count);
output->GetDisplayModeList(mBackBufferFormat, flags, &count, &modeList[0]);
for (int i = 0; i < count; i++)
{
UINT n = modeList[i].RefreshRate.Numerator;
UINT d = modeList[i].RefreshRate.Denominator;
if ( mSetRefresh && ((n / d) == 60) )
{
mResolutionPair.push_back(modeList[i].Width);
mResolutionPair.push_back(modeList[i].Height);
mResolutionPair.push_back(n);
mResolutionPair.push_back(d);
}
else if (!mSetRefresh)
{
mResolutionPair.push_back(modeList[i].Width);
mResolutionPair.push_back(modeList[i].Height);
mResolutionPair.push_back(n);
mResolutionPair.push_back(d);
}
}
It uses DirectX stuff to load the data into the vector and it works fine. I've tested it in Debug mode and written the data out into strings and it's all there and in correct order. Then follows the function that puts the strings and backing data into the combo box:
Code:
void setResolution(HWND hDlg)
{
D3DObj.comboResData.clear();
D3DClass::resData _resdata;
int j = 0;
for (int i = 0; i < D3DObj.mResolutionPair.size(); i += 4)
{
_resdata.w = D3DObj.mResolutionPair[i];
_resdata.h = D3DObj.mResolutionPair[i + 1];
_resdata.Hz = D3DObj.mResolutionPair[i + 2] / D3DObj.mResolutionPair[i + 3];
std::wstring _resolution = std::to_wstring(_resdata.w) +
L" x " + std::to_wstring(_resdata.h);
const WCHAR* resolution = _resolution.c_str();
WPARAM nI = SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_ADDSTRING, (WPARAM)0, (LPARAM)resolution);
D3DObj.comboResData.push_back(_resdata);
SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_SETITEMDATA, (WPARAM)nI, (LPARAM) & (D3DObj.comboResData[j]));
j++;
#ifdef _SKIP
D3DClass::resData* _temp = reinterpret_cast<D3DClass::resData*>(SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_GETITEMDATA, (WPARAM)nI, 0));
std::wstring _string = std::to_wstring(_temp->w) + L" " + std::to_wstring(_temp->h) +
L"\n" + std::to_wstring(_temp->Hz) + L"\n\n";
OutputDebugString(_string.c_str());
#endif
}
return;
}
Again works fine, no problems. If I change the #def from _SKIP to _DEBUG it prints all the data into the debug output with no issues.
And finally the function that puts the refresh rate into the text box:
Code:
void setRefresh(HWND hDlg)
{
WPARAM nI = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_COMBO1));
D3DClass::resData* _resData = reinterpret_cast<D3DClass::resData*>(SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_GETITEMDATA, (WPARAM)nI, 0));
D3DObj.mRefreshRate = _resData->Hz;
SetWindowTextW(GetDlgItem(hDlg, IDC_EDIT3), std::to_wstring(_resData->Hz).c_str());
#ifdef _SKIP
WPARAM nI = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_COMBO1));
D3DClass::resData* _temp = reinterpret_cast<D3DClass::resData*>(SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_GETITEMDATA, nI, (LPARAM)0));
std::wstring _string = std::to_wstring(_temp->w) + L" " + std::to_wstring(_temp->h) +
L"\n" + std::to_wstring(_temp->Hz) + L"\n\n";
OutputDebugString(_string.c_str());
#endif
return;
}
I'll show a picture of the dialog box now for clarity:
And the last piece of code to display is the dialog box message handling function. I've added spaces in parts for clarity:
Code:
INT_PTR CALLBACK ChooseRender(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
WCHAR* text = nullptr;
LRESULT checkBox = Button_GetCheck(GetDlgItem(hDlg, IDC_CHECK1));
switch (message)
{
case WM_INITDIALOG:
{
setAdapterBufferField(text, hDlg); // this works - fills out text fields for adapter
D3DObj.LogResolution(D3DObj.mdxgiFactory); // this works - fills class vector with display data
setResolution(hDlg); // this works - loads class data into combo box fields and strings for selection
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_COMBO1), 0); // this works - sets starting selection in combo box
setRefresh(hDlg); // this causes garbage value to appear - supposed to fill out refresh rate field (works in later call)
return (INT_PTR)TRUE; // setting true or false makes no difference (seemingly)
}
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
if (LOWORD(wParam) == IDC_CHECK1)
{
if (checkBox == BST_CHECKED)
{
D3DObj.mSetRefresh = true;
D3DObj.LogResolution(D3DObj.mdxgiFactory);
SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_RESETCONTENT, 0, 0);
setResolution(hDlg);
return (INT_PTR)TRUE;
}
else
{
D3DObj.mSetRefresh = false;
D3DObj.LogResolution(D3DObj.mdxgiFactory);
SendMessageW(GetDlgItem(hDlg, IDC_COMBO1), CB_RESETCONTENT, 0, 0);
setResolution(hDlg);
return (INT_PTR)TRUE;
}
}
if ((LOWORD(wParam) == IDC_COMBO1) && HIWORD(wParam) == CBN_SELCHANGE)
{
setRefresh(hDlg);
return (INT_PTR)TRUE;
}
}
return (INT_PTR)FALSE;
}
I don't really expect anyone to read all that code, I just wanted to provide it for clarity in case anyone needs to refer to it to find a problem.
Anyways the problem is....it works. Sometimes. When the dialog box initiates there is only ever a garbage value in the refresh rate field. The only way I can stop this is to check the check box in the top right. If I then re-select an item in the combo box the refresh rate show correctly.
So the issue seems to be on startup. This is where things get really confusing. The #def block I wrote in the setResolution(hDlg) outputs all the data correctly even on startup. Note that it is using the CB_ADDSTRING message to get an index (nI) for the box entry for both the function stuff and the debug output string. Seems to work fine even inside the WM_INITDIALOG block.
It's closely related setRefresh(hDlg) function however (which uses the exact same code) only ever produces a garbage value inside the WM_INITDIALOG block. To get it to work I have to check the check box and then select an entry in the combo box.
I've tried absolutely everything to get this to show a valid refresh rate on startup. I've tried SetFocus and returning FALSE as the MSDN says to. I've tried calling setRefresh with a WPARAM returned from a call to ComboBox_GetCurSel. I even re-wrote the .rc file in notepad to put the combo box entry at the top of the list so it's highlighted on startup.
None of it has worked. I even tried changing code in the #def block to print the index being used to check it was a valid integer. And it is.
The only thing I can think of, is that when inside the WM_INITDIALOG block a call to setResolution works because the OS seems happy using a CB_ADDSTRING message to get an index. It does not however seem to appreciate the manual forced setting of an index in any way whatsoever, which is what happens in the setRefresh function.
Once into the WM_COMMAND block though it runs fine once the check box has been checked or unchecked, and the setRefresh function doesn't seem to have an issue with the index when it has been retrieved from a user selection in the combo box.
So...where am I going wrong? I assume there's something wrong with the way I'm trying to retrieve an index in the setRefresh function on startup (inside the WM_INITDIALOG block). I really can't think what it is though.
Sorry that's an awfully long post but the problem has got me so stumped I really felt I needed to go all in on this one.
Thanks