I'm using a VB6 PictureBox on my User Control. I set the PictureBox's picture, I set the BorderStyle to 0, and I set the BackColor to the User Control's BackColor. The idea is that I want a "floating" icon. However, I want that icon to appear clickable when the mouse hovers over it.
Two questions:
Which events do I use? MouseMove seems to be the closest to a "MouseOver" event. Are there any cleaner alternatives?
How should I change the style? I've tried a few things, but none of them quite look right.
MouseMove is the correct event in VB6. You'll have to do some work to manually detect when the mouse leaves the client area cleanly. (My experiments in this world, lo those many years ago, always found implementing this behavior to be tricky.)
For changing the style, I'd recommend using GDI to: (a) shift the image one pixel up and to the left; (b) draw a single pixel line in the ButtonHighlightColor along the top and left edges; and (c) draw a single pixel line in the ButtonShadowColor along the bottom and right edges. This is trickier than it sounds, particularly in VB6, so ultimately I'd recommend ...
That you look at vbAccelerator's toolbar controls. They're free, and they'll probably get you most of where you want to be. (And yes, they're "classic" VB -- that is, VB6.)
Related
Say you have a form that you can expand to the left to show additional controls:
Collapsed:
Expanded:
The simplest way to achieve this in Delphi is to use alRight as the primary anchor for all controls (instead of alLeft) and then simply adjust the width and X coordinate of the form. Either you can set the Width and Left properties individually, or you can use a function that sets them simultaneously, like
if FCollapsed then
SetWindowPos(Handle, 0, Left - Width, Top, 2 * Width, Height, 0)
else
SetWindowPos(Handle, 0, Left + Width div 2, Top, Width div 2, Height, 0)
The problem is that there is quite noticeable flickering in the always-visible part of the form (in this example, the buttons) while expanding or collapsing. Try it yourself!
It is possible for the operating system to resize the form to the left without any flickering at all -- just grab the left edge of the form using the mouse and drag the mouse to the left or right -- but I am unable to find any function in the Windows API that exposes this kind of resizing.
I have tried to use several different Windows API functions to resize and reposition the form, tried their various parameters (for instance, the SWP_* flags), tried LockWindowUpdate, WM_SETREDRAW, TForm.DoubleBuffered etc. to no avail. I also examined the possibility to use the WM_SYSCOMMAND SC_SIZE approach.
I am not yet sure if the problem lies at the OS level or the VCL level.
Any suggestions?
Edit: I am very surprised to see that this Q received close votes. Let me try to clarify:
Create a new VCL forms application.
Add a few buttons to the right side of the main form and a memo to the left. Set Anchors to [alTop, alRight] on all controls. On the OnClick handler of the buttons, add the following code:
if FCollapsed then
SetWindowPos(Handle, 0, Left - Width, Top, 2 * Width, Height, 0)
else
SetWindowPos(Handle, 0, Left + Width div 2, Top, Width div 2, Height, 0);
FCollapsed := not FCollapsed;
where FCollapsed is private boolean field of the form (initialized to false).
Now, click the buttons repeatedly. (Or give one of them keyboard focus and hold the Enter key for a few seconds.) You will probably notice that the region with the buttons on your monitor will not display a perfect still image, but will flicker. In addition, you might actually see 'ghosts' of the buttons to the left of the actual column of buttons.
I am unable to capture this millisecond flickering using screen capture, so instead I used a digital camera to record my screen:
https://privat.rejbrand.se/VCLFormExpandFlicker.mp4
In this video clip, it is apparent that the column of buttons isn't a static image on the screen; instead, for a few milliseconds each time the form is resized, this region is something else than it should be. It is equally apparent that there is a 'ghost' column of buttons to the left.
My question is if there is any reasonably simple way to get rid of these visual artefacts (that at least to me are very visible even if you expand/collapse the form a single time).
On my Windows 10/Delphi 10.1 computer at work, the form is resized in a perfect manner when I drag its left-most edge using the mouse: the unaffected client area of the form is perfectly static on the monitor. However, on my Windows 7/Delphi 2009 PC at home, I do see that there is a lot of repositioning going on when I do this.
I can provide some insight about why you see ghost images of the other half of your UI and possibly a way to stop it. The ghost image indicates that someone is copying your client area pixels (and copying them to the wrong place, always flush-left in your window) before you have a chance to redraw them with the correct pixels.
There are likely two different, overlapping sources of these ghost pixels.
The first layer applies to all Windows OSes and comes from a BitBlt inside SetWindowPos. You can get rid of that BitBlt in several ways. You can create your own custom implementation of WM_NCCALCSIZE to tell Windows to blit nothing (or to blit one pixel on top of itself), or alternately you can intercept WM_WINDOWPOSCHANGING (first passing it onto DefWindowProc) and set WINDOWPOS.flags |= SWP_NOCOPYBITS, which disables the BitBlt inside the internal call to SetWindowPos() that Windows makes during window resizing. This has the same eventual effect of skipping the BitBlt.
However, Windows 8/10 aero adds another, more troublesome layer. Apps now draw into an offscreen buffer which is then composited by the new, evil DWM.exe window manager. And it turns out DWM.exe will sometimes do its own BitBlt type operation on top of the one already done by the legacy XP/Vista/7 code. And stopping DWM from doing its blit is much harder; so far I have not seen any complete solutions.
For sample code that will break through the XP/Vista/7 layer and at least improve the performance of the 8/10 layer, please see:
How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?
Since you have multiple child windows, the situation is even a little more complicated. The BitBlt type operations I mentioned above happen on your whole top-level window as a whole (they treat the window as one set of pixels regardless of how many windows are underneath, and regardless of CLIPCHILDREN). But you need to have windows move atomically so that on the next redraw they are all positioned correctly. You may find BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos useful for that (but only go there if the above tricks do not work).
We need to overlay a target window with a custom shape and tracks the position of the target window such that the overlay drawing always appears above it. Also, the overlay drawing should appear in screenshots taken using BitBlt or PrintClient by screen-capturing tools like Camtasia, Debut, etc. Also, moving the target window around should not leave traces of the drawing at earlier location. The target window is not made using our code.
So far we've tried several ways but each method has its problems:
1) Layered Window:
Using a layered window as the child/owned window of the target window is the easiest thing and it works. But the problem is on Windows 7 and XP, layered windows do not appear in a BitBlt done without the CAPTUREBLT flag and the screen-capturing tools may call BitBlt without the flag, thereby skipping our window from the capture.
2) Region Window:
The crude approach to support all Windows versions then is to use a region window using SetWindowRgn and make the target window its owner. However, region windows are generally very slow in rendering complex shapes and also impact the performance of other windows, sometimes to the point of freezing the application. Region window also leaves traces on dragging the application window.
3) Subclassing and Drawing on HDC:
Another approach is to sub-class the target window and draw the shape on its HDC on the OnPaint() event inside the window procedure hook. The shape can be drawn on the desktop window instead too. The problem is that applications may draw without a paint event, like when some text is selected using the cursor, and such drawing may erase a part of the custom drawing. Tracking all possible paint events is not a good way to do this.
4) Drawing continuously in a timer:
The last resort is to draw the custom shape on the target window in a timer continuously so the drawing is always above the target, even on text selection. But this may show a bit of flicker when the text is selected. Not to mention, it is very performance heavy to draw constantly.
Question
What is the best way to achieve an overlay drawing which works on all Windows versions (since XP) at the same time appearing in screen-captures. We've exhausted all approaches. Is there some method I'm missing? Can the above mentioned ways be used with some improvement? Is DirectX an option? I'm looking for methods with fast rendering capacity to achieve this. Appreciate any help!
I think the best solution to draw an overlay window, is to use a double-buffered technique GDI, just like in this example:
Overlay Drawing in CScrollView
I have myself the same task, and the only solution was that one. Hope it help you.
Effect like the mac mail app,this image is a screenshot
how can i get effect like that. I try the cocoa text system,and don't find some useful things.
and I use the nstextattachment with textatttachmentcell initImageCell,obtain some effect like that,but it is not good,it is not very nature.
please some one give directions to me.
Those objects are not glyphs, they are controls, such as a subclass of a button. Custom controls have a drawing routine, which you override to draw a blue rectangle with round corners (a bezier path is the most flexible way to do so), then you draw the text (including the caret character) centered in the blue rectangle. Finally, handle the mouse events to do what you need to do when the control is clicked, such as popping up a menu in the right location.
I made a flyout window in the notification area using WinAPI and my goal was to make it similar to the flyout windows that show up when you click some of the icons in the notification area, like the Volume icon.
I already succeeded in making it look and behave similar to the other ones, but there is one thing I can't seem to figure out. The link area of the flyout windows has a darker blueish background and there is a subtle difference in the look between Windows 7 and Windows 8. A picture of it in Windows 7 can be seen here
http://msdn.microsoft.com/en-us/library/windows/desktop/aa511448.aspx#flyouts
I achieved this by painting this link area of my flyout window manually in the right colors (including the gradient at the topmost part of the section) using the WM_PAINT message, but I just feel like it's too much of a hack, especially because it's not affected by changing themes in Windows. For example, if I set the "Windows Classic" theme this area should be grey and not blue.
So, my question is, am I missing something in how this can be achieved without painting the window manually. I noticed that the details pane in Explorer windows in Win 7 has the same look. I've searched quite a bit for answers but I haven't found anything yet. This is my first time doing a GUI using the WinAPI so I have very little experience, and therefore I'm assuming there is something that I just don't know about.
UPDATE:
I did manage to figure out how to draw this area without painting it manually. It can be drawn by using the OpenThemeData and DrawThemeBackground functions
HTHEME aeroTheme = OpenThemeData(hWnd, L"FLYOUT");
DrawThemeBackground(aeroTheme, hdc, FLYOUT_LINKAREA, 0, &rect, &rect);
This obviously only works when themes are enabled, so for non-themed cases I draw a normal rectangle with the appropriate color.
I'm not an expert in WinAPI so I can't offer any advice on achieving the look you want without manual painting.
However, if you're successfully achieving the appearance for a particular color theme, I'd suggest you look at the GetSysColor function and use this when creating your brushes for painting. This should allow you to get the correct colors based on the theme that has been set. More info (including a swatch table) can be found here.
Hope this helps.
I'm trying to make an educational interactive presentation for kinder children using Power Point, and I'm trying to do a kind of test/activity in which the children have to click on some pictures according to the question. Some will be right, some don't. (for instance: can you point the tools used by a fireman? and show 4 images of different tools)
Using the mousemove event, I can reproduce a sound that says the name of the object, and using the click event I can reproduce another sound to tell the children "wrong" or "right".
Now, I would like to change the border of the picture they are clicking on (color and or width), but I have no clue how to do it in VBA.
It must be very easy, but I don't know the sintax :-(
Any help? Please?
Thank you!
You would be surprised but it's not so easy as you expected, of course, when doing smartly with classes and events.
I'll give you simple idea, so if you have time and really need it you could go this way. But there would be some problems- you will have to figure out how could you get starting borders of your shapes.
Here is idea how to start.
name each of the shape on the slide- select one and run the following instruction in Immediate window in VBA editor, eg.:
ActiveWindow.Selection.ShapeRange.Name = "Fireman"
to change the color and line write macro for each shape (this will run only in slideshow view):
Sub FiremanClick()
With SlideShowWindows(1).View.Slide.Shapes("Fireman").Line
.Weight = 2
.ForeColor.RGB = RGB(255, 0, 0)
End With
End Sub
in application right-click fireman shape and associate action with macro you wrote.
you will need to figure out how to set back standard setting of each shape and when.
For some reason, some kind of bug happens when setting the border shape color first and then the weight, the shape border color becomes the generic blue one in PowerPoint 2010.