C# override WndProc in Control level to detect - user-controls

I have overridden WndProc in UserControl level to detect MouseDown, MouseUp, and MouseMove to any Control added in that UserControl.
protected override void WndProc(ref Message m)
{
Point mouseLoc = new Point();
switch (m.Msg)
{
case WM_LBUTTONDOWN:
System.Diagnostics.Debug.WriteLine("mouse down");
//this.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, mouseLoc.X, mouseLoc.Y, 0));
break;
case WM_LBUTTONUP:
System.Diagnostics.Debug.WriteLine("mouse up");
//this.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, mouseLoc.X,mouseLoc.Y, 0));
break;
case WM_MOUSEMOVE:
int lParam = m.LParam.ToInt32();
//mouseLoc.X = lParam & 0xFFFF;
//mouseLoc.Y = (int)(lParam & 0xFFFF0000 >> 16);
mouseLoc.X = (Int16)m.LParam;
mouseLoc.Y = (Int16)((int)m.LParam >> 16);
System.Diagnostics.Debug.WriteLine("mouse move: " + mouseLoc.X + ", " + mouseLoc.Y);
//this.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, mouseLoc.X,mouseLoc.Y, 0));
break;
}
base.WndProc(ref m);
}
MouseMove, Down, and Up are working when the mouse pointer is in UserControl but when the mouse pointer is on other control (inside my UserControl) it doesn't work.
Am I doing something wrong?
Currently developing a flick and scroll control.

This is how windows works - each control in winforms is a window, and mouse messages go to the window they are over. If you need to get the mouse input from other windows you need to cooperate them somehow.
Having said all of that, if all you want is a flick and scroll control, you should consider looking at the WM_GESTURE APIs - that is what they are for, and they will allow you to implement flick and scroll without any cooperation from your child windows.

You're not doing anything "wrong", but Windows is simply sending the message to the correct control. It does not send the message to all the enclosing controls as well.
For key events there is the the Form.KeyPreview property, which allows the form to receive the events as well, but I'm not aware of anything similar for mouse events.

Related

How to delete an object in SFML

I try to delete a square when I input the number as "1" into the program. How can I delete it?
sf::RectangleShape rec1(sf::Vector2f(50, 100));
rec1.setPosition(200, 700 );
rec1.setFillColor(sf::Color(100, 250, 50));
window.draw(rec1);
int num;
cout << "Please enter a number: ";
cin >> num;
SFML itself won't track what's drawn on screen – you'll have to do that yourself – and you're supposed to redraw the window contents when needed.
A basic "main loop" for a SFML based program would typically look like this:
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
// Handle events here
}
// Update your program logic here
window.clear();
// Draw your stuff here
window.display();
}
Depending on what you draw, you determine what's visible on screen. So if you want your rectangle to no longer appear, simply no longer call window.draw(rectangle);. How you achieve this – e.g. by removing the rectangle from a std::vector<sf::Drawable*> that's iterated over while drawing – is up to you.
You can't delete it when you created it like that. you can color it as transparent using sf::Color::Transparent and it will become unseenable.
If you want to delete it. you have to make it a pointer first. or wrap it out of a class that handles it.
auto rect = make_unique<sf::Rectangle>(sf::Vector2f(50, 100));
and then use std::unique_ptr::reset() to delete it.
rect.reset();

MFC How to create a context menu with scrolling capability

I need to create a context menu with scrolling capability because I need to insert a lot of file names on it, just like Visual Studio 2010's open files context menu.
Anybody has any idea on how to implement this with MFC?
Windows menu supports scrolling if you have more items than fit into the visible part. You can verify it by inserting a couple hundred items into your menu.
I guess the question should be: how to limit the vertical size of the menu (as it would otherwise extend to the height of your screen). Here is an example:
CMenu menu;
menu.CreatePopupMenu();
CString s;
for (int i = 1; i < 100; ++i)
{
s.Format(L"Item %.3d", i);
menu.AppendMenu(MF_STRING, i, s);
}
MENUINFO mi = { sizeof(MENUINFO) };
mi.fMask = MIM_MAXHEIGHT;
mi.cyMax = 400;
menu.SetMenuInfo(&mi);
menu.TrackPopupMenu(TPM_RETURNCMD, 100, 100, this);

simple counter in windows forms application C++

