Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» C++ WinAPI

Автор: alamar5
Дата сообщения: 03.03.2010 15:52
RedPromo
Спасибо за пример.
Но в нем все необходимые отступы и размеры формируются вручную с использованием неких констант (зазор в 2 пиксела и т.п).
Ну ладно, когда темы нет, там по части координат всё достаточно жестко и неизменно и не ошибешься.

А при рисовании с использованием темы, например, той же темы Aero в Win7, кнопки могут рисоваться как внутри заголовка (виртуальная Win7 под VMWare Workstation 6.5, 3D в виртуальной машине не поддерживается), так и выходить на его край (обычная, "невиртуальная" Win7, 3D есть).
Т.е., получается, что координаты прямоугольника кнопки тут должны как-то по-другому вычисляться.

Я понимаю, в принципе (при отсутствии 3D), в Win7 можно теми же эмпирическими (во всяком случае, недокументированными) константами пользоваться, т.к. схема размещения кнопок вроде бы совпадает с тем, что делается в WinXP.

Но, всё равно, по сути выходит, что иначе, чем задавать смещения вручную, никак и не сделать?

Автор: RedPromo
Дата сообщения: 03.03.2010 16:25
alamar5
Да формирование размеров кнопок задается темой и получить эти размеры можно но отступы скорее всего прийдется через константы. Хотя может искать TopLeft от нижней части Caption тогда согласно размерам вылезет хоть за край.
[more=Можно еще посмотреть эту функцию]
Код: BOOL
PaintThemeCaptionMaxButtonNormal(
IN CONST HWND hWnd,
IN CONST HDC hDC,
IN CONST POINT ptTopLeft
)
{
BOOL bRet = FALSE;
if (hWnd && hDC)
{
HTHEME hTheme = OpenThemeData(hWnd, L"WINDOW");
if (hTheme)
{
SIZE sz;
if (S_OK == GetThemePartSize(
hTheme, hDC, WP_MAXBUTTON, MAXBS_NORMAL,
NULL, TS_TRUE, &sz))
{
RECT rc;
if (SetRect(&rc, 0, 0, sz.cx, sz.cy) &&
OffsetRect(&rc, ptTopLeft.x, ptTopLeft.y))
{
bRet = (S_OK == DrawThemeBackground(hTheme,
hDC,
WP_MAXBUTTON, MAXBS_NORMAL, &rc, &rc));
}
}
CloseThemeData(hTheme);
}
}
return bRet;
}
Автор: alamar5
Дата сообщения: 03.03.2010 17:17
RedPromo
В этой ф-ции всё строится на том, что координаты кнопки передаются извне в качестве параметра. Причем GetThemePartSize выдает размер кнопки по умолчанию (у меня 20х20 пикселов) и это значение не зависит от пользовательских настроек.
Чтобы получить реальный размер кнопки, можно вызвать GetThemePartSize с параметром TS_DRAW, задав в качестве входного пр-ка 0,0,GetSystemMetrics(SM_CXSIZE),GetSystemMetrics(SM_CYSIZE).
Если GetSystemMetrics выдает размер кнопки 20х20, то на выходе GTPS получим пр-к 2,2,18,18. Что, вроде бы, и надо, но у меня под WinXP это работает, а под Win7 нет. Там выходной пр-к совпадает со входным и нужные отступы так не получить.

В общем, похоже, что иначе, чем через константы, не сделать.
Ни GetThemeMargins, ни GetThemePosition, ни GetThemeRect для кнопок в заголовке не работают.
Может, что-то через GetThemeInt (или типа того) можно выжать, пока не знаю. Инфы-то практически нет.
Автор: RedPromo
Дата сообщения: 03.03.2010 18:04
alamar5
Понял проблема закралась в Windows 7 в работе функций Theme.
Автор: alamar5
Дата сообщения: 03.03.2010 19:54
RedPromo
Насчет тем Windows я по ходу нашел вот такую статью.
Для меня, во всяком случае, она хоть как-то по полочкам тему раскладывает.

