MFC: Dialog PreTranslateMessage() WM_KEYDOWN not seeing VK_DELETE? - winapi

I have a weird one where I get all the other virtual keys but VK_DELETE is not received? This is an MFC App and based on a CDialogEx. I check for it in the PreTranslateMessage()
if (pMsg->wParam==VK_SPACE) {
// do my stuff - WORKS!
}
else if (pMsg->wParam==VK_INSERT) {
// do my stuff - WORKS!
draw=true;
}
else if (pMsg->wParam==VK_DELETE) {
// do my stuff - NEVER RECEIVED!!
}
else ... etc ...
I copy/pasted above from code to ensure not something in the if statements I'm blind to see.
Any Ideas?
TIA!!

Okay, so finding VK_DELETE was an accelerator and VK_F6 was as well, using VK_F6 worked, but then looking closer at the accelerator VK_F6 had CONTROL, removing that so acts like VK_DELETE has the same issue so these type of problems has to do with accelerators.
The workaround I used was to add a disable option so that the TranslateAccelerator() call would not be done from the PretranslateMessage() of the other main window. This allowed the key pressed to be sent through to the dialog.

Related

CDockablePane and Accelerators

In my MFC MDI application, I have CDockablePanes.
In CDockablePane's I have edit control and listcontrol.
For example, if the user is typing text in an edit control in the app, and presses the delete key, instead of deleting a character like normal, it sends the ID_EDIT_DELETE command to active view, causing the selected objects to be deleted.
How can I fix this?
I think I need to override PreTranslateMessage, and check what window has focus before passing it on, but I really don't know what to do in PreTranslateMessage.
I overrided the PreTranslatemessage function in CDockablePane derived class and added below code and it is working for me.
BOOL CMyDockablePane::PreTranslateMessage(MSG* pMsg)
{
if(IsDialogMessage(pMsg))
return true;
return CDockablePane::PreTranslateMessage(pMsg);
}

Hiding a control in Windows

