I have created a combo box in my program. I have a function named add() which adds some files to the drive specified.
I searched Google on how to get the list of drives present in the computer, and found this:
DWORD var1 = 100;
WCHAR storeValue[100];
DWORD drives = GetLogicalDriveStrings(var1, storeValue);
for (int i = 0;i < 100;i++)
{
return 0;
}
I want to add the drives present in the computer to the combo box, so that my function can add files to the specified drive. How can I do this? It is quiet tricky for a beginner.
I am very well aware this will be easier when we create something to browse the drive but I wish to do this in my combo box.
GetLogicalDriveStrings fills your buffer with a double-null terminated array of strings. You can iterate through like this, stopping when the first character of the "next" string is null.
wchar_t szDrives[MAX_PATH];
if (GetLogicalDriveStrings(MAX_PATH, szDrives))
{
wchar_t* pDrive = szDrives;
while (*pDrive)
{
// do something with pDrive
// jump to next
pDrive += wcslen(pDrive) + 1;
}
}
Now the "do something with pDrive" can in your case add the string to a combo box:
SendMessage(hwndCombo, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(pDrive));
Related
The MFC feature pack seem to magically print the resources keyboard accelerator shortcuts to the tooltip of a menu item.
How would I find the key combination for any given command ID (if all I have is the HACCEL handle?).
You can use the CopyAcceleratorTable() function to retrieve the list of accelerators for a given HACCEL handle.
First, call that function with nullptr and 0 as the second and third arguments to get the size of the list (i.e. the number of accelerators) and then allocate a buffer of ACCEL structures of appropriate size.
Then you can call CopyAcceleratorTable again with a pointer to that buffer and the previously returned count.
Now you can iterate through that buffer, using the three fields of each structure to determine what the accelerator key is, what flags it has and what command it represents.
HACCEL hAcc; // Assuming this is a valid handle ...
int nAcc = CopyAcceleratorTable(hAcc, nullptr, 0); // Get number of accelerators
ACCEL *pAccel = new ACCEL[nAcc]; // Allocate the required buffer
CopyAcceleratorTable(hAcc, pAccel, nAcc); // Now copy to that buffer
for (int a = 0; a < nAcc; ++a) {
DWORD cmd = pAccel[a].cmd; // The command ID
WORD key = pAccel[a].key; // The key code - such as 0x41 for the "A" key
WORD flg = pAccel[a].fVirt; // The 'flags' (things like FCONTROL, FALT, etc)
//...
// Format and display the data, as required
//...
}
delete[] pAccel; // Don't forget to free the data when you're done!
You can see a description of the values and formats of the three data fields of the ACCEL structure on this page.
I am using wxWidgets 3.0.2 in a static unicode build on Windows 10. I am using a wxStyledTextCtrl, which is a near 1-to-1 mapping of Scintilla.
I am looking for functionality similar to Notepad++ where upon double-clicking on something in the editor, all occurrences of that item get highlighted. It is hard to find good examples that really demonstrate styling. I've looked at wxWidgets documentation, Scintilla documentation, Notepad++ source and Code::Blocks source (the latter two use Scintilla as their text editors) and still haven't had much luck.
I've tried many different variations of the following code and it never quite works right. Either nothing is highlighted or the whole document is highlighted. I know I'm missing something, but I can't figure out what.
//textarea is a wxStyledTextCtrl*
textarea->StyleSetBackground(styleHightlightAllSelected, wxColor(80, 255, 80));
wxString selectedText = textarea->GetSelectedText();
int selSize = selectedText.size();
int selStart = textarea->GetSelectionStart();
int pos = 0;
int curr = 0;
int maxPos = textarea->GetLastPosition();
while(pos != -1){
pos = textarea->FindText(curr, maxPos, selectedText);
if(pos == selStart){ //skip the actual highlighted item
curr = pos + selSize;
} else if(pos != -1){
textarea->StartStyling(pos, 0x1F);
textarea->SetStyling(selSize, styleHightlightAllSelected);
curr = pos + selSize;
}
}
The search part of the loop does successfully find the selected text; it's just that the styling doesn't seem to take hold.
So my questions that I couldn't really find answers to are:
styleHightlightAllSelected is an int set to 100. When I had it as 0, the whole document turned green when doubleclicking. I see that styles 32-39 are predefined. Are there other styles that are predefined-but-not-really-documented; meaning, is 100 ok?
Do I have to set the entire style up, or can I just set the background color as I do above?
Is it enough to do StartStyling() and SetStyling() when I find an occurrence and be done with it, or is there more?
StartStyling() in wxWidgets has a mask argument, but the Scintilla counterpart does not. I can't clearly determine what I should set this to. It seems to be 31 (00011111) to preserve the 5 existing styling/lexer bits? Essentially, I'm not sure what to set this to if all I want to do is modify the background color of each occurrence.
My program will regularly deal with files that are dozens or more megabytes in size, so should I just be highlighting occurrences that are visible, and adjust as necessary when srolling/jumping? At the moment it searches and (fails to) set styling on each occurrence, and it takes about a second on a 50MB file. I've observed that on the same file loaded in Notepad++, it happens instantly, so I'm assuming it does it on a visible basis?
I ended up asking about this on the github issues page for the Notepad++ project, and the correct way to do this is to not use styles, but rather use indicators instead. So my code above changes to this:
int maxPos = textarea->GetLastPosition();
textarea->IndicatorClearRange(0, maxPos);
textarea->IndicatorSetStyle(styleHightlightAllSelected, wxSTC_INDIC_ROUNDBOX);
textarea->IndicatorSetAlpha(styleHightlightAllSelected, 100);
textarea->IndicatorSetUnder(styleHightlightAllSelected, true);
textarea->IndicatorSetForeground(styleHightlightAllSelected, wxColor(0, 255, 0));
wxString selectedText = textarea->GetSelectedText();
int selSize = selectedText.size();
int selStart = textarea->GetSelectionStart();
int pos = 0;
int curr = 0;
vector<int> selectionList;
while((pos = textarea->FindText(curr, maxPos, selectedText)) != -1){
selectionList.push_back(pos);
curr = pos + selSize;
}
textarea->SetIndicatorCurrent(styleHightlightAllSelected);
for(unsigned int i = 0; i < selectionList.size(); i++){
if(selectionList[i] != selStart){
textarea->IndicatorFillRange(selectionList[i], selSize);
}
}
This doesn't factor in, however, only highlighting the visible range and only highlighting new occurrences as they scroll into view (I will add this later), so for files that are dozens of megabytes in size, it will take 2-3 seconds for the highlighting to finish.
have a question that has puzzled me several times and I always had to turn to owner-drawn solution - which is, however, what I don't wanna engage with this time. My problem is as the title says and here is a model situation in code:
HWND hComboBox=::CreateWindow(WC_COMBOBOX,NULL,WS_VISIBLE | WS_CHILD | CBS_HASSTRINGS | CBS_DROPDOWN,10,10,100,100,hWnd,0,hInstance,NULL);
ComboBox_SetItemData( hComboBox,
ComboBox_AddString(hComboBox,"My item 1"),
1234
);
ComboBox_SetItemData( hComboBox,
ComboBox_AddString(hComboBox,"My item 2"),
5678
);
int i=ComboBox_FindString(hComboBox,0,1234); // <-- crash
ComboBox_SetCurSel(hComboBox, i );
Apparently, I want to identify each item by its associated custom data (1234 and 5678 in this case). I know I was able to do that in Delphi but haven't yet convinced pure WinAPI to do the same thing (obvious question is what's hidden behind the Delphi's out-of-the-box functionality).
Thanks for a reply.
CBS_HASSTRINGS is meaningless in a non-owner draw combobox. In a non-owner draw combobox, every item has a string and an optional item of data, and ComboBox_FindString always looks for items using a string. Of course, 1234 isn't a valid string pointer. You're basically giving the control an invalid pointer and it's not surprising that it crashes :)
There's no built-in message that lets you search by item data in a non-owner draw combo, so you need to write your own, e.g.:
int iCount = ComboBox_GetCount(hComboBox), iFound = -1;
for (int i = 0; i < iCount; i++)
{
if (ComboBox_GetItemData(hComboBox, i) == 1234)
{
iFound = i;
break;
}
}
I am working with list control in MFC. I have written code to insert elements into list control present in a dialog box as follows:
int nIndex = 0;
for (int count = 0; count < arrResults.GetSize(); count++)
{
nIndex = m_cListCtrl.InsertItem(count, _T(arrResults[count].ElementAt(0)));
m_cListCtrl.SetItemText(nIndex, 1, _T(arrResults[count].ElementAt(1)));
}
However, when I try to retrieve data from m_cListCtrl, it always returns blank. Also, the GetItemCount() method also returns 0 items. Any suggestions are appreciated.
Following is the data retrieve code that I have written:
arrResults.SetSize(1);
arrResults[0].Add("Header1");
arrResults[0].Add("Header2");
TestDialog testDlg;
testDlg.FillControlList(arrResults); // This function has above code to add data to control list
EXPECT_EQ("Header1", queryDlg.m_cListCtrl.GetItemText(0, 0));
EXPECT_EQ("Header2", queryDlg.m_cListCtrl.GetItemText(0, 1));
The GetItemText function is returning blank string.
When you call FillControlList(), you are using testDlg object. But when you call GetItemText() you're using queryDlg object. You have inserted the items in one dialog and you're trying to get data from different object. Please check with that.
I've got a CString with a Text that also is an Item Text of my CListCtrl. For example:
CString m_SearchThisItemText = _T("Banana");
And in my CListCtrl
m_List.SetItemText (1, 1, _T ("Banana"));
Now I want to find out, on which Index the Text is.
CListCtrl::FindItem
doesnt work. It only searches the name of the Item, not the Text.
I also tried this
for (Index= 0; dlg.GetSearchContentText () == m_List.GetItemText (Index, Spalte); Index++)// HIER IST NOCH EIN FEHLER.
{
if (dlg.GetSearchContentText () == m_List.GetItemText(Index, Spalte))
{
m_List.SetItemState (Zeile, LVIS_SELECTED, LVIS_SELECTED);
m_List.SetFocus();
}
}
But it doesnt work. It stops at Index 0
Can anyone help me, how to find out on which Item the text is.
I hope you understand my question.
Iterate all the items and search in the column you want:
int nCol = 1; // to search in the second column (like your question)
CString m_SearchThisItemText = _T("Banana");
for (int i = 0; i < m_List.GetItemCount(); ++i)
{
CString szText = m_List.GetItemText(i, nCol);
if (szText == m_SearchThisItemText)
{
// found it - do something
break;
}
}
If you mean that you have a list view with several columns and you want to search in other columns than the first one, then FindItem won't help you. You'll have to explicitly write the find code yourself. You must iterate over all the rows in the list, and for each column of a row call GetItemText and compare what you get with the text you have.