Автор: RedPromo
Дата сообщения: 03.03.2010 22:10
alamar5
Интересно Демонстрационное приложение для исследования Visual Styles API.
Затра проверю какие параметры оно мне выдает на Win7 размера buttons caption.
Автор: RedPromo
Дата сообщения: 04.03.2010 14:55
alamar5
У меня программа выдает адеватные правильные размеры согласно текущему стилю на Вин7
[more=Информация]
Текущий хэндл данных темы
Класс окна: window
Код элемента: 18 (WP_CLOSEBUTTON)
Код состояния: 0 (Состояние не определено)
Элемент определён в данном состоянии
Элемент имеет прозрачные или полупрозрачные участки
Элемент имеет минимально допустимый размер, равный (1x1)
Элемент имеет оптимальный размер, равный (28x17)

Текущий хэндл данных темы
Класс окна: window
Код элемента: 17 (WP_MAXBUTTON)
Код состояния: 0 (Состояние не определено)
Элемент определён в данном состоянии
Элемент имеет прозрачные или полупрозрачные участки
Элемент имеет минимально допустимый размер, равный (1x1)
Элемент имеет оптимальный размер, равный (5x17)

Текущий хэндл данных темы
Класс окна: window
Код элемента: 15 (WP_MINBUTTON)
Код состояния: 0 (Состояние не определено)
Элемент определён в данном состоянии
Элемент имеет прозрачные или полупрозрачные участки
Элемент имеет минимально допустимый размер, равный (1x1)
Элемент имеет оптимальный размер, равный (5x17)
[/more]
Автор: alamar5
Дата сообщения: 04.03.2010 17:40
RedPromo
Различие, возможно, объясняется тем, что у меня Win7 виртуальная и в ней под VMWare 6.5, как я говорил, неклиентская область (в т.ч. заголовок) окна рисуется не так, как в обычной. В VMWare Workstation 7 всё, возможно, будет рисоваться как положено, но у меня ее пока нет.

Сейчас, под VMWare 6.5 у меня GetThemePartSize для кнопок выдает (при минимальной выставленной в настройках виртуальной Win7 высоте заголовка, 20, кажется) размер 35х21, а реальный размер кнопки 31х15 (т.е., отступы совсех сторон по 2 пиксела).

А что за демонстрационное приложение?
Автор: RedPromo
Дата сообщения: 04.03.2010 18:50
alamar5
Демонстрационное приложение для исследования Visual Styles API и его исходные тексты (Delphi). Исходные тексты также включают в себя пример работы с Microsoft XML 2.0. Отмечу, что в силу природной лени я не определил полностью все константы для элементов и состояний, но Вы всегда можете либо доработать это приложение, либо создать и дополнить XML-документ, определяющий схему визуального стиля. Загрузить >>>.
Автор: alamar5
Дата сообщения: 15.03.2010 17:28
RedPromo
Спасибо. Но я, в итоге, решил оствить это рисование Windows. Я думал, можно относительно простыми средствами (вызовами Theme-функций) получить расположение кнопок.
Я решил, что эта нестандартная рамка будет рисоваться только в случае, когда выбрана классическая тема WinXP, т.е., когда размер и расположение кнопок хорошо предсказуемы.

У меня сейчас другой вопрос.
Для случая, когда рисуется эта нестандартная тонкая рамка, системное меню (меню окна) получается расположенным внутри клиентской области (со сдвигом по диагонали на пару пикселов, но тем не менее).
Чтобы оно располагалось вплотную к левому верхнему краю клиентской области, в обработчике WM_NCLBUTTONDOWN делаю следующее:

