28.06.08
Tags: WPF (.Net 3.0), Программирование / 12:21 pm , Victor Laskin
Уже несколько раз подряд за последние дни упираюсь в “пределы” WPF. Причём задачи были отнюдь не экзотические.
Класс Popup генерирует окно, которое располагается поверх всех окон в системе. Если вы хотите изменить это вам поможет только Win32 API:
[DllImport(“user32″, EntryPoint = “SetWindowPos”)]
private static extern int SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int cx, int cy, UInt32 wFlags);
const UInt32 SWP_NOSIZE = 0×0001;
const UInt32 SWP_NOMOVE = 0×0002;
const UInt32 SWP_NOACTIVATE = 0×0010;
static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
static readonly IntPtr HWND_TOP = new IntPtr(0);
public static void Popup_SetZOrderTop(Popup pop)
{
IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(pop.Child)).Handle;
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
С помощью этой функции также можно регулировать какое из окон находиться наверху в данный момент.
Получение текущих координат мыши в WPF возможно только с указанием контрола, относительно которого вам нужны эти координаты. А что делать если этот самый контрол нужно двигать?
public struct POINT
{
public int x;
public int y;
};
[DllImport(“user32.dll”)]
static extern bool GetCursorPos(out POINT point);
Еще пара полезных функций (поиск окна и получение его положения):
[DllImport(“user32.dll”, SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport(“user32.dll”)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
};
Direct link
07.06.08
Tags: Программирование / 7:45 pm , Victor Laskin
Водится за мной такой недостаток, люблю изобрести велосипед… Временами это плохо отражается на результате, но ничего не могу с собой поделать. С другой стороны, иногда, велосипед дорабатывается до мощного мотоцикла…
Недавно делал локализацию (поддержку многих языков в приложении) и понял что делал ее неверно, даже несмотря на то что с самого начала разработки софта продумал как она будет сделана. Казалось бы, что может быть проще, но только теперь для меня стало понятно как она должна выглядеть. Можно уложить это в небольшой список рекомендаций:
Структура:
- Локализованные (переведённые) строки должны храниться во внешнем файле открытого формата (txt или xml например)
- Новый язык нужно мочь подключать без перекомпиляции кода
- Приложение должно уметь на любом этапе исполнения переключать язык, перечитать строки из файла и “перерисовать” весь интерфейс
- Любая функция по выводу текста должна вызывать функцию вида GetLocalText(string Token), где токен - идентификатор выводимой строчки
- Необязательно: Хорошо бы разбить строки по группам и написать маленькую утилитку для их быстрого редактирования и перевода.
Для чего все это нужно, если есть стандартные методы локализации? Не вижу смысла в файлах ресурсов, в формате непонятном простым смертным пользователям, которые могут захотеть перевести ваш продукт на свой язык. Любой пользователь должен уметь перевести интерфейс и видеть изменения, которые он делает, сразу в интерфейсе, без перекомпиляции и перезапусков. Конечно лучше воспользоваться услугами профессиональных переводчиков, но это не всегда реально.
Актуальны еще рекомендации по языку ресурсных строчек, которые можно найти в MSDN.
Язык:
- Не разбивайте фразы на куски, переводчику будет трудно понять как именно эти куски переводить
- Аналогично нельзя использовать отдельно многозначные термины или слова, которые могут быть глаголом и существительным одновременно
- Учтите, что при переводе размер надписей может увеличиться процентов на 50-75%. Это самая существенная проблема в компактных интерфейсах.
Эти проблемы как раз и призвана решить возможность оперативного просмотра результатов своей работы переводчиком.
Direct link
01.06.08
Tags: .Net 2.0, Программирование / 4:18 pm , Victor Laskin
Оказывается метод, который возвращает список директорий (GetDirectories) иногда может их не сортировать. Вроде как это происходит на винтах под FATом. Поэтому если Вы где-то визуализируете список директорий, то рекомендую Вам вставить туда алгоритм ручной сортировки, ибо сделать это легко с помощью Array.Sort:
DirectoryInfo[] dirs = dir.GetDirectories();
//Сортировочка:
Array.Sort(dirs, 0, dirs.Length, new DirectorySort());
Сам принцип сортировки нужно оформить ввиде класса реализующего интерфейс IComparer:
class DirectorySort : System.Collections.IComparer
{
public int Compare(object x, object y)
{
DirectoryInfo d1 = x as DirectoryInfo;
DirectoryInfo d2 = y as DirectoryInfo;
return String.Compare(d1.Name, d2.Name, true, CultureInfo.CurrentCulture);
}
}
Сортировка тут не различает заглавные-прописные буквы и учитывает CurrentCulture.
Direct link