Just practicing my vs 2010 C++ in Windows Form Applications, I haven't done this for a very long time. I am trying to develop a simple applications where a user presses a button and then label1 begins to count everytime users presses that button1. Not sure why label1 is not incrementing by 1. Can someone tell what the problem is? Thanks in advance?
EDITED
I have found the solution and I have amended the code. I will try to close the thread and if I can't, because of I have low points, I will then try tomorrow.
namespace Counter
{
int counter = 0;
//some additional namespaces
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
counter++;
label1->Text = counter.ToString();
}
The reason why this isn't working is twofold.
The way you've written this, you only set the label text once, after you finish your "loop" (*). So the text will only change once.
Even if you move the assignment inside the loop, you're keeping the main thread busy throughout the whole function. What you want is to spawn a second thread and invoke a delegate to change the label text, something like this (C# version):
void StartCounting()
{
var thread=new Thread(()=>
{
for(int i=0;i<10;++i)
label1.Invoke((MethodInvoker)()=>{label1.Text=i.ToString();});
}
}
(*) As a side note, your entire for loop is equivalent to absolutely nothing. j will never be less than i when i starts as 0.

Object disposed exception to be thrown

I have recently integrated in a HUD method into my XNA game project and when the method is called by the main Draw method it throws out a object disposed exception this has something to do with the two Drawstring used in the program.
The exception is thrown at spriteBatch.End() and says Cannot access a disposed object.
Object name: 'Texture2D'.
//initiation of the spritebatch
private SpriteBatch spriteBatch;
//game draw method
public override void Draw(GameTime gameTime)
{
ScreenManager.GraphicsDevice.Clear(Color.CornflowerBlue);
// Our player and enemy are both actually just text strings.
spriteBatch = ScreenManager.SpriteBatch;
tileMap.Draw(spriteBatch, camera);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
null, null, null, null,
camera.TransformMatrix);
DrawHud();
level.Draw(gameTime, spriteBatch);
spriteBatch.End();
// If the game is transitioning on or off, fade it out to black.
if (TransitionPosition > 0 || pauseAlpha > 0)
{
float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);
ScreenManager.FadeBackBufferToBlack(alpha);
}
base.Draw(gameTime);
}
the HUD method
private void DrawHud()
{
Rectangle titleSafeArea = ScreenManager.GraphicsDevice.Viewport.TitleSafeArea;
Vector2 hudLocation = new Vector2(titleSafeArea.X + camera.Position.X, titleSafeArea.Y + camera.Position.Y);
Vector2 center = new Vector2(titleSafeArea.Width + camera.Position.X / 2.0f,
titleSafeArea.Height + camera.Position.Y / 2.0f);
// Draw time remaining. Uses modulo division to cause blinking when the
// player is running out of time.
string timeString = "TIME: " + level.TimeRemaining.Minutes.ToString("00") + ":" + level.TimeRemaining.Seconds.ToString("00");
Color timeColor;
if (level.TimeRemaining > WarningTime ||
level.ReachedExit ||
(int)level.TimeRemaining.TotalSeconds % 2 == 0)
{
timeColor = Color.Yellow;
}
else
{
timeColor = Color.Red;
}
DrawShadowedString(hudFont, timeString, hudLocation, timeColor);
// Draw score
float timeHeight = hudFont.MeasureString(timeString).Y;
DrawShadowedString(hudFont, "SCORE: " + level.Score.ToString(), hudLocation + new Vector2(0.0f, timeHeight * 1.2f), Color.Yellow);
}
//method which draws the score and the time (and is causing the problem)
private void DrawShadowedString(SpriteFont font, string value, Vector2 position, Color color)
{
spriteBatch.DrawString(font, value, position + new Vector2(1.0f, 1.0f), Color.Black);
spriteBatch.DrawString(font, value, position, color);
}
As the exception says, the problem exists because one of the Texture2Ds you are using is being disposed before you are using it.
There are two things in the XNA API (that come to mind) that will dispose of a Texture2D: The ContentManager.Unload() method for any textures loaded by that content manager, and the Texture2D.Dispose() method. So check if your own code is calling one of these two functions at any point.
The exception will only be thrown when the Texture2D instance is "used". Because SpriteBatch batches together texture draws, the texture doesn't actually get used until you end the SpriteBatch (at which point it draws everything in one go). If you change to SpriteSortMode.Immediate SpriteBatch will stop batching sprites and will instead draw them "immediately" you ask it to. This will cause the texture to be used and the exception to be thrown at a Draw call instead of an End call, which should make it easier to identify which texture is being disposed of while still in use.
The code you have posted seems to be fine, I suspect the problem exists elsewhere in your code. The above information should help you identify where the problem is.
My guess is that something is happening in level.Draw that is disposing of a texture somewhere. It doesn't look like the drawhud method in particular is responsible
You mention though that you are sure it's caused by the drawstring methods ... if you comment those two out in particular does the error go away?

MFC's GetClientRect and MoveWindow don't preserve size?

I'm using MFC for Visual Studio 2003. I have an Edit Control with ID IDC_COMMENT_EDIT.
In the following code, after my first call to GetClientRect, I don't expect the value of rc to change.
CWnd* pWnd = GetDlgItem(IDC_COMMENT_EDIT);
if (pWnd != NULL)
{
RECT rc;
pWnd->GetClientRect(&rc);
pWnd->MoveWindow(&rc, TRUE);
pWnd->GetClientRect(&rc);
}
rc.top and rc.left are 0 all the way through, as expected.
However:
After the first call to GetClientRect, I get rc.bottom == 52, and rc.right == 575.
After the second call to GetClientRect, I get rc.bottom == 48, and rc.right == 571.
Does anyone have any idea what is going on?
Your call to MoveWindow is resizing. You need to use GetWindowRect instead of GetClientRect.
The client rect only includes the client area which is the non windows elements (such as border) of the window.
The client rect doesn't include the window borders, but MoveRect expects a rectangle that includes the borders. Use GetWindowRect instead.

Resources