Залепа №4. Деревянный TreeView.
Как вы думаете, должно ли зависеть поведение контрола от его начального состояния? Не поняли что я имею в виду? Сейчас объясню.
Дамы и господа, встречайте! На сцене TreeView - самый деревянный контрол от майкрософта! Именно деревянный, с маленькой буквы и без кавычек! И вовсе не потому, что он рисует деревья, а целиком и полностью исходя из его поведения.
Итак, начальное состояние дерева в контроле - свернутое. Казалось бы разницы в этом нет - свернутое-развернутое - все равно и контрол должен вести себя одинаково. Для нас возможно и так, но вот майкрософт в этом наверное видит некий глубокий смысл, ибо их TreeView ведет себя абсолютно по-разному именно исходя из начальной степени свернутости дерева.
Но давайте все по-порядку.
Появилась у меня необходимость раскрасить надписи в TreeView. Задача эта тривиальна и встречается довольно часто. По крайней мере в грамотных интерфейсах. Событие для этого тоже предусмотрено - TreeView.DrawNode.
Итак, вот примерный обработчик (для простоты все лишнее я выбросил):
private void Tree_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
if ((e.State & TreeNodeStates.Selected) != 0)
{
e.Graphics.FillRectangle(SystemBrushes.HotTrack, e.Bounds);
e.Graphics.DrawString(e.Node.Text, Tree.Font,
Brushes.Yellow, e.Bounds);
}
else
{
e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
e.Graphics.DrawString(e.Node.Text, Tree.Font, Brushes.Red,
e.Bounds);
}
}Запускаем и наслаждаемся разноцветными надписями. Вроде все работает правильно. Но...
Но это только до тех пор, пока вы не попытаетесь развернуть какой-либо из узлов дерева. При этом происходит что-то по-настоящему удивительное - названия вложенных пунктов из разворачиваемого узла пишутся ПОВЕРХ КОРНЕВОГО УЗЛА, т.е. в левом верхнем углу окна!
Этот эффект наблюдается только при ПЕРВОМ разворачивании любого узла. Последующие сворачивания/разворачивания этого же узла уже аномалий не проявляют. Если дерево изначально развернуто, то глюк не наблюдается вообще.
Прикольно? По-моему да! :)
Но это еще не все! Самое вкусное я приберёг напоследок.
Посмотрите внимательно на приведенный выше код. Видите, в нем до печати текста происходит стирание площадки под текст. Т.е. по логике вещей, если бы в событие просто были переданы неверные координаты области текста, то было бы все понятно - вывод идет не в то место окна и потому надписи появляются абы где. Но на практике все намного интереснее!
Дело в том, что СТИРАНИЯ площадки под надписью в левом верхнем углу почему-то НЕ ПРОИСХОДИТ!!!
Т.е. получается, что координаты получены верные и FillRectangle срабатывает правильно, а вот следующая за ним команда DrawString словно срабатывает дважды - первый раз пишет строку в правильных координатах, а потом каким-то магическим образом повторяет надпись, но уже в координатах 0,0 окна TreeView.
Объяснить это загадочное поведение я не берусь. Ибо в заклинаниях культа Ктулху я не силен, особенно когда эти заклинания наложены мега-пряморуким софтверным гигантом Microsoft.
[Дополнение от 14 декабря 2007]
Как показало время, вышеописанный глюк не так прост. Он оказывается имеет несколько разных обличий.
То, что написано выше наблюдалось на тестовом дереве, в котором было около десятка узлов. Когда же это количество достигло полу-сотни глюк внезапно исчез. От неожиданности я чуть было не усомнился в собственном рассудке.
Решив отложить звонок в психушку на потом, я, как заядлый трудоголик, продолжил добавлять узлы. И тут попался пункт, название которого вышло за правый край контрола. Естественно снизу тут же возник скрол-бар, который я сразу же решил обкатать. Ну не мог я себе отказать в таком удовольствии :)
И что же я увидел?
А увидел я, что глюк мой снова вернулся, но уже не в виде скромного бага, а превратился в сильно мутировавшего монстра. Надписи, которые уезжали за край контрола (когда я тянул бегунок скрол-бара) больше не выезжали назад! На экран вернулись только иконки узлов и символы "Плюс" и "Минус", обозначающие состояние свернутости. Ни фонов, ни надписей, пустота.... :(
Такого развития событий моя и так изрядно измотанная психика уже вынести не смогла. Истерически отхохотав, я решил посмотреть, что же будет дальше и снова взялся за пополнение горе-дерева....
...не знаю, как там будет дальше, но сейчас в дереве около 400 узлов - глюка не наблюдаю. Ни одного символа в коде не менял. Наверное пора мне к психиатру... :(
Залепа №3. Майкрософт - антиглобалист!
C# - мега-объектно-ориентированный язык. Настолько ориентированный, что создатели решили насовсем отказаться от глобальных объектов, хотя в классическом ООП на этот счет нет таких строгих правил.
Смысл этого отказа остается непонятным - без глобальных объектов просто невозможно написать ни одной программы, в крайнем случае хотя бы один объект но все же будет глобальным. Например объект, представляющий само приложение :)
Но давайте лучше рассмотрим КАК это выглядит на практике.
Думаю, никто не будет спорить, что в любой программе есть функции, не привязанные к какому-то определенному объекту, т.е. по-сути глобальные (например та же Main()). Так же есть и объекты, не являющиеся членами других объектов, т.е. тоже глобальные. В C# глобальных объектов быть не может, поэтому вышеописанные пасажиры насильно всунуты в классы-обертки, а свою истинную глобальность выдают только наличием волшебного слова "Static".
Но объясните мне, дураку, в чем такое мега-отличие между обычной глобальной переменной от той же переменной с атрибутом static и засунутой в псевдо-класс, который представляет собой просто бесполезную оболочку?
Скажете - это для разделения, чтоб не возникало конфликтов имен? Но чем гениев из мелкософта не удовлетворили обычные (и именно для этого и созданные!) пространства имен? Ну разве это:
namespace MyVariables
{
int a, b, c;
void ThisIsMyFunc(string par) {...};
}хуже чем это:
namespace MyNamespace
{
public class МойНафигЗдесьНеНужныйКласс
{
public static int a,b,c;
public static void ThisIsMyFunc(string par) {...};
}
}Меня пол-часа бил истерический хохот, когда я впервые увидел вот эту супер-ООП-конструкцию:
static class Program
{
static void Main(){...}
}Может в мелкософте ЭТО считают вершиной своих достижений, мне же кажется, что ЭТО - просто чушь.
