In Perl Win32::GUI desktop apps,
While checkbox checked status I need to hide some controls and I need to move the controls to places which are hidden, for window compact view in Perl Win32::GUI. While using below code the control's images are repeated(duplicates) at the time of Controls movement. Kindly please give solution to avoid duplicate images of controls while moving and resizing the window.
sub Check_Status{
if($btwdates->GetCheck eq 1){
$Pushlistmodelabel->Move(30,168);
$Fromdatelabel->Show();
$get_From_day->Show();
$Todatelabel->Show();
$get_To_day->Show();
$FoldersOption->Disable();
$PushListButton->Move(200,255);
$processlabel->Move(2,285);
$PushListButton->Move(135,295);
$processlabel->Move(2,320);
$Selectionlabel->Move(195,168);
$FilesOption->Move(200,195);
$FoldersOption->Move(200,225);
$With_root->Move(35,195);
$Without_root->Move(35,225);
$changeOption->Move(35,255);
$replacepath->Move(180,255);
Win32::GUI::DoEvents() >= 0;
}
else{
$FoldersOption->Move(200,165);
$FilesOption->Move(200,135);
$FoldersOption->Enable();
$Selectionlabel->Move(195,108);
$Pushlistmodelabel->Move(30,108);
$Fromdatelabel->Hide();
$get_From_day->Hide();
$Todatelabel->Hide();
$get_To_day->Hide();
$PushListButton->Move(200,195);
$processlabel->Move(2,225);
$Pushlistmodelabel->Move(30,108);
$With_root->Move(35,135);
$Without_root->Move(35,165);
$changeOption->Move(35,195);
$replacepath->Move(180,195);
}
}
Taking a shot in the dark (I don't have a win32 perl install), you could try the SetRedraw method. SetRedraw(0) before rearranging the controls and SetRedraw(1) afterwards. Maybe also a manual Redraw() afterwards.
There is a non-perl-specific discussion of some techniques for avoiding flicker when updating a window in the question Win32 GUI flickering on resize.
Related
I want to create a window with the following properties:
Thick border ("double border" as described in MSDN)
Not resizable
Icon in the title
Close button in the title
It sounds so simple and we can find this kind of windows everywhere in Windows. But as soon as I disable ability to resize my window I also lose the thick border. Here is the illustration of my problem:
The height of my test window's caption bar is slightly less than that of a Shell property dialog, but I would like it to be the same height.
I have tried to use WinSpy and copy all styles from Explorer's window to mine, but this did not help.
I don't know what's going on under the hood, but I found two solutions:
Switch to the newer Platform Toolset (which means drop support of Windows XP)
Disable resizing by writing custom WM_NCHITTEST handler
The second option is quite simple and I do not want drop Windows XP support for a silly reason. Job is done:
LRESULT CListEditorDlg::OnNcHitTest(CPoint point)
{
LRESULT retVal = CDialog::OnNcHitTest(point);
switch (retVal)
{
case HTBOTTOM:
case HTBOTTOMLEFT:
case HTBOTTOMRIGHT:
case HTLEFT:
case HTRIGHT:
case HTTOP:
case HTTOPLEFT:
case HTTOPRIGHT:
retVal = HTBORDER;
}
return retVal;
}
I am trying to hide the mouse cursor using win32 API ShowCursor(FALSE), but on a multiscreen setup when the mouse gets to the other screen I don't get any mouse updates in windows.
Is there any way I can prevent this?
This is for a fullscreen video game and I don't seem to find any windows api that can do something like this.
From what I understand, your problem is not in hiding the mouse cursor, but in constraining it to your window?
In that case, the ClipCursor function should do the job.
{
RECT windowRect;
GetWindowRect(hWnd, &windowRect);
ClipCursor(&windowRect);
}
For a border-less full-screen window, it should be fine to do that once. You would need to repeat that step if your window's position or size ever changes or the window loses focus.
For game programming, there are likely better methods though, such as DirectInput, which provides an exclusive mouse handling mode (tutorials available) and does all that for you on a lower-level basis.
There are some discussions available about the different ways to handle this, for instance this one on the MSDN forums.
If, on the other hand, you want the cursor to be able to leave your window, and only hide it while it's over your window, you should handle the WM_SETCURSOR message and use SetCursor to hide the cursor.
case WM_SETCURSOR:
SetCursor(NULL);
return TRUE;
My purpose is to size a window to a width/height greater than the size of my physical screen programmatically under Win32. How can I do this?
On my systems it seems the maximum size of a given window is bound by the size of my screen whether programmatically or whether sizing manually by dragging the sizing cursor.
I have tried programmatically with SetWindowPos() and MoveWindow() and both cap the size of the target window. Oddly I know some people do not have this 'cap' so I wonder whether this is perhaps due to some OS setting (registry). Does anyone know something about this? Or perhaps some way to workaround it?
// Edit: new developments
I am testing on Windows XP and Windows 7. The graphics cards I'm using are a NVIDIA Quadro NVS 290 (256MB) and a Geforce 9800GT (1GB). After further investigation it looks like Windows is intercepting the message and fiddling with the parameters. For example, if you call SetWindowPos to make a target 2000x2000 it will only receive a WM_SIZE for the capped x/y.
Implement a message handler for WM_GETMINMAXINFO to stop Windows from applying the sane default behavior:
case WM_GETMINMAXINFO: {
DefWindowProc(hWnd, message, wParam, lParam);
MINMAXINFO* pmmi = (MINMAXINFO*)lParam;
pmmi->ptMaxTrackSize.x = 2000;
pmmi->ptMaxTrackSize.y = 2000;
return 0;
}
Windows with a thick frame (to allow user resize) are restricted from growing larger than the desktop.
Try SetWindowLong() clearing the THICKFRAME (0x40000) flag.
The following should allow programatic sizing, but the user will lose the ability to resize. If you add the Thickframe back after sizing, the user can resize, but when he does so the window will immediately shrink back to the desktop limited size.
The following is from some csharp code that also removes all borders, caption, etc:
WS style = (WS)GetWindowLong(ptr, GWL_STYLE);
style = style & ~WS.BORDER & ~WS.ThickFrame & ~WS.SYSMENU & ~WS.CAPTION | WS.POPUP;
SetWindowLong(ptr, GWL_STYLE, (int)style);
A good tool to play with window settings is uuSpy.
It's like Microsoft Spy++, but allows you to modify settings like THICKFRAME.
Yes, windows can be larger than the screen (or even the sum of all your monitors). Windows can also be positioned off-screen (which some applications do as a hack to hide while remaining active).
Perhaps the Windows 7 desktop manager is kicking in and trying to "dock" those windows to the edges of your screen for you.
You might try using the slightly lower-level API SetWindowPos, which gives you control over notifications, z-order, and other stuff.
You can get a window to be larger in resolution (and even way way larger) than your screen, using the 'Infinte Screen" software:
http://ynea.futureware.at/cgi-bin/infinite_screen.pl
Here's how to use it:
Download it, run it.
In the Oversize tab, choose the Windows you want to enlarge.
Give it the Width and Height you want. Done!
Just in case you need a large screenshot (that's how I ended up here):
If you want to get a screenshot of the window, you've got a screenshot option in the same Oversize tab. (Because screenshots are normally no bigger than the screen size, even if the window is larger). Another (and better) way to screenshot the window is using Greenshot, as you can save them in .tiff and directly watching the window.
I'm developing an interactive MFC application which displays a 3D object using my own algorithm, essentially using MFC as a framework, but using lots of pDC->Polygon(), pDC->Rectangle(), pDC->DrawText(), etc. calls.
The UI has numerous clickable areas which all work well. However, the onscreen controls for rotating, spinning, etc. the 3D image motivate users to double click, triple click, and beyond.
I'm 99% positive that CWnd::OnLButtonDown() is not called until Windows (or whatever) has decided the operation is not a double click, or when double clicked, but only once. That is a series of clicks results in a notification every second click. The user experience is stuttered rotation. The temporary workaround is to have users move the mouse slightly between clicks—It solves the problem, but is rather unfriendly.
The application does no double click event hooking. Maybe there's a way to go further to disable potential double click processing? Or maybe there is a lower-level way to capture the mouse button down?
I think you have it backwards - the first click gets through as a WM_LBUTTONDOWN, the second one gets turned into a double-click.
To prevent a window from generating WM_LBUTTONDBLCLK messages, remove the CS_DBLCLKS style from the window.
This is all explained in the WM_LBUTTONDBLCLK documentation.
Edit: I misspoke, CS_DBLCLKS is a class style, not a window style. I don't think you can remove it, you have to create a new window class that doesn't include it. It's provided by MFC - see this page http://msdn.microsoft.com/en-us/library/a77269ff(VS.80).aspx.
Just to add an answer, this method worked for me:
WORD dwStyle = GetClassLongPtr(handle, GCL_STYLE);
dwStyle &= ~CS_DBLCLKS;
SetClassLongPtr(handle, GCL_STYLE, dwStyle);
You can use these functions to edit a WNDCLASSEX style structure for an specific window removing the double click event and correcting the single click behavior.
GetClassLongPtr
SetClassLongPtr
I have a dialog that resizes. It also has a custom background which I paint in response to a WM_ERASEBKGND call (currently a simple call to FillSolidRect).
When the dialog is resized, there is tremendous flickering going on. To try and reduce the flickering I enumerate all child windows and add them to the clipping region. That seems to help a little -- now the flickering is mostly evident in all of the child controls as they repaint.
How can I make the dialog flicker-free while resizing? I suspect double-buffering must play a part, but I'm not sure how to do that with a dialog with child controls (without making all child controls owner-draw or something like that).
I should note that I'm using C++ (not .NET), and MFC, although pure Win32-based solutions are welcomed :)
NOTE: One thing I tried but which didn't work (not sure why) was:
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.FillSolidRect(rect, backgroundColor);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
Assuming that "FillSolidRect" is the erase of your background then return TRUE from the WM_ERASEBKGND.
To do the double buffering that you are almost doing in your code fragment, you will need to use CreateCompatibleBitmap and select that into your memDC.
Try adding the following line to your OnInitDialog function:
ModifyStyle(0, WS_CLIPCHILDREN, 0);
Do nothing in the WM_ERASEBKGND handling and do the erase as part of your main WM_PAINT. You can either paint smarter so that you only redraw the invalid areas, or more easily, double-buffer the drawing.
By not doing anything in the erase background, you have all your drawing code in one location which should make it easier for others to follow and maintain.
If you are targeting WinXP or higher, you can also use the WS_EX_COMPOSITED style to enable double-buffering by default for top-level windows with this style. Bear in mind this has its own set of limitations -- specifically, no more drawing out of OnPaint cycles using GetDC, etc.
you can set parameter of your call to InvalidateRect method as false. This will prevent you to send WM_ERASEBKGND when the window will redraw.
Double buffering is indeed the only way to make this work.
Child controls will take care of themselves so long as you make sure CLIPCHILDREN.