I can't figure out how to hide a child window (a control), more specifically a GroupBox and a PushButton. I thought ShowWindow() with SW_HIDE as the second parameter would do the job, but it simply doesn't work. Yet SW_SHOW works just fine. I have the correct window handle for both controls, so that's not the issue.
I googled and all I could find was people asking how to hide dialogs, not controls. Either that or MFC-based applications, which doesn't apply here.
I'm using pure Windows API, no MFC.
What am I getting wrong?
EDIT: More info: I'm writing some simple class wrappers for WinApi controls. The WindowsControl class has, along other methods, the following methods for showing and hiding the Control:
void Show() {
ShowWindow(this->_hWnd,SW_SHOWNOACTIVATE);
}
void Hide() {
ShowWindow(this->_hWnd,SW_HIDE);
}
Every control inherits from WindowsControl.
This image has the window layout so you understand exactly what I'm doing: http://i.stack.imgur.com/PHQnH.png
When the user clicks inside the "Chipset" Static control, it'll load information for a given Tile (which is stored in an array, but that's irrelevant). Depending on the setting, it'll hide the "Edit bitwall" button on the left and show the empty GroupBox behind it or viceversa.
Just to be clear this isn't something wrong with my windows api wrappers, I am getting the correct HWND. Though ShowWindow might not be able to be called from a Window Procedure that isn't the parent's (that'd be weird).
EDIT2: Using C++ with Visual Studio 2008, no MFC, no WTL, no CLR, no .NET
EDIT3: I'll post even more code so it's easier
Inside the static's window procedure, I handle WN_LBUTTONDOWN like this:
case WM_LBUTTONDOWN: {
...
update_tiledata(c, l)
void update_tiledata(GroupBox * c, ListView* l ) {
...
if (chp_copy.Tiles[selectedTile].Pass() == PT_BITWALL) {
c->Controls(CTL_BTNEDITBIT)->Show();
c->Controls(CTL_FRPHOLD)->Hide();
} else {
c->Controls(CTL_FRPHOLD)->Show();
c->Controls(CTL_BTNEDITBIT)->Hide();
}
update_edits();
}
The ommited code does nothing to affect the classes, as I said before, ShowWindow with SW_HIDE IS getting called, with the correct HWND, but nothing is happening.
A control in a Window or dialog can be hidden using
ShowWindow(hControlWin, SW_HIDE);
In a dialog you can retrive the controls window handle by calling
GetDlgItem(hDlg, < CtrlID >);
Typically you write something like:
ShowWindow(GetDlgItem(hDlg, 2), SW_HIDE);
It would be helpful if you give more information and some code: How did you create the controls? What language, compile and framework did you use?
I think the function call you want is EnableWindow I have used this before to disable a button on a form. You will need to get an handle to the Window (object) first though so you might want to use EnumChildWindows to iterate through all the controls to find the one you want.

Minimize/restore windows programmatically skipping the animation effect

I need to perform several operations on a list of windows (minimize some of them, restore others) in order to switch between two or more set of windows at once.
The problem with this are those animations you can see when minimizing and restoring a window. The whole process look terrible with all those animations going in and out, up and down.
I cannot, however, disable those animations because this is for other computers and i dont want to change other people's settings, plus those animations are actually useful when you minimize/restore one window only (i.e. when YOU do it manually) because you can see what is happening, but for doing it programmatically on several windows at a time, it's not nice.
I'm currenlty using the SendMessage function to send the WM_SYSCOMMAND message with params SC_MINIMIZE/SC_RESTORE. I dont know whether there is another way.
So, the question:
How can I minimize/restore a window programatically without the animation effect??
PS: The programming language is not important. I can use any language that's nessesary for accomplishing this.
SetWindowPlacement with SW_SHOWMINIMIZED or SW_RESTORE as appropriate for showCmd in WINDOWPLACEMENT seems to bypass window animation. I'd keep an eye on the functionality for future versions of the OS though since documentation does not mention anything about animation.
How about Hide > Minimize > Show ?
You could temporarily disable the animations and then restore the user's original setting.
class WindowsAnimationSuppressor {
public:
WindowsAnimationSuppressor() : m_suppressed(false) {
m_original_settings.cbSize = sizeof(m_original_settings);
if (::SystemParametersInfo(SPI_GETANIMATION,
sizeof(m_original_settings),
&m_original_settings, 0)) {
ANIMATIONINFO no_animation = { sizeof(no_animation), 0 };
::SystemParametersInfo(SPI_SETANIMATION,
sizeof(no_animation), &no_animation,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
m_suppressed = true;
}
}
~WindowsAnimationSuppressor() {
if (m_suppressed) {
::SystemParametersInfo(SPI_SETANIMATION,
sizeof(m_original_settings),
&m_original_settings,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
}
private:
bool m_suppressed;
ANIMATIONINFO m_original_settings;
};
void RearrangeWindows() {
WindowsAnimationSuppressor suppressor;
// Rearrange the windows here ...
}
When the suppressor is constructed, it remembers the user's original setting and turns off the animation. The destructor restores the original settings. By using a c'tor/d'tor, you ensure that the user's settings are restored if your rearranging code throws an exception.
There is a small window of vulnerability here. In theory, the user could change the setting during the operation, and then you'll slam the original setting back. That's extremely rare and not really that bad.

Repeating key events blocking

I wrote a simple program with SFML and OpenGL which draws a spinning square that can be moved around the screen with the arrow keys.
It works fine on all the Linux and Mac computers I've tested it on, but when I try to move the square on Windows (by holding down an arrow key) it moves a small distance and then stops moving and spinning. I'm pretty sure the program is getting stuck in the GetEvent method - my guess is that when I've held the key down long enough for it to start repeating, the event stack keeps getting new events added to it before I can pop everything off it (and if I turn the key repeat rate on Windows right down to the minimum then the problem goes away - I don't really like this as a solution though).
I found that pressing and holding Alt, Ctrl, Delete, Page up, Page down, Home, End etc all cause this behavior too (even though I don't specifically detect any of these keys in the program), but all the letter keys, as well as space, enter, backspace and the keypad arrow keys work fine (i.e. they don't cause the program to pause if I hold them down for too long).
I don't have the exact code (I just turned my laptop off), but it looks like:
while(running) {
while(app.GetEvent(event))
if(event.Type==sf::Event::Closed) running=false;
if(input.IsKeyDown(sf::Key::Right)); // move right
// etc etc
// update rotation
// draw everything
}
Any ideas as to what the exact problem might be, and how I could fix it?
I know this is an old question but I would like to answer it in the interest of helping others who may find themselves here experiencing similiar problems.
SFML 1.6 has two ways you can get input from the user. One is event-based where you process each event sent to you via sf::Window::GetEvent(). The other is query-based where you check the sf::Input class of your window directly.
You have used the query-based method here but put it inside an event loop which isn't really the way it was intended to be used. It was meant to be used like this. This is a nice feature because SFML essentially keeps a boolean table of keys automatically for you so you don't need to manage key states yourself. IMHO for using repeating input this is more elegant since you won't be spamming your event queue, just checking a boolean value.
while(app.GetEvent(event))
if(event.Type == sf::Event::Closed) running=false;
if(event.Type == sf::Event::KeyPressed && event.Key.Code == sf::Key::Right)
{
// move right
}
}
If you wanted to just query sf::Input directly then you use the same code as above, but you put it outside the event loop.
while(app.GetEvent(event)
{
}
if (myWindow.GetInput().IsKeyDown(sf::Key::Right))
{
}
By default automatic key repeat should be enabled for sf::Windows but you can make sure by using sf::Window::EnableKeyRepeat(true). This means it will send a KeyPressed event repeatedly while a key is held down.
Try using the query-based method outside the main event loop and see if that works for you.

EN_PROTECTED and RichEdit

The EN_PROTECTED notify message is sent to the parent of a rich edit control when there is an attempt to change "protected" text. This works for me and I've tried it with both richedit20 and richedit50. Any change to this protected text immediately triggers the EN_PROTECTED message. (Its a little complicated to set it up, but I've done that correctly.)
However, the documentation says if the parent returns non zero in response to the EN_PROTECTED message, it will prevent the protected text from being changed. This is not working for me.
I created a simple test dialog test app, using MFC - add the richedit control via the dialog edit, added a call to AfxInitRichEdit in the app initialization, added some code to the dialog to put text in the control (SetWindowText), selected the second word, applied the CFE_PROTECTED effects and then added a handler for EN_PROTECTED, in the handler i just set *pResult = TRUE.
When i ran the app it all worked fine; in that i was not able to modify the protected word but i could modify the rest of the text.
Unfortunately that really doesn't lead us to a conclusive reason as to why your code doesn't work - from what i can see it appears correct. Could be the version of the RichEdit20 dll i suppose - mine is 5.31.23.1224
(To Ruddy: code sample below if it reveals anything)
I eventually just did a PostMessage(hwnd,EM_UNDO...) from within the EN_PROTECTED handler and that is what I had to do to get this working for me. Returning TRUE never accomplished anything, though I know the handler was being hit and only for protected text. (the ODS function below is OutputDebugString).
But I've seen multiple examples on the web (most of them MFC however or sometimes DELPHI or something), where just returning TRUE in the EN_PROTECTED handler is said to prevent the change.
Actually, my Rich Edit Control was within a dialog but was being created with CreateWindowEx,so I tried intializing it through the RC file instead but it made no difference. (Some of the stuff I'm doing is kind of old school admittedly - sorry about that.) But actually I tried anything and everything to make EN_PROTECTED work like its documented and nothing worked - bizarre.
Oh well, EM_UNDO from within the EN_PROTECTED handler works, so guess I'll stick with that.
Original code (with the added EM_UNDO call):
case WM_NOTIFY: {
NM_UPDOWN* nm = (NM_UPDOWN*)lParam;
if ((nm->hdr.code == UDN_DELTAPOS) && (nm->hdr.idFrom == ID_UPD_ERR)) {
int e = nm->iPos + nm->iDelta;
SetWindowText(xml2->hStatMsg[1],xml2->ErrMsg(1,e));
SetWindowText(xml2->hStatMsg[2],xml2->ErrMsg(2,e));
}
else if (wParam == ID_EDIT_A) {
if (((LPNMHDR)lParam)->code == EN_PROTECTED) {
ODS("EN_PROTECTED", (int)((ENPROTECTED*)lParam)->msg);
PostMessage(xml2->hImgXml2,EM_UNDO,0,0);
return TRUE;
}
if (((LPNMHDR)lParam)->code == EN_SELCHANGE) {
anchors_adjsel(xml2->hImgXml2);
}
}
}
break;

Resources