ON_CONTROL_RANGE C++ error invalid type conversion - visual-studio

I am programming the windows base application using MFC. when I was trying to use ON_CONTROL_RANGE function there is an error message popped up.
Visual Studio was used to build the app.
error
E0171 invalid type conversion
why is this error comes up,
give me a hint
Code
#define IDC_USR_MANUAL_TUNING_CH1_CHECK 1134
#define IDC_USR_MANUAL_TUNING_CH7_CHECK 1140
ON_CONTROL_RANGE(BN_CLICKED, IDC_USR_MANUAL_TUNING_CH1_CHECK, IDC_USR_MANUAL_TUNING_CH8_CHECK, OnUsrManualTuningChCheck)
void CMainteManualTuningDialog::OnUsrManualTuningChCheck(int nId)
{
if (FALSE == m_bInitFlag) // Initialization flag TRUE: Initialized / FALSE: Uninitialized
{
return;
}
UpdateData(TRUE);
int nChCnt = nId - IDC_USR_MANUAL_TUNING_CH1_CHECK;
if ((CH1 > nChCnt) || (CH8 < nChCnt))
{
return;
}
// unused
if (FALSE == m_bUseCheck[nChCnt])
{
if (nChCnt == m_rbutCh)
{
MessageBox("While selecting a channel, it cannot be invalidated.");
m_bUseCheck[nChCnt] = TRUE; // invalid
}
else
{
m_butUseCheck[nChCnt].SetWindowText(MSG_IGNORE); // Ignore
m_butChSel[nChCnt].EnableWindow(FALSE); // invalid
g_eTuningStat[nChCnt] = E_TUNING_STAT_NONE; // unused
m_strStatCh[nChCnt] = MSG_NONE; // unused
if (FALSE == m_clp->ZeroSetSend(nChCnt, m_pcTuningData))
{
((CMicroDetectorView*)m_hpView)->PostMessage(WM_USR_ALARM, eAPP_T);
}
}
}
// use
else
{
m_butUseCheck[nChCnt].SetWindowText(MSG_USE); // Use
m_butChSel[nChCnt].EnableWindow(TRUE); // Effectiveness
// Unadjusted the adjustment status
SetStatStill(nChCnt);
}
UpdateData(FALSE);
}

when we use the ON_CONTROL_RANGE(wNotifyCode, id, idLast, memberFxn)
memberFxn Fn has to use UINT variables

Related

I want to copy, paste and cut content in my CEdit from my Clipboard

