Measurement Studio for VB6

cancel
Showing results for 
Search instead for 
Did you mean: 

Problems overcoming Knowledgebase limitation DocID: 1ZC806FI

I am trying to manipulate a CW++ UI control from a secondary thread. The
CW++ UI control was created in the main thread. I am trying to use a user
defined message to do this control and overcome the Knowledgebase documented
limitation. The Knowledgebase Document ID: 1ZC806FI notes the limitation
that Tools for VC++ UI controls can be directly updated only from the thread
in which they were created. It suggests using a user event
to update the controls instead. This is what I am attempting to do, but
still run into problems.

I use the following call from a secondary (socket traffic handling) thread
to send my user message (WM_ICUCOMMAND) and manipulate the (here a CNiSlide)
control that is part of a modeless dialog box:

if (SendMessageTimeout(m_mdwHwnd[eMDW_IcuDlg],
WM_ICUCOMMAND, (WPARAM)nIcu, (LPARAM)nIcuState,
SMTO_NORMAL, 10 * 1000, &result) == 0)
{
// Check for timeout, or other error...
int errorCode = GetLastError();
if (errorCode == 0)
{
// Timeout has occurred...
// Echo back a Icu error
CString errMsg;
errMsg.Format("ERROR %d\n", eSocketErrorIcuError);
Send(errMsg, errMsg.GetLength());
}
else
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);

// Echo back a Icu error
CString errMsg;
errMsg.Format("ERROR %d %s\n", eSocketErrorIcuError, lpMsgBuf);
Send(errMsg, errMsg.GetLength());

// Free the buffer.
LocalFree( lpMsgBuf );
}
}


I observe that I reach my User message handler in the primary thread below:

////////////////////////////////////////////////////////////////////////////
///
// FUNCTION: OnIcuCommand( WPARAM, LPARAM )
//
// PURPOSE: Handles Windows User message to set the ICU value
//
// COMMENTS:
//
LRESULT CIcuCtl::OnIcuCommand(WPARAM wParam, LPARAM lParam)
{
// TODO: Add your control notification handler code here
int icuId = (int)wParam;
int slideValue = (int)lParam;

ASSERT(icuId >= 1 && icuId <= 4);
ASSERT(slideValue >= 0 && slideValue < 3);
if (icuId < 1 || icuId > 4 || slideValue < 0 || slideValue > 2)
{
return 1L; // Indicate error
}

switch(icuId)
{
case 1: m_icuPower1.SetValue(slideValue); break;
case 2: m_icuPower2.SetValue(slideValue); break;
case 3: m_icuPower3.SetValue(slideValue); break;
case 4: m_icuPower4.SetValue(slideValue); break;
}

return 0L; // Indicate success
}

The m_icuPower'x' class members are mapped with VC6 classwizard to the
CNiSlide controls in the dialog. When the handerl reach the CNiSlider
SetValue call, a dialog is raised:
Title:
Message in body: Unable to set the value.

I believe an exception is being thrown in the main thread as well.

Upon return to the calling thread, the value 0 is returned from the
SendMessageTimeout() call, and a subsequent check of GetLastError() gives
back a 1460 error code. FormatMessage() on this error code yields the
system message:

"This operation returned because the timeout period expired".

Please help. I just want to be able to send user messages to the UI
controls from my secondary thread.

Thanks,
Mark Greenman
Space Dynamics Laboratory
0 Kudos
Message 1 of 2
(3,280 Views)
With the timely help of NI's tech support, I was able to figure out the
problem below. The problem was not related to the use of threads, but
rather to using the wrong method to set the 'pointer' values in my CNiSlide
control. I realized that since I am using value-pair mode for the pointer,
I cannot use the SetValue() method to position the slider, but rather must
use SetValuePairIndex().

My suggestion to the National CW++ team is that a better diagnostic message
be passed along in the COleDispatchException thrown when trying to use the
SetValue() method on a UI control member that needs a SetValueIndexPair()
call instead. The current message of "Unable to set the value" was only 1/4
helpful.

Mark Greenman
Space Dynamics Laboratory

