Zorder of overlapping rectangles

I am drawing some simple rectangles. One overlaps the other slightly to create a shadow effect. Top rectangle is dark gray and shadow is black I can't figure out tell it to put the dark gray rectangle on top.
I tried code for dark gray rect then shadow and also shadow then dark gray. Doesn't make any difference.
Is there a way to specify z order?

(And is there an easier way to create a drop shadow?)

Which OS / Compiler / Graphics Library are you using?

Some example code to look at would be better.

If it's a http://sscce.org/ even better.
Last edited on
@jvallee

Here is a program I wrote to create boxes of varying sizes and colors. I modified it a bit, by not asking for colors of box, shadow, text etc. Nor which of 4 border designs or none at all. If you have questions on how to add this to your program, I'll be happy to help out.

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <iostream>
#include <string>
#include <windows.h>

using std::cout;
using std::cin;
using std::endl;
using std::string;

using namespace System;

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); \\ For gotoXY()
COORD CursorPosition; \\ Also for gotoXY()

enum {
	black,          //  0
	dark_blue,      //  1
	dark_green,     //  2
	dark_cyan,      //  3
	dark_red,       //  4
	dark_magenta,   //  5
	dark_yellow,    //  6
	light_gray,     //  7
	dark_gray,      //  8
	light_blue,     //  9
	light_green,    // 10
	light_cyan,     // 11
	light_red,      // 12
	light_magenta,  // 13
	light_yellow,   // 14
	white           // 15
};

#define _CRT_SECURE_NO_WARNINGS

#define on , // So I can use the function - void text(text_color on background_color)
// To more easily remember which is text color vs background color

void gotoXY(int x, int y);
void gotoXY(int x, int y, string text);

void Box(int style, int across, int down, int amount, int rows, int b_color, int f_color, int shadow, int shadow_color);

void WaitKey();

void ClearScreen();

// My text color function. Use it if you wish.
void text(int text_color = 0 on int paper_color = 7)
{
	// defaults to black on light_gray

	int color_total = (text_color + (paper_color * 16));
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_total);
}

int width = 120;
int height = 34;

int main()
{
	int wide, tall, shadow;
	int over, down; // To center the box
	Box(1, 0, 0, width, height, black, light_gray, 0, 0);

	gotoXY( 5, 2, "How wide is the box being created?  _\b");
	cin >> wide;
	over = (width-wide)/2;
	gotoXY( 5, 4, "And how tall is the box being created?  _\b");
	cin >> tall;
	down = (height-tall)/2;
	gotoXY( 5, 6, "Do you want a shadow effect from the box? ( 1 for 'Yes', 0 for 'No'  _\b");
	cin >> shadow;

	Box(2, over, down, wide, tall, black, white, shadow, dark_gray);
	gotoXY( 53, 34);
	text(white on black);

}

void gotoXY(int x, int y)
{
	CursorPosition.X = x;
	CursorPosition.Y = y;
	SetConsoleCursorPosition(console, CursorPosition);
}

void gotoXY(int x, int y, string text)
{

	CursorPosition.X = x;
	CursorPosition.Y = y;
	SetConsoleCursorPosition(console, CursorPosition);
	cout << text;
}