Код:
POINT pt = { 0, 0 };
ClientToScreen(hWnd, &pt);
int sys_cmd = TrackPopupMenuEx(
GetSystemMenu(hWnd, FALSE),
TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD|TPM_NONOTIFY, pt.x, pt.y, hWnd, NULL);
if (sys_cmd) PostMessage(hWnd, WM_SYSCOMMAND, sys_cmd, 0);
Автор: CruelCrow
Дата сообщения: 14.04.2010 21:14
Возможно ли выполнить JS/VBScript прямо из памяти, не записывая временный файл на диск для передачи его потом параметром wscript.exe через system() или CreateProcess()?
Автор: vlary
Дата сообщения: 06.07.2010 21:32
Всем доброе время суток!
Написал некое десктопное приложение, которое собирает некоторую информацию в сети, визуализирует ее и пишет лог. При нажатии кнопки или меню запускает с помощью CreateProcess() notepad.exe с параметром в виде имени файла лога.
При работе на локальном компьютере блокнот с содержимым лога без проблем возникает на экране.
Однако, при ее работе в терминальной сессии на 2003 сервере (для этого, собственно, и предназначалась), ничего при нажатии кнопки не происходит.
Каким образом запустить блокнот из программы, чтобы это работало и в терминальной сессии?
Автор: ShIvADeSt
Дата сообщения: 07.07.2010 01:55
vlary
ИМХО ShellExecute более в тему.
Автор: vlary
Дата сообщения: 07.07.2010 09:44
ShIvADeSt ShellExecute тоже пробовал. Результат аналогичный, на компе все работает, в терминалке - нет.
Автор: ShIvADeSt
Дата сообщения: 07.07.2010 10:58
vlary
Приведи код запуска, попробую у себя.
Автор: vlary
Дата сообщения: 07.07.2010 13:13
ShIvADeSt Все, отбой! Дело оказалось в функции GetWindowsDirectory(), которая в терминалке возвращает отнюдь не директорию Виндовс, поэтому блокнота в том месте, где я его рассчитывал найти, просто не было. Добавил проверку на работу в терминале по GetSystemMetrics( SM_REMOTESESSION ), скорректировал путь к директории Виндовс, убрав лишнее, после этого все заплясало.
Автор: ShIvADeSt
Дата сообщения: 07.07.2010 14:38
vlary
При ShellExecute вообще не надо заботиться о поиске блокнота - операционка сама должна определить приложение для открытия файла.
Автор: vlary
Дата сообщения: 07.07.2010 14:57
ShIvADeSt
Цитата:
При ShellExecute вообще не надо заботиться о поиске блокнота
Да я знаю... Просто при замене CreateProcess на ShellExecute оставил тот же полный пункт к блокноту. Ну и не прокатило.
Автор: getwellsoon
Дата сообщения: 11.07.2010 13:30
Дурацкий вопрос - при использовании функции WriteFile для записи в файл на диске, надо ли проверять возвращенный параметр с информацией о количестве реально записанных данных? Или в данном случае это совершенно излишне?
Автор: Abs62
Дата сообщения: 11.07.2010 14:12
getwellsoon
Ну, если важно знать, что всё записалось нормально, то надо проверять. А если наплевать, записалось или нет, то не надо.
Автор: getwellsoon
Дата сообщения: 12.07.2010 14:01
Abs62

Ну, функция и так сообщает была ли ошибка. Так как функция универсальная, то количество записанных байтов, возможно, актуально для каких-то случаев типа записи в мейлслот или в пайп, а вот при записи в файл я подумал, что может и не бывает такого случая как частичная запись данных без наличия сообщения об ошибке.
Автор: Garrett
Дата сообщения: 12.07.2010 14:24
getwellsoon
Не будет никакого сообщения об ошибке. Хочешь сообщение - проверяй результат функции, если ошибка(зеро), то получи сообщение через FormatMessage.
Автор: Andrey32
Дата сообщения: 05.10.2010 20:37
Мне нужно окно (окно верхнего уровня), размеры которого нельзя изменить.
Я это делаю через отлов WM_SIZING. Но еще остается возможность развертывания окна. Как деактивировать кнопку развертывания?
Автор: Abs62
Дата сообщения: 05.10.2010 20:52
Andrey32

Цитата:
Как деактивировать кнопку развертывания?

Не ставить соответствующий стиль окна при его создании - WS_MAXIMIZEBOX.
Автор: Andrey32
Дата сообщения: 05.10.2010 21:10
У меня стиль - WS_OVERLAPPEDWINDOW.

Цитата:
Не ставить соответствующий стиль окна при его создании - WS_MAXIMIZEBOX.

Вот так: ^WS_MAXIMIZEBOX ?
Автор: Abs62
Дата сообщения: 05.10.2010 21:20
Andrey32