This is the event handlers i implemented to the copy, paste and Cut buttons in my MFCRibbonBar:
in the MyRibbonView.cpp:
void CMyRibbonView::OnEditCopy()
{
CWnd *wnd = GetFocus();
if (wnd == pEdit)
pEdit->Copy();
if (!OpenClipboard())
{
AfxMessageBox(_T("Cannot open the Clipboard"));
return;
}
if (!EmptyClipboard())
{
AfxMessageBox(_T("Cannot empty the Clipboard"));
return;
}
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64);
strcpy_s((char*)hGlob, 64, "Current selection\r\n");
if (::SetClipboardData(CF_TEXT, hGlob) == NULL)
{
CString msg;
msg.Format(_T("Unable to set Clipboard data, error: %d"), GetLastError());
AfxMessageBox(msg);
CloseClipboard();
GlobalFree(hGlob);
return;
}
CloseClipboard();
}
void CMyRibbonView::OnEditPaste()
{
if (OpenClipboard())
{
HANDLE hClipboardData = GetClipboardData(CF_TEXT);
char *pchData = (char*)GlobalLock(hClipboardData);
CString strFromClipboard;
strFromClipboard = pchData;
pEdit->SetWindowText(strFromClipboard);
GlobalUnlock(hClipboardData);
CloseClipboard();
}
}
void CMyRibbonView::OnEditCut()
{
OnEditCopy();
pEdit->SetWindowText(L" ");
}
There is no errors, it's just not working. I tested it by adding the messages to check if it's actually the data or not but they're not popping up.
You need to GlobalLock your hGlob memory before copying your character string into it (this operation converts it into a usable pointer for your process - see here), and then call GlobalUnlock after you've done that (so that the clipboard can access hGlob):
HGLOBAL hGlob = GlobalAlloc(GMEM_FIXED, 64); // Maybe also need GMEM_MOVEABLE here instead?
char* cCopy = (char*)GlobalLock(hGlob);
strcpy_s(cGlob, 64, "Current selection\r\n");
GlobalUnlock(hGlob);
if (::SetClipboardData(CF_TEXT, hGlob) == NULL)
{
//...
And you'll need a similar arrangement for the paste operation.

Correct way of synchronization between a method and a stop functionality

I have a function (lets call it function A) that 0 to many threads can access it (at the same time, no shared resources). At any given time, the user can use to stop the process. The stop functionality needs to make sure that there are threads accessing function A, so that a graceful shutdown can be performed. Is there a native procedure to do so?
What I was going to do is have an InterlockedIncrement an integer everytime function A is called (and a corresponding InterlockedDecrement on said integer when function A exists). When an InterlockedDecrement takes place, it checks the value of the integer, if it's set to zero, a event is set to signalled. If the value is not zero, the event is set to nonsignalled.
This makes sense in my mind, but I'm curious whether there is a more native structure / functionality adapted to do so.
I still have to thing about the fact the "stop" function may get starved (in the sense, the said integer may never be set to zero). A sidenote: when the stop event takes place, the InterlockedIncrement process shall be stopped, to reduce said starvation.
what you need and want implement is called Run-Down Protection. unfortunately it supported only in kernel mode, but not hard implement it yourself in user mode too.
the simplest implementation is next:
HANDLE ghStopEvent;
LONG gLockCount = 1;
BOOLEAN bStop = FALSE;
void unlock()
{
if (!InterlockedDecrement(&gLockCount)) SetEvent(ghStopEvent);
}
BOOL lock()
{
LONG Value = gLockCount, NewValue;
for ( ; !bStop && Value; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&gLockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void funcA();
void UseA()
{
if (lock())
{
funcA();
unlock();
}
}
and when you want begin rundown - once call
bStop = TRUE; unlock();
how you can see lock function is interlocked increment gLockCount on 1 but only if it not 0.
in kernel mode you can call instead
EX_RUNDOWN_REF gRunRef;
void UseA()
{
if (ExAcquireRundownProtection(&gRunRef))
{
funcA();
ExReleaseRundownProtection(&gRunRef)
}
}
and on place final unlock - ExWaitForRundownProtectionRelease
some more complex and scalable implementation of rundown-protection:
#define RUNDOWN_INIT_VALUE 0x80000000
#define RUNDOWN_COMPLETE_VALUE 0
class __declspec(novtable) RUNDOWN_REF
{
LONG _LockCount;
protected:
virtual void RundownCompleted() = 0;
public:
BOOL IsRundownBegin()
{
return 0 <= _LockCount;
}
void Reinit()
{
if (InterlockedCompareExchange(&_LockCount, RUNDOWN_INIT_VALUE, RUNDOWN_COMPLETE_VALUE) != RUNDOWN_COMPLETE_VALUE)
{
__debugbreak();
}
}
RUNDOWN_REF()
{
_LockCount = RUNDOWN_INIT_VALUE;
}
BOOL AcquireRundownProtection()
{
LONG Value = _LockCount, NewValue;
for ( ; Value < 0; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&_LockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void ReleaseRundownProtection()
{
if (RUNDOWN_COMPLETE_VALUE == InterlockedDecrement(&_LockCount))
{
RundownCompleted();
}
}
void BeginRundown()
{
if (AcquireRundownProtection())
{
_interlockedbittestandreset(&_LockCount, 31);
ReleaseRundownProtection();
}
}
};
and use it like:
class MY_RUNDOWN_REF : public RUNDOWN_REF
{
HANDLE _hEvent;
virtual void RundownCompleted()
{
SetEvent(_hEvent);
}
// ...
} gRunRef;
void UseA()
{
if (gRunRef.AcquireRundownProtection())
{
funcA();
gRunRef.ReleaseRundownProtection();
}
}
and when you want stop:
gRunRef.BeginRundown();// can be safe called multiple times
// wait on gRunRef._hEvent here
interesting that in kernel exist else one (more old - from win2000, when rundown protection from xp) api Remove Locks. it do almost the same. different only in internal implementation and usage. with remove locks code will be look like this:
IO_REMOVE_LOCK gLock;
void UseA()
{
if (0 <= IoAcquireRemoveLock(&gLock, 0))
{
funcA();
IoReleaseRemoveLock(&gLock, 0);
}
}
and when we want stop - call
IoAcquireRemoveLock(&gLock, 0);
IoReleaseRemoveLockAndWait(&gLock, 0);
my first code spinet by implementation near remove locks implementation, when second near rundown-protection implementation. but by sense both do the same

alBufferData() sets AL_INVALID_OPERATION when using buffer ID obtained from alSourceUnqueueBuffers()

I am trying to stream audio data from disk using OpenAL's buffer queueing mechanism. I load and enqueue 4 buffers, start the source playing, and check in a regular intervals to refresh the queue. Everything looks like it's going splendidly, up until the first time I try to load data into a recycled buffer I got from alSourceUnqueueBuffers(). In this situation, alBufferData() always sets AL_INVALID_OPERATION, which according to the official v1.1 spec, it doesn't seem like it should be able to do.
I have searched extensively on Google and StackOverflow, and can't seem to find any reason why this would happen. The closest thing I found was someone with a possibly-related issue in an archived forum post, but details are few and responses are null. There was also this SO question with slightly different circumstances, but the only answer's suggestion does not help.
Possibly helpful: I know my context and device are configured correctly, because loading small wav files completely into a single buffer and playing them works fine. Through experimentation, I've also found that queueing 2 buffers, starting the source playing, and immediately loading and enqueueing the other two buffers throws no errors; it's only when I've unqueued a processed buffer that I run into trouble.
The relevant code:
static constexpr int MAX_BUFFER_COUNT = 4;
#define alCall(funcCall) {funcCall; SoundyOutport::CheckError(__FILE__, __LINE__, #funcCall) ? abort() : ((void)0); }
bool SoundyOutport::CheckError(const string &pFile, int pLine, const string &pfunc)
{
ALenum tErrCode = alGetError();
if(tErrCode != 0)
{
auto tMsg = alGetString(tErrCode);
Log::e(ro::TAG) << tMsg << " at " << pFile << "(" << pLine << "):\n"
<< "\tAL call " << pfunc << " failed." << end;
return true;
}
return false;
}
void SoundyOutport::EnqueueBuffer(const float* pData, int pFrames)
{
static int called = 0;
++called;
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
if(tState == AL_STATIC)
{
Stop();
// alCall(alSourcei(mSourceId, AL_BUFFER, NULL));
}
ALuint tBufId = AL_NONE;
int tQueuedBuffers = QueuedUpBuffers();
int tReady = ProcessedBuffers();
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
void* tConverted = convert(pData, pFrames);
// the fifth time through, we get AL_INVALID_OPERATION, and call abort()
alCall(alBufferData(tBufId, mFormat, tConverted, pFrames * mBitdepth/8, mSampleRate));
alCall(alSourceQueueBuffers(mSourceId, 1, &mBufferId));
if(mBitdepth == BITDEPTH_8)
{
delete (uint8_t*)tConverted;
}
else // if(mBitdepth == BITDEPTH_16)
{
delete (uint16_t*)tConverted;
}
}
void SoundyOutport::PlayBufferedStream()
{
if(!StreamingMode() || !QueuedUpBuffers())
{
Log::w(ro::TAG) << "Attempted to play an unbuffered stream" << end;
return;
}
alCall(alSourcei(mSourceId, AL_LOOPING, AL_FALSE)); // never loop streams
alCall(alSourcePlay(mSourceId));
}
int SoundyOutport::QueuedUpBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tCount));
return tCount;
}
int SoundyOutport::ProcessedBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_PROCESSED, &tCount));
return tCount;
}
void SoundyOutport::Stop()
{
if(Playing())
{
alCall(alSourceStop(mSourceId));
}
int tBuffers;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tBuffers));
if(tBuffers)
{
ALuint tDummy[tBuffers];
alCall(alSourceUnqueueBuffers(mSourceId, tBuffers, tDummy));
}
alCall(alSourcei(mSourceId, AL_BUFFER, AL_NONE));
}
bool SoundyOutport::Playing()
{
ALint tPlaying;
alCall(alGetSourcei(mSourceId, AL_SOURCE_STATE, &tPlaying));
return tPlaying == AL_PLAYING;
}
bool SoundyOutport::StreamingMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STREAMING;
}
bool SoundyOutport::StaticMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STATIC;
}
And here's an annotated screen cap of what I see in my debugger when I hit the error:
I've tried a bunch of little tweaks and variations, and the result is always the same. I've wasted too many days trying to fix this. Please help :)
This error occurs when you trying to fill buffer with data, when the buffer is still queued to the source.
Also this code is wrong.
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
You can fill buffer with data only if it unqueued from source. But your first if block gets tBufId that queued to the source. Rewrite code like so
if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}