void Box(int style, int across, int down, int amount, int rows, int f_color, int b_color, int shadow, int shadow_color)
{

 	char Shadow = ' ';
	char  Style[5][11] = {
	{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
	{ ' ', '\xDA', '\xC4', '\xBF', '\xB3', '\xC0', '\xD9', '\xC3', '\xB4', '\xC2', '\xC1' },
	{ ' ', '\xC9', '\xCD', '\xBB', '\xBA', '\xC8', '\xBC', '\xCC', '\xB9', '\xCB', '\xCA' },
	{ ' ', '\xD5', '\xCD', '\xB8', '\xB3', '\xD4', '\xBE', '\xC6', '\xB5', '\xD1', '\xCF' },
	{ ' ', '\xD6', '\xC4', '\xB7', '\xBA', '\xD3', '\xBD', '\xC7', '\xB6', '\xD2', '\xD0' }
	};
	
	int x;
	string BoxLine(amount - 2, Style[style][2]);
	string BoxBody(amount - 2, ' ');
	string ShadowLine(amount, Shadow);

	gotoXY(across, down);
	text(f_color on b_color);
	cout << Style[style][1] << BoxLine << Style[style][3];
	for (x = 1; x < rows; x++)
	{
		gotoXY(across, down + x);
		cout << Style[style][4] << BoxBody << Style[style][4];
		if (shadow)
		{
			text(shadow_color, shadow_color);
			cout << Shadow;
			text(f_color on b_color);
		}
	}
	gotoXY(across, down + rows - 1);
	cout << Style[style][5] << BoxLine << Style[style][6];
	if (shadow)
	{
		text(shadow_color, shadow_color);
		cout << Shadow;
		gotoXY(across + 1, down + rows);
		cout << ShadowLine;
		text(f_color on b_color);
	}
}
Visual Studio 2019
This is what I have added to a basic Visual Studio Form and it works correctly thru the "OK TO HERE" comment.

But code after that does not paint in the correct z order (I would think mid top shadow rect then mid top gray rect) like the first set does.

The code after the "ok to here" put the shadow box ON TOP!

Graphics^ g = pe->Graphics;
g->Clear(Color::White);
Pen^ redPen = gcnew Pen(Color::FromArgb(255,0,0,192));

// Create background rectangle
Pen^ blackPen = gcnew Pen(Color::Black);
blackPen->Width = 6;
SolidBrush^ myBrush = gcnew SolidBrush(Color::FromArgb(255, 230, 230, 230));
Rectangle rect = Form::ClientRectangle;
Rectangle smallRect;
smallRect.X = 10;
smallRect.Y = 40;

smallRect.Width = 1024 - 20;
smallRect.Height = 768 - 55;
g->DrawRectangle(blackPen, smallRect.X, smallRect.Y, smallRect.Width, smallRect.Height);
// Fill rectangle to screen.
g->FillRectangle(myBrush, Rectangle(smallRect));

// Create left black shadow box.

blackPen->Width = 1;
SolidBrush^ shadowBrush = gcnew SolidBrush(Color::Black);
//Rectangle rect = Form::ClientRectangle;
Rectangle shadowRect;
shadowRect.X = 45 + 5;
shadowRect.Y = 80 + 5;
shadowRect.Width = 935;
shadowRect.Height = 642;
g->DrawRectangle(blackPen, shadowRect.X, shadowRect.Y, shadowRect.Width, shadowRect.Height);
// Fill rectangle to screen.
g->FillRectangle(shadowBrush, Rectangle(shadowRect));


// Create left dark gray box
redPen->Width = 6;
SolidBrush^ grayBrush = gcnew SolidBrush(Color::FromArgb(255, 192, 192, 192));
//Rectangle rect = Form::ClientRectangle;
Rectangle leftgrayRect;
leftgrayRect.X = 45;
leftgrayRect.Y = 80;
leftgrayRect.Width = 935;
leftgrayRect.Height = 642;
g->DrawRectangle(redPen, leftgrayRect.X, leftgrayRect.Y, leftgrayRect.Width, leftgrayRect.Height);
// Fill rectangle to screen.
g->FillRectangle(grayBrush, Rectangle(leftgrayRect));

//create while header
redPen->Width = 1;
SolidBrush^ whiteBrush = gcnew SolidBrush(Color::White);
//Rectangle rect = Form::ClientRectangle;
Rectangle whitetopRect;
whitetopRect.X = 46;
whitetopRect.Y = 80;
whitetopRect.Width = 933;
whitetopRect.Height = 50;
g->DrawRectangle(redPen, whitetopRect.X, whitetopRect.Y, whitetopRect.Width, whitetopRect.Height);
// Fill rectangle to screen.
g->FillRectangle(whiteBrush, Rectangle(whitetopRect));

// OK to here *********************

// BUT NOT THIS CODE??? same order as above (shadow first then dark gray box)

// middle top shadow
shadowRect.X = 389;
shadowRect.Y = 137;
shadowRect.Height = 430;
g->DrawRectangle(blackPen, shadowRect.X, shadowRect.Y, shadowRect.Width, shadowRect.Height);
// Fill rectangle to screen.
g->FillRectangle(shadowBrush, Rectangle(shadowRect));

// middle top gray rect
Rectangle midgrayRect;
midgrayRect.X = 384;
midgrayRect.Height = 430;
g->DrawRectangle(redPen, midgrayRect.X, leftgrayRect.Y, leftgrayRect.Width, midgrayRect.Height);
// Fill rectangle to screen.
g->FillRectangle(grayBrush, Rectangle(midgrayRect));


Topic archived. No new replies allowed.