"Mark Greenman" wrote in message
news:3a241ebf@newsgroups.ni.com...
> I am trying to manipulate a CW++ UI control from a secondary thread. The
> CW++ UI control was created in the main thread. I am trying to use a user
> defined message to do this control and overcome the Knowledgebase
documented
> limitation. The Knowledgebase Document ID: 1ZC806FI notes the limitation
> that Tools for VC++ UI controls can be directly updated only from the
thread
> in which they were created. It suggests using a user event
> to update the controls instead. This is what I am attempting to do, but
> still run into problems.
>
> I use the following call from a secondary (socket traffic handling) thread
> to send my user message (WM_ICUCOMMAND) and manipulate the (here a
CNiSlide)
> control that is part of a modeless dialog box:
>
> if (SendMessageTimeout(m_mdwHwnd[eMDW_IcuDlg],
> WM_ICUCOMMAND, (WPARAM)nIcu, (LPARAM)nIcuState,
> SMTO_NORMAL, 10 * 1000, &result) == 0)
> {
> // Check for timeout, or other error...
> int errorCode = GetLastError();
> if (errorCode == 0)
> {
> // Timeout has occurred...
> // Echo back a Icu error
> CString errMsg;
> errMsg.Format("ERROR %d\n", eSocketErrorIcuError);
> Send(errMsg, errMsg.GetLength());
> }
> else
> {
> LPVOID lpMsgBuf;
> FormatMessage(
> FORMAT_MESSAGE_ALLOCATE_BUFFER |
> FORMAT_MESSAGE_FROM_SYSTEM |
> FORMAT_MESSAGE_IGNORE_INSERTS,
> NULL,
> errorCode,
> MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
> (LPTSTR) &lpMsgBuf,
> 0,
> NULL
> );
>
> // Echo back a Icu error
> CString errMsg;
> errMsg.Format("ERROR %d %s\n", eSocketErrorIcuError, lpMsgBuf);
> Send(errMsg, errMsg.GetLength());
>
> // Free the buffer.
> LocalFree( lpMsgBuf );
> }
> }
>
>
> I observe that I reach my User message handler in the primary thread
below:
>
>
////////////////////////////////////////////////////////////////////////////
> ///
> // FUNCTION: OnIcuCommand( WPARAM, LPARAM )
> //
> // PURPOSE: Handles Windows User message to set the ICU value
> //
> // COMMENTS:
> //
> LRESULT CIcuCtl::OnIcuCommand(WPARAM wParam, LPARAM lParam)
> {
> // TODO: Add your control notification handler code here
> int icuId = (int)wParam;
> int slideValue = (int)lParam;
>
> ASSERT(icuId >= 1 && icuId <= 4);
> ASSERT(slideValue >= 0 && slideValue < 3);
> if (icuId < 1 || icuId > 4 || slideValue < 0 || slideValue > 2)
> {
> return 1L; // Indicate error
> }
>
> switch(icuId)
> {
> case 1: m_icuPower1.SetValue(slideValue); break;
> case 2: m_icuPower2.SetValue(slideValue); break;
> case 3: m_icuPower3.SetValue(slideValue); break;
> case 4: m_icuPower4.SetValue(slideValue); break;
> }
>
> return 0L; // Indicate success
> }
>
> The m_icuPower'x' class members are mapped with VC6 classwizard to the
> CNiSlide controls in the dialog. When the handerl reach the CNiSlider
> SetValue call, a dialog is raised:
> Title:
> Message in body: Unable to set the value.
>
> I believe an exception is being thrown in the main thread as well.
>
> Upon return to the calling thread, the value 0 is returned from the
> SendMessageTimeout() call, and a subsequent check of GetLastError() gives
> back a 1460 error code. FormatMessage() on this error code yields the
> system message:
>
> "This operation returned because the timeout period expired".
>
> Please help. I just want to be able to send user messages to the UI
> controls from my secondary thread.
>
> Thanks,
> Mark Greenman
> Space Dynamics Laboratory
>
>
>
>
0 Kudos
Message 2 of 2
(3,280 Views)