Haxe - sending enum as flags to a function

I'm just trying to convert my code from C# to Haxe NME. I use enums as flags.
[Flags]
enum State
{
StateOne = 1,
StateTwo = 2,
StateThree = 4
}
And use it
if (someObj.HasState(State.StateOne | State.StateTwo))
{
// Contains both the states. Do something now.
}
I had no idea on how to do this in Haxe NME.
Thanks.
In Haxe 3, there is haxe.EnumFlags. This uses Haxe 3 Abstract Types which basically wrap an underlying type, in this case, it uses an Int, just like you have done - but then it wraps it up in a pretty API so you don't have to worry about the details.
Here is some sample code:
import haxe.EnumFlags;
class EnumFlagTest
{
static function main()
{
var flags = new EnumFlags<State>();
flags.set(StateOne);
flags.set(StateTwo);
flags.set(StateThree);
flags.unset(StateTwo);
if (flags.has(StateOne)) trace ("State One active");
if (flags.has(StateTwo)) trace ("State Two active");
if (flags.has(StateThree)) trace ("State Three active");
if (flags.has(StateOne) && flags.has(StateTwo)) trace ("One and Two both active");
if (flags.has(StateOne) && flags.has(StateThree)) trace ("One and Three both active");
}
}
enum State
{
StateOne;
StateTwo;
StateThree;
}
All of this works is stored as a standard Int, and uses integer operators like you have done, so it should be pretty fast (no wrapping in an external object). If you want to see how it works under the box, the source code for EnumFlags can be viewed here.
If you're still on Haxe 2, then you could create an object that is really similar, but of course, it has to create an object as well as the integer, so if you're doing thousands (millions?) of them then you might get a slow down. The equivalent code, that should work with Haxe 2 (though I haven't checked):
class MyEnumFlags<T:EnumValue>
{
var i:Int;
public function new(?i=0)
{
this.i = i;
}
public inline function has( v : T ) : Bool {
return i & (1 << Type.enumIndex(v)) != 0;
}
public inline function set( v : T ) : Void {
i |= 1 << Type.enumIndex(v);
}
public inline function unset( v : T ) : Void {
i &= 0xFFFFFFF - (1 << Type.enumIndex(v));
}
public inline static function ofInt<T:EnumValue>( i : Int ) : MyEnumFlags<T> {
return new MyEnumFlags<T>(i);
}
public inline function toInt() : Int {
return i;
}
}
I've managed to find it. I had trouble using enums but I had been successful using constants. This is the simple test file I used.
package ;
class FlagsTest
{
static inline var FLG_1:Int = 1;
static inline var FLG_2:Int = 2;
public static function main() : Void
{
var flag:Int = FLG_1;
if (hasFlag(flag, FLG_1))
{
trace ("Test 1 passed");
}
flag |= FLG_2;
if (hasFlag(flag, FLG_2))
{
trace ("Test 2 passed");
}
}
public static function hasFlag( flags:Int, flag:Int ) : Bool
{
return ((flags & flag) == flag) ? true : false;
}
}
Output:
FlagsTest.hx line 14: Test 1 passed
FlagsTest.hx line 19: Test 2 passed

Inputs in SDL (on key pressed)

I would like to know how can I detect the press of a key or release of a key in a while loop in SDL. Now, I know you can get the events with SDL like OnKeyPressed, OnKeyReleased, OnKeyHit, etc, but I want to know how to build functions like 'KeyPressed' that returns a boolean, instead of being an event. Example:
while not KeyHit( KEY_ESC )
{
//Code here
}
I know you have already selected an answer.. but here is some actual code of how I typically do it with one array. :)
first define this somewhere.
bool KEYS[322]; // 322 is the number of SDLK_DOWN events
for(int i = 0; i < 322; i++) { // init them all to false
KEYS[i] = false;
}
SDL_EnableKeyRepeat(0,0); // you can configure this how you want, but it makes it nice for when you want to register a key continuously being held down
Then later, create a keyboard() function which will register keyboard input
void keyboard() {
// message processing loop
SDL_Event event;
while (SDL_PollEvent(&event)) {
// check for messages
switch (event.type) {
// exit if the window is closed
case SDL_QUIT:
game_state = 0; // set game state to done,(do what you want here)
break;
// check for keypresses
case SDL_KEYDOWN:
KEYS[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
KEYS[event.key.keysym.sym] = false;
break;
default:
break;
}
} // end of message processing
}
Then when you actually want to use the keyboard input i.e. a handleInput() function, it may look something like this:
void handleInput() {
if(KEYS[SDLK_LEFT]) { // move left
if(player->x - player->speed >= 0) {
player->x -= player->speed;
}
}
if(KEYS[SDLK_RIGHT]) { // move right
if(player->x + player->speed <= screen->w) {
player->x += player->speed;
}
}
if(KEYS[SDLK_UP]) { // move up
if(player->y - player->speed >= 0) {
player->y -= player->speed;
}
}
if(KEYS[SDLK_DOWN]) { // move down
if(player->y + player->speed <= screen->h) {
player->y += player->speed;
}
}
if(KEYS[SDLK_s]) { // shoot
if(SDL_GetTicks() - player->lastShot > player->shotDelay) {
shootbeam(player->beam);
}
}
if(KEYS[SDLK_q]) {
if(player->beam == PLAYER_BEAM_CHARGE) {
player->beam = PLAYER_BEAM_NORMAL;
} else {
player->beam = PLAYER_BEAM_CHARGE;
}
}
if(KEYS[SDLK_r]) {
reset();
}
if(KEYS[SDLK_ESCAPE]) {
gamestate = 0;
}
}
And of course you can easily do what you're wanting to do
while(KEYS[SDLK_s]) {
// do something
keyboard(); // don't forget to redetect which keys are being pressed!
}
**Updated version on my website: **
For the sake of not posting a lot of source code, you can view a complete SDL Keyboard class in C++ that supports
Single Key Input
Simultaneous Key Combos (Keys all pressed in any order)
Sequential Key Combonations (Keys all pressed in specific order)
http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html (if you have any problems, let me know)
There is an SDL function for this: SDL_GetKeyboardState
Example to check whether left or right CTRL key is pressed:
const Uint8* state = SDL_GetKeyboardState(nullptr);
if (state[SDL_SCANCODE_LCTRL] || state[SDL_SCANCODE_RCTRL]) {
std::cerr << "ctrl pressed" << std::endl;
}
I had this problem in LuaJIT with FFI, this is how I solved it:
Global:
KEYS = {}
Event code:
ev = ffi.new("SDL_Event[1]")
function event()
while sdl.SDL_PollEvent(ev) ~= 0 do
local e = ev[0]
local etype = e.type
if etype == sdl.SDL_QUIT then
return false -- quit
-- os.exit() -- prevents interactive mode
elseif etype == sdl.SDL_KEYDOWN then
if e.key.keysym.sym == sdl.SDLK_ESCAPE then
return false -- quit
-- os.exit()
end
print("Pressed: ", e.key.keysym.scancode, "\n")
KEYS[tonumber(e.key.keysym.sym)] = true
-- print("Pressed: ", (e.key.keysym.sym == sdl.SDLK_w), "\n");
elseif etype == sdl.SDL_KEYUP then
KEYS[tonumber(e.key.keysym.sym)] = false
elseif etype == sdl.SDL_VIDEORESIZE then
-- print("video resize W:".. e.resize.w .. " H:" .. e.resize.h)
width = e.resize.w
height = e.resize.h
onResize()
end
end
return true -- everything ok
end
Update function:
if KEYS[sdl.SDLK_w] == true then
rot = rot + 1
end
Most time i wasted on this:
KEYS[tonumber(e.key.keysym.sym)] = false
Because FFI is returning a CData object, which was used as the array-key, but it needs the integer.
You should have 2 tables of booleans for keys. One table, in which you set keys true or false based on the SDL keydown/keyup events, and another one, that you initialize with false. When checking keyPressed, you just compare the second table key with the first table key, and if different, if second table key is false, then it was pressed, else it was released. After that, you do secondTable[key] := not secondTable[key]. Works!

Resources