I have come up with the following function which works as it should:
bool CChristianLifeMinistryStudentMaterialDlg::EncodeText(HWND hWnd, CString strCode)
{
bool bHandled = false;
map<HWND, CComboBox*> mapControls;
map<HWND, CString*> mapControlsText;
mapControls.emplace(m_cbMaterialAssignment1.GetSafeHwnd(), &m_cbMaterialAssignment1);
mapControls.emplace(m_cbMaterialAssignment2.GetSafeHwnd(), &m_cbMaterialAssignment2);
mapControls.emplace(m_cbMaterialAssignment3.GetSafeHwnd(), &m_cbMaterialAssignment3);
mapControls.emplace(m_cbMaterialAssignment4.GetSafeHwnd(), &m_cbMaterialAssignment4);
mapControlsText.emplace(m_cbMaterialAssignment1.GetSafeHwnd(), &m_strMaterialAssignment1);
mapControlsText.emplace(m_cbMaterialAssignment2.GetSafeHwnd(), &m_strMaterialAssignment2);
mapControlsText.emplace(m_cbMaterialAssignment3.GetSafeHwnd(), &m_strMaterialAssignment3);
mapControlsText.emplace(m_cbMaterialAssignment4.GetSafeHwnd(), &m_strMaterialAssignment4);
if (mapControls.find(::GetParent(hWnd)) != mapControls.end())
{
UpdateData(TRUE);
DWORD dwSel = mapControls[::GetParent(hWnd)]->GetEditSel();
CMeetingScheduleAssistantApp::EncodeText(*mapControlsText[::GetParent(hWnd)],
strCode, LOWORD(dwSel), HIWORD(dwSel));
UpdateData(FALSE);
bHandled = true;
}
else
{
map<HWND, CEdit*> mapControls;
map<HWND, CString*> mapControlsText;
mapControls.emplace(m_editBibleReading.GetSafeHwnd(), &m_editBibleReading);
mapControls.emplace(m_editDiscussionVideoTheme.GetSafeHwnd(), &m_editDiscussionVideoTheme);
mapControls.emplace(m_editDiscussionVideoMaterial.GetSafeHwnd(), &m_editDiscussionVideoMaterial);
mapControlsText.emplace(m_editBibleReading.GetSafeHwnd(), &m_strBibleReading);
mapControlsText.emplace(m_editDiscussionVideoTheme.GetSafeHwnd(), &m_strDiscussionVideoTheme);
mapControlsText.emplace(m_editDiscussionVideoMaterial.GetSafeHwnd(), &m_strDiscussionVideoMaterial);
if (mapControls.find(hWnd) != mapControls.end())
{
UpdateData(TRUE);
DWORD dwSel = mapControls[hWnd]->GetSel();
CMeetingScheduleAssistantApp::EncodeText(*mapControlsText[hWnd],
strCode, LOWORD(dwSel), HIWORD(dwSel));
UpdateData(FALSE);
bHandled = true;
}
}
return bHandled;
}
The code is straight forward to follow. But as you can see I have to potentially deal with either a comb box edit control or regular edit control. As a result, I have two sets of similar code.
Is it possible to consolidate some of this code without overcomplicating it too much? My project is set to the ISO C++ 17 Standard if that helps.
Update
Initially I thought I would try a single map of CWnd* pointers. But then I had the two problems of CComboBox verses CEdit.
CComboBox uses:
::GetParent(hWnd)
GetEditSel()
CEdit uses:
hWnd
GetSel()
By using a single list of CWnd* I no longer know which is a combo or a edit control.
—-
Update
The core problem I would like to solve is to have a single loop rather than the two.
One possibility would be to define an interface to the functionality you need, then a couple of implementations of that functionality. Add in a map to get from an HWND to the object you need, and you're off to the races:
class Writer {
virtual DWORD getSel() = 0;
CString* data;
public:
Writer(CString *data) : data(data) {}
void write(CString text) {
UpdateData(true);
DWORD selection = getSel();
CMeetingScheduleAssistantApp::EncodeText(*data, text, LOWORD(dwSel), HIWORD(dwSel));
UpdateData(false);
}
virtual ~Writer() = default;
};
class ComboBoxWriter : public writer {
CWnd *parent;
DWORD getSel() override { return parent->GetEditSel(); }
public:
ComboBoxWriter(CComboBox &dest, CString &data) : Writer(&data), parent(dest.GetParent()) {}
};
class EditCtrlWriter : public Writer {
CEdit *ctrl;
DWORD getSel() override { return ctrl->GetSel(); }
public:
EditCtrlWriter(CEdit &ctrl, CString &data) : Writer(&data), ctrl(&ctrl) {}
};
bool CChristianLifeMinistryStudentMaterialDlg::EncodeText(HWND hWnd, CString strCode) {
static std::map<HWND, Writer*> controls {
{ m_cbMaterialAssignment1.GetSafeHwnd(), new ComboBoxWriter(&m_cbMaterialAssignment1, &m_strMaterialAssignment1) },
{ m_cbMaterialAssignment2.GetSafeHwnd(), new ComboBoxWriter(&m_cbMaterialAssignment2, &m_strMaterialAssignment2) },
{ m_cbMaterialAssignment3.GetSafeHwnd(), new ComboBoxWriter(&m_cbMaterialAssignment3, &m_strMaterialAssignment3) },
{ m_cbMaterialAssignment4.GetSafeHwnd(), new ComboBoxWriter(&m_cbMaterialAssignment4, &m_strMaterialAssignment4) },
{ m_editBibleReading.GetSafeHwnd(), new EditCtrlWriter(&m_editBibleReading, &m_strBibleReading) },
{ m_editDiscussionVideoTheme.GetSafeHwnd(), new EditCtrlWriter(&m_editDiscussionVideoTheme, &m_strDiscussionVideoTheme) },
{ m_editDiscussionVideoMaterial.GetSafeHwnd(), new EditCtrlWriter(&m_editDiscussionVideoMaterial, &m_strDiscussionVideoMaterial) }
};
auto ctrl = controls.find(hwnd);
if (ctrl == controls.end())
return false;
ctrl->second->write(strCode);
return true;
}
This isn't a lot shorter overall (in fact, it's almost the same length), but quite a bit more of that length is boilerplate that's pretty easy to ignore.
Your building maps of HWND to MFC controls looks very strange.
Surely MFC already has that map. See if this helps: https://learn.microsoft.com/en-us/cpp/mfc/accessing-run-time-class-information?view=msvc-160
Based on the comments to one of the answers (#vlad-feinstein):
all HWND handles are unique system-wide
I decided that I could take a much simpler approach to simplifying my code:
bool CChristianLifeMinistryStudentMaterialDlg::EncodeText(HWND hWnd, CString strCode)
{
map<HWND, CWnd*> mapControls; // Use generic CWnd pointers
map<HWND, CString*> mapControlsText;
// Lookup map of controls
mapControls.emplace(m_cbMaterialAssignment1.GetSafeHwnd(), &m_cbMaterialAssignment1);
mapControls.emplace(m_cbMaterialAssignment2.GetSafeHwnd(), &m_cbMaterialAssignment2);
mapControls.emplace(m_cbMaterialAssignment3.GetSafeHwnd(), &m_cbMaterialAssignment3);
mapControls.emplace(m_cbMaterialAssignment4.GetSafeHwnd(), &m_cbMaterialAssignment4);
mapControls.emplace(m_editBibleReading.GetSafeHwnd(), &m_editBibleReading);
mapControls.emplace(m_editDiscussionVideoTheme.GetSafeHwnd(), &m_editDiscussionVideoTheme);
mapControls.emplace(m_editDiscussionVideoMaterial.GetSafeHwnd(), &m_editDiscussionVideoMaterial);
// Lookup map of text values
mapControlsText.emplace(m_cbMaterialAssignment1.GetSafeHwnd(), &m_strMaterialAssignment1);
mapControlsText.emplace(m_cbMaterialAssignment2.GetSafeHwnd(), &m_strMaterialAssignment2);
mapControlsText.emplace(m_cbMaterialAssignment3.GetSafeHwnd(), &m_strMaterialAssignment3);
mapControlsText.emplace(m_cbMaterialAssignment4.GetSafeHwnd(), &m_strMaterialAssignment4);
mapControlsText.emplace(m_editBibleReading.GetSafeHwnd(), &m_strBibleReading);
mapControlsText.emplace(m_editDiscussionVideoTheme.GetSafeHwnd(), &m_strDiscussionVideoTheme);
mapControlsText.emplace(m_editDiscussionVideoMaterial.GetSafeHwnd(), &m_strDiscussionVideoMaterial);
// Determine if the use clicked on a combo or edit control
bool bIsComboControl = false;
HWND hWndToUse = nullptr;
if (mapControls.find(::GetParent(hWnd)) != mapControls.end())
{
bIsComboControl = true;
hWndToUse = ::GetParent(hWnd);
}
else if (mapControls.find(hWnd) != mapControls.end())
hWndToUse = hWnd;
if (hWndToUse == nullptr)
return false;
// Process
UpdateData(TRUE);
// Get the correct selection from the control
DWORD dwSel = (bIsComboControl) ?
((CComboBox*)mapControls[hWndToUse])->GetEditSel() :
((CEdit*)mapControls[hWndToUse])->GetSel();
// Encode the text
CMeetingScheduleAssistantApp::EncodeText(*mapControlsText[hWndToUse],
strCode, LOWORD(dwSel), HIWORD(dwSel));
UpdateData(FALSE);
return true;
}
After searching all over and scratching my head a lot, I'm still not able to figure this out. haven't used smart pointers,vectors much before. Please help.
I'm trying to make deep copy of class A and i'm getting this error. the Error points to microsoft's xutility.cpp's "Template Function Copy" if this matters.
classA
{
public:
ClassA (const ClassA& origClassA)
{
ClassA::Copy(origClassA);
}
ClassA & ClassA ::operator=(const ClassA & origClassA )
{
if (this != &origClassA )
{
ClassA ::Clear();
ClassA ::Copy(origClassA );
}
return *this;
}
void ClassA ::Clear()
{
m_nId = 0;
m_pType = nullptr;
}
void ClassA ::Copy(const ClassA & fromClassA )
{
m_nId = fromClassA .m_nId;
if (fromClassA.m_pType)
{
if (!m_pType)
m_pType = std::make_unique<int>();
*m_pType = *fromClassA.m_pType;
}
}
private:
int m_nId;
std::unique_ptr<int> m_pType;
}
Class B
{
public:
ClassB(const ClassB& origClassB)
{
classB::Copy(origClassB);
}
classB& operator=(const classB& fromclassB)
{
if (this != &origClassA )
{
classB::Clear();
classB::Copy(origClassA );
}
return *this;
}
void classB::Clear()
{
m_vectorclassA.Clear();
}
void Copy(const classB& fromclassB)
{
m_vectorclassA = fromclassB.m_vectorclassA;
}
void SetVector(const std::vector<std::unique_ptr<classA>>& vectorclassA )
{
std::vector<std::unique_ptr<classA>>::const_iterator Iterator;
for (Iterator = vectorclassA.begin(); Iterator != vectorClassA.end(); Iterator++)
{
m_vectorclassA.push_back(std::make_unique<classA>(*(*Iterator)));
}
}
private:
std::vector<std::unique_ptr<classA>> m_vectorclassA;
}
m_vectorclassA = fromclassB.m_vectorclassA
Was the line causing the problem as pointed by user Igor Tandetnik
I'm using EMDK 2.5 (VS2008 and VC# and .NetCF3.5) Barcode2 class from the library to write a sample application to scan bar codes. I followed the samples available in EMDK namely CS_Barcode2Sample1 project.Every time I hardware trigger the scan the notification "E_SCN_READINCOMPATIBLE" is thrown and not able to retrieve the scanned data. The documentation doesn't say much about the cause of E_SCN_READINCOMPATIBLE notification and no luck from Google search. I tried several options including making use of Symbol.Barcode and the outcome is same.
I also tried EMDK 2.3 but the result is same.
I've pasted the whole code here....
public partial class Form1 : Form
{
private Barcode2 myBarcode2 = null;
public Form1()
{
InitializeComponent();
InitBarcode();
}
public bool InitBarcode()
{
// If the Barcode2 object is already initialized then fail the initialization.
if (myBarcode2 != null)
{
return false;
}
else // Else initialize the reader.
{
try
{
Symbol.Barcode2.Device[] AvailableDevices = Symbol.Barcode2.Devices.SupportedDevices;
if (AvailableDevices.Length == 0)
{
return false;
}
if (AvailableDevices.Length == 1)
{
//get the first available scanner in the list
Symbol.Barcode2.Device MyDevice = AvailableDevices[0];
// Create the reader, based on selected device.
myBarcode2 = new Barcode2(MyDevice);
// Attach a scan notification handler.
//this.myScanNotifyHandler = new Barcode2.OnScanHandler(myBarcode2_ScanNotify);
myBarcode2.OnScan += myBarcode2_ScanNotify;
// Attach a status notification handler.
//this.myStatusNotifyHandler = new Barcode2.OnStatusHandler(myBarcode2_StatusNotify);
myBarcode2.OnStatus += myBarcode2_StatusNotify;
myBarcode2.Config.TriggerMode = TRIGGERMODES.HARD;
// Submit a scan.
myBarcode2.Scan(5000);
}
}
catch (OperationFailureException ex)
{
MessageBox.Show("Exception Raised 1");
return false;
}
catch (InvalidRequestException ex)
{
MessageBox.Show("Exception Raised 2");
return false;
}
catch (InvalidIndexerException ex)
{
MessageBox.Show("Exception Raised 3");
return false;
}
}
return false;
}
private void myBarcode2_ScanNotify(ScanDataCollection scanDataCollection)
{
// Checks if the BeginInvoke method is required because the OnScan delegate is called by a different thread
if (this.InvokeRequired)
{
// Executes the OnScan delegate asynchronously on the main thread
this.BeginInvoke(new Barcode2.OnScanHandler(myBarcode2_ScanNotify), new object[] { scanDataCollection });
}
else
{
// Get ScanData
ScanData scanData = scanDataCollection.GetFirst;
int i;
switch (scanData.Result)
{
case Symbol.Barcode2.Results.SUCCESS:
String str = scanData.Text;
myBarcode2.Config.TriggerMode = TRIGGERMODES.HARD;
myBarcode2.Scan(5000);
break;
case Symbol.Barcode2.Results.E_SCN_READTIMEOUT:
break;
case Symbol.Barcode2.Results.CANCELED:
break;
case Symbol.Barcode2.Results.E_SCN_DEVICEFAILURE:
i = 93;
break;
default:
if (scanData.Result == Symbol.Barcode2.Results.E_SCN_READINCOMPATIBLE)
{
// If the failure is E_SCN_READINCOMPATIBLE, exit the application.
MessageBox.Show("Fatal Error");
this.Close();
return;
}
break;
}
}
}
private void myBarcode2_StatusNotify(StatusData statusData)
{
// Checks if the Invoke method is required because the OnStatus delegate is called by a different thread
if (this.InvokeRequired)
{
// Executes the OnStatus delegate on the main thread
this.Invoke(new Barcode2.OnStatusHandler(myBarcode2_StatusNotify), new object[] { statusData });
}
else
{
int i;
switch (statusData.State)
{
case States.IDLE:
break;
case States.READY:
break;
default:
break;
}
}
}
}
}
I've went thru this recently also, as I observed, it probably due to the scanner device is occupied by other application, where the scan request has been queued already, you can go to memory management, and kill the suspect app, and try your app again.
Refer to the Symbol FAQ
Hi i am trying to grab a value from my threading but it seem work not so find to me course i found that my code structure are unstable enough..here is my code i name my thread class as "clsThreadCount" and below is my implementation
public volatile bool Grab = false;
public volatile int count = 0;
public void Initialization(int i)
{
count = i;
}
public void Play()
{
Grab = false;
_shouldStop = false;
ThreadTest();
}
public void Stop()
{
_shouldStop = true;
workerThread.Join(1);
workerThread.Abort();
}
private void ThreadTest()
{
workerThread = new Thread(DoWork);
workerThread.Start();
while (!workerThread.IsAlive) ;
}
private void DoWork()
{
try
{
while (!_shouldStop)
{
if (Grab)
{
count++;
Grab = false;
}
}
}
catch (Exception)
{
Play();
}
finally
{
}
}
when my program(main menu) are starting to run i will trigger the initialize function at pass the parameter as 7
ObjThreadCount.Initialization(7); // count = 7
ObjThreadCount.Play(); // the thread are running
ObjThreadCount.Grab = true; // the grab equal to true, count++ are trigger
Thread.Sleep(100); // wait awhile
lblResult.Text = ObjThreadCount.count.ToString(); // sometime i can get count++ result (e.g. 8)
ObjThreadCount.Stop(); // thread stop
sometime my program can able to get a right counting from the thread but sometime are not.
i realize at my while loop implementation there are something are missing..
something like waitone or waitautoevent..can i ignore Thread.Sleep(100) ?? what are the suitable code should i add in the while loop ?
Please help me~ :S
** sorry in the first upload i forgot to write down "volatile" into the variable
thank you..
If C# (and C and java, and probably C++), you need to declare _shouldStop and Grab as volatile.
I got:
InvokeHelper(0x18, DISPATCH_METHOD, VT_I4, (void*)&result, NULL);
How to get function name, if we have the object method or property
specified by dwDispID = 0x18?
void AFX_CDECL InvokeHelper(
DISPID dwDispID,
WORD wFlags,
VARTYPE vtRet,
void* pvRet,
const BYTE* pbParamInfo,
...
);
Here's a simple sample of how to fetch the name
void CTestDlg::OnTypeinfo()
{
HRESULT hr = S_OK;
COleDispatchDriver sc;
sc.CreateDispatch("Omtool.ServConnect.1"); // change for your type
CComPtr<ITypeInfo> pti;
hr = sc.m_lpDispatch->GetTypeInfo(0, GetUserDefaultLCID(), &pti);
ASSERT(SUCCEEDED(hr));
CComBSTR bstrName;
UINT nCount = 0;
hr = pti->GetNames(0x2, &bstrName, 1, &nCount); // change 0x2 for your ID
ASSERT(SUCCEEDED(hr));
}
I would try to get a ITypeInfo interface on the object (CWnd::GetControlUnknown, IUnknown::QueryInterface). Then you can use the ITypeInfo::GetNames function with your member ID (0x18) to get the name of the method.