When exactly is WM_PAINT called? Im trying to create a dialog based slot machine application, but i've run into a couple of logical issues. My application will consist of:
"Spin" Button
Exit Button
Three BMP images to display the results of the spin(coin/heart/soldier)
How will i show the final result of the spin using the BMP images? Am i correct in using WM_PAINT to attempt to display the images, how will i refresh the screen each time the user presses the spin button to show the new images? I really appreciate the help!
Dialog boxes normally use DefDlgProc as the window procedure. You can't handle WM_PAINT in your DialogProc (it isn't a window procedure). You can use your own window procedure with a dialog but that's probably more trouble than it's worth.
The simplest way to display a bitmap on a dialog is to use a static control with the SS_BITMAP style.
You can change the displayed bitmap by sending the STM_SETIMAGE message to the static control. The control will take care of repainting itself with the new bitmap.
This is OK if you just want to display the result of a spin, but won't work very well if you want to animate the spinning of the reels. To handle this you could create your own static control (i.e. a window for each reel) that would display a portion of a reel bitmap.
Related
we have one desktop(1st screen) to display the image and another touchscreen(2nd screen) for the control, we wrote a virtual keyboard(html&javascript) on touchscreen, ideally when we touch the keys on the touchscreen, we could input text in editbox(in an input dialog window) in the 1st desktop. Now the problem is the mouse is lost(originally it is in a input dialog in 1st desktop) when we touch the touchscreen, so we have to create a global window in C++ program, and manually copy each possible input dialog window to this global window when it is in use, also we need to set focus for each possible editbox in this input dialog window. please see this:
for each possible input dialog, we add
extern HWND activeInputWindow;
activeInputWindow=m_Edit_Name.m_hWnd;
also for each possible input box in this window we have to add
activeInputWindow=GetDlgItem(IDC_EDIT_TEST)->m_hWnd;
then the program always do this to get back the original window after clicking the touchscreen(2nd window)
extern HWND activeInputWindow;
if(IsWindow(activeInputWindow))
::SetFocus(activeInputWindow);
suppose we have 10 input window and 10 input boxes in each window,then I need to code 100 places! There must have some simple ways, windows osk.exe (virtual keyboard) have no problem for this but we have to use our own virtual keyboard.... I tried GetTopWindow() and GetForegroundWindow() but not working.. Many thanks for the help
This is trying to solve the problem using the wrong tools. What you really want is a window that receives input, but rejects activation. To achieve this, handle the WM_MOUSEACTIVATE message by returning MA_NOACTIVATE. This also works for touch input.
See How can I have a window that rejects activation but still receives pointer input? for all the ins and outs.
The problem is that your virtual keyboard is stealing the focus of the edit control. You'll need to prevent this.
Try to set the flag WS_EX_NOACTIVATE for a window's style or other approaches from this or this answers.
In windows: I would like to know if it is possible (and if so, how) to make a program in C++ that displays images/text on the screen directly, meaning no window; if you are still confused about what I am after some examples are: Rocketdock and Rainmeter.
you can do it certainly without using Qt or any other framework. Just Win32 API helps you do that and internally, every framework calls these API so there is no magic in any of these frameworks
First of all, understand that no image or text can be displayed without a window. Every program uses some kind of window to display text or image. You can verify it using the Spy++ that comes with windows SDK. click the cross-hair sign, click the image or text you think is displayed without any windows. The Spy++ will show you the window it is contained in.
Now how to display such image or text that seems like not contained in any window. Well you have to perform certain steps.
Create a window with no caption bar, resize border, control box, minimize, maximize or close buttons. Use the CreateWindowEx() and see the various windows style WS_EX_XXX, WS_XXX for the desired window style.
Once the window is there you need to cut the window. Much like a cookie cutter. for this you need to define an area. This area is called region and you can define it using many functions like CreateEllipticRgn(), CreatePolygonRgn(), CreateRectRgn(), CreateRoundRectRgn() etc. all these functions return a HRGN which is the handle to the region. Elliptical or rectangle regions are OK as starter.
Now the last part. You have to cut the window like that particular region. Use the SetWindowRgn() function which requires a handle to your window and a handle to that region (HRGN). This function will cut the window into your desired shape.
Now for the image or text. Draw the image or text inside the window. I assume you must have cut the window according to your image, You just need to give window a face. so just draw the image either on WM_ERRASE BACKGROUND or WM_PAINT messages
Use the SetWindowPos() to move the window to the location you wish to on screen. If you have used correct parameters in CreateWindowEx() then this step is not necessary
You can set any further styles of windows using SetWindowLong() function.
Congratulations, you have your image displayed without using any windows ;)
First of all this is not MFC.
Here is a cropped version of the GUI I have been working on:
As you can see there is a bitmap image above the tab control (which uses the default window's handle), I will refer to it as "Blue Bitmap" I have no problems with it, it is functioning perfectly.
The problem I am having is setting another bitmap (from a bitmap file on disk) to the background of the child window (more specifically the tab control child window), replacing the grey colour. Here are some things I did to try and set the bitmap as the background for the child window (the tab).
1) I used the same method as was used to assign the blue bitmap to the window by first importing the bitmap using LoadImage like so:
index->hbmBitmapBanner = (HBITMAP)LoadImage(index->hInstance,L"Images\\horizontal.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
Then in the WM_PAINT message:
case WM_PAINT:
{
PAINTSTRUCT ps1;
if (BeginPaint(WINDOWHANDLE,&ps1))
{
HDC hdcBanner = CreateCompatibleDC(ps1.hdc);
HBITMAP hbmOldHorizontal = (HBITMAP)SelectObject(hdcBanner,index->hbmBitmapBanner); // banner
BitBlt(ps1.hdc,0,0,516,101,hdcBanner,5,0,SRCCOPY);
SelectObject(hdcBanner,hbmOldHorizontal);
DeleteDC(hdcBanner);
EndPaint(WINDOWHANDLE,&ps1);
}
break;
}
That code was successful in setting blue bitmap to the window, but not in setting the other bitmap into the window, (with the blue bitmap's variables substituted into, size and orientation changed as well of course). It simply did not display the bitmap on the screen, and the window remained unchanged, yet no functions failed. ALSO, when I swapped the file locations around, it loaded the bitmap into where the blue bitmap was, so there is definitely no failure in the loading function.
2) Using the above code, I tried changing the first argument of BeginPaint to the window handle of the tab control box, this proved yet again of no use, and the window remained unchanged. I also tried changing the first argument of BeginPaint to a child window which is displayed on the information tab, this caused the child window (which is a groupbox) to disappear, yet still no bitmap appeared on the window.
3) As a last resort I stupidly attempted to use this function on the child window
SetClassLongPtr(tab->hTabIndex[0],GCLP_HBRBACKGROUND,(DWORD)GetStockObject(BLACK_BRUSH));
And of course, it didn't work
If it is of any use, here is how I created the tabbing in my window:
TCITEM tie = {0};
tab->hTab = CreateWindowEx(0,WC_TABCONTROL,L"",WS_CHILD | WS_VISIBLE,0,101,600,400,
WINDOWHANDLE,NULL,(HINSTANCE)GetWindowLong(WINDOWHANDLE,GWLP_HINSTANCE),NULL
);
Is the main tab control, followed by inserting individual the tabs (i.e the information tab)
TCHAR pszTab1 [] = L"Information"; // tab1's text
tie.pszText = pszTab1; // the tab's text/caption
TabCtrl_InsertItem(tab->hTab, 0, &tie); // insert the tab
Additional info: The tab control, and the windows are working/interacting perfectly apart from this. I was testing/attempting this for only one tab, because I knew if it worked on one tab, then it would work on all the tabs, hence saving time.
I have Programming For Windows Fifth Edition, by Charles Petzold beside me as reference, and there is a rather large section on bitmaps, but he doesn't go into talking about loading a bitmap to a child window, the closest he gets is using a bitmap in a menu, which is completely different than a window.
I think that the issue here is that Windows Common Controls do not interact with your application via your main thread's window procedure but via their own (system-defined) window procedures.
So, for example, when your tab window redraws itself, it does not do so in response to a WM_PAINT message arriving at the window procedure defined in your code. You should be able to verify for yourself that this is so by examining the window handles of messages passed to your window procedure, eg WM_PAINT.
If you wish to 'tap into' the default behaviour of a common control you have to 'subclass' it (see here) but in my experience attempting to change the re-draw behaviour is generally problematic.
In the case of a tab control the best thing to do is create an array of child windows sized to the client area of the tab control and arrange that the one displayed at any one time corresponds to the tab that is selected.
If you're using C++ you might consider creating a base class to wrap these windows in which the background (bitmap) drawing is handled. You can then derive a series of wrappers to handle each individual tab. I've used exactly this approach in the past and it works well.
It may be helpful to bear in mind that the tabs of the tab control do not extend over the whole of the control's client area but are just literally the tabs themselves. I don't remember the details but I think they are handled internally by the control and that manipulating them in any way is rather trick, even when the control is subclassed - may be wrong about that.
Hope that helps.
Cheers, Ian.
Hello there I have issue with overlapping of child windows,I have created a software with menu driven interface( IDR_MAINFRAME - CFormView
etc) and upon clicking one of the menu items another child-window appears( Dialog based ) where I do the calculations as a normal
calculator.Now if I open any other entry say conversion of metrics which is also in menu entry then on overlapping with any other such
window the background windows gets horribly disfigured and if i move about the calculator or the metrics conversion calculator randomly
they get disfigured and its a mess.Also I have put up a bitmap image on the background.Upon moving the calculator the background image also
gets erased.
Please let me know about how to handle this issue.I have googled and found that handling of paint messages or WM_ERASEBKGND helps ..but I
have tried this piece of code which just doesn't help in OnEraseBkGnd();
BOOL COfficesoftDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CRect Rect;
GetClientRect(Rect);
//ClientToScreen(&Rect);
//this->ScreenToClient(&Rect);
this->InvalidateRect(Rect);
return CDialog::OnEraseBkgnd(pDC);
}
how can i achieve the smooth overlapping of different windows like a notepad overlapping a word document or even a calculator or even a VC6
IDE in my project.
Please explain it with an example .I am just a newbie and I need to understand in detail...thanks and regards
Override OnEraseBkgnd and return true so it stops erasing the background you're painting. Returning TRUE says that you've done the work. If you simply call the base class implementation, it's going to do this for you, and you'll lose the background until it gets a chance to paint.
You're not getting paint messages to the parent window for some reason. Make sure you're calling the modal in the correct manner. DoModal() works fine. Make sure you're not just creating the modal and showing it.
If your windows are children on the same dialog/window and they overlap or you have children on either dialog/window, make sure that you use clipchildren and clipsiblings (if children on a window overlap). Otherwise they'll get to paint in any order they choose artifacting all over the place.
Ensure that you're painting to memory and bitblting back to your dialog, otherwise you'll get a flashing effect.
What's a simple way to implement a c++ Win32 program to...
- display an 800x600x24 uncompressed bitmap image
- in a window without borders (the only thing visible is the image)
- that closes after ten seconds
- and doesn't use MFC
If you're targeting modern versions of Windows (Windows 2000) and above, you can use the UpdateLayeredWindow function to display any bitmap (including one with an alpha channel, if so desired).
I blogged a four-part series on how to write a C++ Win32 app that does this. If you need to wait for exactly ten seconds to close the splash screen (instead of until the main window is ready), you would need to use Dan Cristoloveanu's suggested technique of a timer that calls DestroyWindow.
Register a class for the splash window and create a window using these styles:
WS_POPUPWINDOW: will make sure your window has no caption/sysmenu
WS_EX_TOPMOST: will keep the splash screen on top of everything. Note that this is a bit intrusive. It might be better to just make the splash window a child of your main window. You may have to manipulate the z-order, though, to keep any other popup windows (if you create any) below the splash screen.
Use CreateDIBSection to load the bitmap. It should be easy, since BMP files are essentially dumps of DIB structures. Or do what Ken said and use LoadImage.
Handle the WM_PAINT or WM_ERASEBKGND message to draw the bitmap on the window.
On WM_CREATE set a timer of 10 seconds and when Windows sends the WM_TIMER message, have the window destroy itself.
The key point here is to use layered window.
You can start with a win32 wizard generated project and change CreateWindow call to CreateWindowEx and set WS_EX_LAYERED as extended window style and combination of WS_POPUP and WS_SYSMENU as window style. When you do that launch your application it will be invisible. Then you should use UpdateLayeredWindow to paint your image. You may also need AlphaBlend function if you want use PNG image with alpha layer.
Hope this helps!
You can:
Create a dialog in your resource file
Have it contain a Picture control
Set the picture control type to Bitmap
Create/import your bitmap in the resource file and set that bitmap ID to the picture control in your dialog
Create the window by using CreateDialogParam
Handle the WM_INITDIALOG in order to set a timer for 10 seconds (use SetTimer)
Handle WM_TIMER to catch your timer event and to destroy the window (use DestroyWindow)
Use LoadImage to load the bitmap
Use CreateWindowEx to create the window.
In the window proc capture the WM_PAINT. Use BitBlt to paint the bitmap.
It's a Win32 api FAQ
See professional Win32api forum
news://194.177.96.26/comp.os.ms-windows.programmer.win32
where it has been answered hundreds of times for 20 years..