A pragmatic solution is to use the form’s GetChildAtPoint() method, passing the 4 corners of the control. If one of them returns true then the control is definitely visible. It is not 100% reliable, all 4 corners could be overlapped by another control but still leave part of interior visible. I would not worry about that, too bizarre.
public bool ChildReallyVisible(Control child) {
var pos = this.PointToClient(child.PointToScreen(Point.Empty));
//Test the top left
if (this.GetChildAtPoint(pos) == child) return true;
//Test the top right
if (this.GetChildAtPoint(new Point(pos.X + child.Width - 1, pos.Y)) == child) return true;
//Test the bottom left
if (this.GetChildAtPoint(new Point(pos.X, pos.Y + child.Height -1)) == child) return true;
//Test the bottom right
if (this.GetChildAtPoint(new Point(pos.X + child.Width - 1, pos.Y + child.Height -1)) == child) return true;
return false;
}