Цитата:
У меня стиль - WS_OVERLAPPEDWINDOW

WS_OVERLAPPEDWINDOW - это комбинация стилей WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX.
Можно самому нужные стили скомбинировать, можно в WS_OVERLAPPEDWINDOW ненужный затереть.
Вроде (WS_OVERLAPPEDWINDOW)&(~WS_MAXIMIZEBOX) (Это на C/C++). Как удобнее.
Автор: Andrey32
Дата сообщения: 05.10.2010 21:33
Попробовал, ^WS_MAXIMIZEBOX работает. Комбинация это -"|" , "или"; убрать из комбинации - "^", "исключающее или". На С, /++.
Спасибо большое. Я сейчас только воткнул, что стили- это всего лишь набор битов, комбинируемых с помощью |. На WinAPI недавно пробую писать.
Автор: stazher
Дата сообщения: 05.12.2010 11:16
Всем привет!
Хочу программно найти и завершить процесс "proga.exe" с помощью tlhelp32.h и вот такого кода (Borland C++):


Код:
#include <windows.hpp>
#include <sysutils.hpp>
#include <tlhelp32.h>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
    //создаётся снимок состояния системы
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    HANDLE hProcess;
    //параметр TH32CS_SNAPPROCESS означает, что мы хотим узнать
    //только информацию о процессах
    bool Result = true;
    bool Find = false;
    //опишем структуру, в которой будет храниться эта информация
    PROCESSENTRY32 *ProcEntry = new PROCESSENTRY32();
    char* FileName;
    //Поиск запущенной программы "proga.exe"
    Result = Process32First(hSnapshot, ProcEntry);
    FileName = ExtractFileName(ProcEntry->szExeFile).c_str();
    if(FileName == "proga.exe")
    {
        hProcess = OpenProcess(PROCESS_TERMINATE, false, ProcEntry->th32ProcessID);
        //Программа найдена
        Find = true;
        //Вырубаем ее
        if(TerminateProcess(hProcess, 0)) //Ok
        {
            delete ProcEntry;
            //выгрузим из памяти системный снимок
            CloseHandle(hSnapshot);
            exit(0);
        }
        else
        {
            MessageBox(0,"Не удалось завершить-1",0,MB_OK);
        }
    }
    //Вызываемые функции - булевские. Поэтому, когда вернется false,
    //значит, информации боьше нет. => можно использовать цикл
    while(Result)
    {
        Result = Process32Next(hSnapshot, ProcEntry);
        if(Result)
        {
            FileName = ExtractFileName(ProcEntry->szExeFile).c_str();
            if(FileName == "proga.exe")
            {
                hProcess = OpenProcess(PROCESS_TERMINATE, false, ProcEntry->th32ProcessID);
                //Программа найдена
                Find = true;
                //Вырубаем ее
                    if(TerminateProcess(hProcess, 0)) //Ok
                    {
                        delete ProcEntry;
                        //выгрузим из памяти системный снимок
                        CloseHandle(hSnapshot);
                        exit(0);
                    }
                    else
                    {
                        MessageBox(0,"Не удалось завершить-2",0,MB_OK);
                    }
            }
        }
    }
    if(!Find) //Программа не найдена
    {
        MessageBox(0,"Программа не найдена",0,MB_OK);
    }
    return 0;
}
Автор: Abs62
Дата сообщения: 05.12.2010 12:21
stazher

Цитата:
PROCESSENTRY32 *ProcEntry = new PROCESSENTRY32();


Код: PROCESSENTRY32 *ProcEntry = new PROCESSENTRY32;
ProcEntry->dwSize=sizeof(PROCESSENTRY32);
Автор: stazher
Дата сообщения: 05.12.2010 14:50
Спасибо, понял, работает .

С этой прогой ещё небольшая заморочка - не хочет линковаться без runtime packages. Насколько знаю, это из-за использования AnsiString, советуется их заменять на строки char*. Но чем можно заменить функцию ExtractFileName которая AnsiString - непонятно.

Страницы: 12345678910111213141516171819202122232425262728293031323334353637

Предыдущая тема: посоветуйте книги по SQL


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.