Shadow under homemade menus

You see them everywhere. Office 2003 uses them, most programs with a custom user interface have them and they are even available when creating a GUI application in Visual Studio with a .NET language.

I'm talking about the shadows a few pixels 'south east' of any popup in a menu, and by menu I mean the horizontal bar that is always in the top of the client area. For example open Notepad and fold out one of the popups in the menu - 'File' for example. Then you will see a dark gray shadow surrounding it's bottom and right sides. It is not entirely transparent, I think the word here is translucent, and it goes from that dark gray color that is closest to the popup itself to whatever the shadow is 'cast upon' very smoothly.

Obviously I'm telling you all this because I wish to program a similar menu with that shadow. Programming a popup menu like the standard one is difficult but by no means impossible and I have succeeded in doing so actually. But the shadow... I have an idea on how to make it, but it's rather clumsy and thus I'm turning to you guys for a solution.

I am quite proficient with the Windows API and GDI, but I'd prefer a detailed explanation of how to make the shadow rather than a link to a source code (I've had that) that's several thousand lines long.

I think that was all for now.
Have a nice weekend all :-)
Not sure I follow: Are you saying you want to write the code to mimic the shadow as opposed to ask the Windows OS to just show it for you? If that's your case then my first attempt would be to append to the window that's about to be shown to tiny layered windows with transparency. But if that's cheating, I guess my real first attempt would be to take a screenshot of the desktop beneath the position of the shadow windows and alpha-blend it with black and repeat this process every time the window is moved.

But that leaves us with a problem: How can we efficiently detect if the background changes? That tosses my solution to the can.

So all in all, I don't think I would venture do this.

So in conclusion: My recommendation is to just specify CS_DROPSHADOW and be done with it. See http://msdn.microsoft.com/en-us/library/windows/desktop/ff729176(v=vs.85).aspx .
There are sample codes which do exactly this in codeproject.com website, but all of them uses either MFC or WTL. Look at them and try to port to win32api if you want.
I did not know of CS_DROPSHADOW ... !! Thank you very much!

I will try CS_DROPSHADOW first, and if that doesn't do what I want I might try your way, modoran, but I'd prefer not to involve MFC.
I cannot get it to work. Could you post an example? This is the code I'm using. It creates a window and a homemade child control with a border but no shadow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <windows.h>

HWND hStatic;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE:
			SystemParametersInfo(SPI_SETDROPSHADOW, 0, NULL, SPIF_SENDCHANGE);
            hStatic = CreateWindow("CustomChildWindow", "Hello",
                WS_CHILD | WS_VISIBLE | WS_BORDER,
                10, 10, 100, 50,
                hwnd, NULL, NULL, NULL);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

LRESULT CALLBACK CustomProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) {
    WNDCLASS wc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND+1;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInst;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "TestWindow";
    wc.lpszMenuName = NULL;
    wc.style = 0;
    RegisterClass(&wc);

	wc.lpszClassName = "CustomChildWindow";
	wc.style = CS_DROPSHADOW;
	wc.lpfnWndProc = CustomProc;
	RegisterClass(&wc);
    
    HWND hwnd = CreateWindow("TestWindow", "This is a test window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        0, 0, hInst, 0);

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
CS_DROPSHADOW only works on non-child windows. Menus and such are created as non-child (as in no WS_CHILD window style).

If you are looking for a shadow effect on a WS_CHILD window then go with the screenshot+alpha blend approach because chances are you are in 100% control of the background, meaning this approach is probably the next best thing.
Okay, but I also tried CS_DROPSHADOW on non-child windows, and it still did not seem to work. First I tried on a non-child with no frame (like a menu popup), but there was no shadow. Then I tried on a WS_OVERLAPPED window, and I couldn't see any changes there either.

I think the screenshot+alpha blend solution is the next best thing too, but the screen may vary each time the user clicks the menu, which means I have to take a screenshot each time, and that will slow down things a lot... Am I right?
Topic archived. No new replies allowed.