Министерство образования Республики Беларусь
ПОЛОЦКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
Кафедра вычислительных систем и сетей
Методические указания для выполнения лабораторной работы №2 по курсу «Операционные системы и системное программирование»
Часть 2
Вариант 23
«Создание графического интерфейса пользователя с использованием Win32 API»
Выполнил:
Винник Алесей Александрович
10-ИТ-2
Проверил:
Тычина Сергей Григорьевич
Полоцк, 2011
Цель работы
Получить навыки по созданию графического пользовательского интерфейса средствами Win32 API.
Условие задания
Создание SDI приложения с функциями просмотра процессов Windows и подгруженных к нем DLL. Т.е. в левой части имеется дерево процессов. В правой части в виде стандартного списка подгруженные DLL в зависимости от выбранного процесса в левой части. Левая и правая часть разделяются элементом «сплитер».
ЛИСТИНГ ПРОГРАММЫ:
#include "stdafx.h"
#include "laba2.h"
#define MAX_LOADSTRING 100
#define LEFT_SPLIT_FRAME TEXT("LEFT_SPLIT_FRAME")
#define RIGHT_SPLIT_FRAME TEXT("RIGHT_SPLIT_FRAME")
#define SPLIT_WIDTH 4
#define SPLIT_START_POS 200
#define WM_GETDLL WM_USER + 100
// Глобальные переменные:
HINSTANCE hInst; // текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка
TCHAR szWindowClass[MAX_LOADSTRING]; // имя класса главного окна
HANDLE hSnap;
// Отправить объявления функций, включенных в этот модуль кода:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK LeftWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK RightWndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: разместите код здесь.
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
MSG msg;
HACCEL hAccelTable;
// Инициализация глобальных строк
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_LABA2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Выполнить инициализацию приложения:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_LABA2));
// Цикл основного сообщения:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// ФУНКЦИЯ: MyRegisterClass()
//
// НАЗНАЧЕНИЕ: регистрирует класс окна.
//
// КОММЕНТАРИИ:
//
// Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код
// был совместим с системами Win32, не имеющими функции RegisterClassEx'
// которая была добавлена в Windows 95. Вызов этой функции важен для того,
// чтобы приложение получило "качественные" мелкие значки и установило связь
// с ними.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
ATOM res;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LABA2));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_LABA2);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
res = RegisterClassEx(&wcex);
wcex.lpfnWndProc = LeftWndProc;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszClassName = LEFT_SPLIT_FRAME;
RegisterClassEx(&wcex);
wcex.lpfnWndProc = RightWndProc;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszClassName = RIGHT_SPLIT_FRAME;
RegisterClassEx(&wcex);
return res;
}
//
// ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
// НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
// КОММЕНТАРИИ:
//
// В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
// создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// НАЗНАЧЕНИЕ: обрабатывает сообщения в главном окне.
//
// WM_COMMAND - обработка меню приложения
// WM_PAINT -Закрасить главное окно
// WM_DESTROY - ввести сообщение о выходе и вернуться.
//
//
VOID ResizeSpliterFrms(HWND hWndMain, HWND hWndLeft, HWND hWndRight, INT nSplitPos)
{
RECT rect;
GetWindowRect(hWndMain, &rect);
MoveWindow(hWndLeft, 0,
0,
nSplitPos,
rect.bottom - rect.top - 60,
TRUE);
MoveWindow(hWndRight, nSplitPos + SPLIT_WIDTH,
0,
rect.right - (rect.left + nSplitPos + SPLIT_WIDTH)-16,
rect.bottom - rect.top - 60,
TRUE);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static HWND shWndLeftFrm, shWndRightFrm;
static INT snWidthT, snHeightT, snSplitPos = SPLIT_START_POS;
RECT rect;
switch (message)
{
case WM_CREATE:
{
GetWindowRect(hWnd,&rect);
shWndLeftFrm = CreateWindowEx(WS_EX_CLIENTEDGE, LEFT_SPLIT_FRAME, NULL,
WS_CHILD | WS_VISIBLE, 0, 0, snSplitPos, rect.bottom-rect.top-60, hWnd, NULL, hInst, NULL);
shWndRightFrm = CreateWindowEx(WS_EX_CLIENTEDGE, RIGHT_SPLIT_FRAME, NULL,
WS_CHILD | WS_VISIBLE, snSplitPos+SPLIT_WIDTH, 0, rect.right-(rect.left+snSplitPos+SPLIT_WIDTH)-16, rect.bottom-rect.top-60, hWnd, NULL, hInst, NULL);
}
break;
case WM_SIZE:
ResizeSpliterFrms(hWnd, shWndLeftFrm, shWndRightFrm, snSplitPos);
break;
case WM_MOUSEMOVE:
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
if (wParam == MK_LBUTTON)
{
snSplitPos = LOWORD(lParam);
ResizeSpliterFrms(hWnd, shWndLeftFrm, shWndRightFrm, snSplitPos);
}
break;
case WM_LBUTTONUP:
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
break;
case WM_LBUTTONDOWN:
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Разобрать выбор в меню:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_GETDLL:
SendMessage(shWndRightFrm, WM_GETDLL, wParam, (INT)lParam);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код отрисовки...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
HTREEITEM InsertToTreeView(HWND hWndTreeView, HTREEITEM hItemParent, LPCTSTR lpctzText, LPARAM lParam)
{
HTREEITEM hItem;
TVINSERTSTRUCT tvInsertStruct;
ZeroMemory(&tvInsertStruct, sizeof(TVINSERTSTRUCT));
tvInsertStruct.hParent = hItemParent;
tvInsertStruct.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
tvInsertStruct.item.pszText = (LPTSTR)lpctzText;
tvInsertStruct.item.cchTextMax = lstrlen(lpctzText);
tvInsertStruct.item.iImage = 0;
tvInsertStruct.item.iSelectedImage = 1;
tvInsertStruct.item.lParam = lParam;
hItem = TreeView_InsertItem(hWndTreeView, &tvInsertStruct);
return hItem;
}
LRESULT CALLBACK LeftWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static HWND shWndTreeView;
INT count = 0;
switch (message)
{
case WM_CREATE:
shWndTreeView = CreateWindow(WC_TREEVIEW, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES, 0, 0, 100, 100, hWnd,
(HMENU)IDC_TREEVIEW, hInst, NULL);
if (shWndTreeView)
{
HIMAGELIST himl = ImageList_Create(16, 16, 0, 2, 0);
ImageList_Add(himl, LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1)), NULL);
ImageList_Add(himl, LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP2)), NULL);
TreeView_SetImageList(shWndTreeView, himl, TVSIL_NORMAL);
PROCESSENTRY32 proc;
proc.dwSize = sizeof(PROCESSENTRY32);
TCHAR tzProcName[MAX_PATH];
if (Process32First(hSnap, &proc))
{
do
{
wcscpy(tzProcName, proc.szExeFile);
count++;
InsertToTreeView(shWndTreeView, NULL, tzProcName, (LPARAM)count-1);
}while(Process32Next(hSnap, &proc));
}
}
break;
case WM_SIZE:
MoveWindow(shWndTreeView, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_MOUSEMOVE:
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
if (wParam == MK_LBUTTON)
{
SendMessage(GetParent(hWnd), WM_MOUSEMOVE, wParam, lParam);
}
else
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR) lParam;
if (pnmh->hwndFrom == shWndTreeView)
{
switch (pnmh->code)
{
case TVN_SELCHANGED:
{
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*) lParam;
SendMessage(GetParent(hWnd), WM_GETDLL, NULL, pnmtv->itemNew.lParam);
}
}
}
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код отрисовки...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK RightWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static HWND shWndListView;
switch (message)
{
case WM_CREATE:
shWndListView = CreateWindow(WC_LISTVIEW, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
WS_HSCROLL | LVS_REPORT, 0, 0, 100, 100, hWnd, (HMENU)IDC_LISTVIEW, hInst, NULL);
{
LVCOLUMN lvColumn;
ZeroMemory(&lvColumn, sizeof(LVCOLUMN));
lvColumn.mask = LVCF_WIDTH | LVCF_TEXT;
lvColumn.cx = 600;
lvColumn.pszText = TEXT("DLL Name");
lvColumn.cchTextMax = lstrlen(lvColumn.pszText);
ListView_InsertColumn(shWndListView, 0, &lvColumn);
}
break;
case WM_SIZE:
MoveWindow(shWndListView, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_NOTIFY:
break;
case WM_GETDLL:
{
ListView_DeleteAllItems(shWndListView);
INT numProc = (INT)lParam;
INT count=0;
LVITEM lvItem;
PROCESSENTRY32 proc;
proc.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnap, &proc))
{
do
{
if (count == numProc)
{
HANDLE hSnapModules = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc.th32ProcessID);
MODULEENTRY32 modules;
modules.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hSnapModules,&modules))
{
do
{
if (wcsstr(modules.szModule,TEXT(".dll")))
{
ZeroMemory(&lvItem, sizeof(LVITEM));
lvItem.mask = LVIF_TEXT | LVIF_PARAM;
lvItem.pszText = modules.szModule;
lvItem.cchTextMax = lstrlen(modules.szModule);
ListView_InsertItem(shWndListView, &lvItem);
}
}while(Module32Next(hSnapModules, &modules));
}
}
count++;
}while((Process32Next(hSnap, &proc)) && (count <= numProc));
}
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код отрисовки...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}