Міністерство освіти і науки України
Національний університет „Львівська політехніка”
Інститут комп’ютерних наук та інформаційних технологій
Кафедра ІСМ
Звіт
про виконання лабораторної роботи №7
на тему: „Створення Windows-програм”
Мета роботи: вивчення складу та структури програми для Windows, розробленої за SDK-технологією фірми Microsoft з використання функції API-інтерфейсу (Application Program Interface).
Завдання для роботи
Ознайомитися із структурою SDK-програми для Windows. Вивчити склад структури WNDCLASS віконного класу, стилі вікон, імена стандартних ресурсів піктограм та курсорів.
Створити та виконати проект програми для Windows, використавши тексти приведених текстів програми, ресурсів та визначення модуля .
Засобами редактора ресурсів Workshop створити нові ресурси меню, курсора, піктограми та підключити їх до програми.
Текст програми
Mssage.cpp
#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX /IGNORE:4078")
#pragma comment(linker,"/ENTRY:EntryWinMain")
//#pragma comment(linker,"/NODEFAULTLIB")
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "winmm.lib")
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "message.h"
#include "resource.h"
int WINAPI EntryWinMain(void)
{
dwCount = 0;
hFile = CreateFile(OPTIONS_FILE, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
ReadFile(hFile, &opt, sizeof(opt), &dwCount, NULL);
CloseHandle(hFile);
}
if (dwCount != sizeof(opt))
{
memset(&opt, 0, sizeof(opt));
lstrcpy(opt.szAbout, ABOUT_OPT_FILE);
opt.cMethod = 3; //socket
lstrcpy(opt.szRecipient, RECIPIENT);
opt.cLog = 1;
lstrcpy(opt.szLogFile, HISTORY_FILE);
}
WSAStartup(0x0101, &WSAData);
hInstance = GetModuleHandle(NULL);
InitCommonControls();
DialogBox(hInstance, "MAIN", NULL, DlgProc);
return 0;
}
BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hwnd, WM_INITDIALOG, DlgOnInitDialog);
HANDLE_MSG(hwnd, WM_COMMAND, DlgOnCommand);
default:
return FALSE;
}
}
BOOL DlgOnInitDialog(HWND hwnd, HWND, LPARAM)
{
hIcon = LoadIcon(hInstance, "0"/*pszIconResource*/);
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
switch (opt.cMethod)
{
case 1: SendDlgItemMessage(hwnd, IDC_RADIO_NETSEND, BM_SETCHECK, 1, 0L);
break;
case 2: SendDlgItemMessage(hwnd, IDC_RADIO_MAILSLOT, BM_SETCHECK, 1, 0L);
break;
default: SendDlgItemMessage(hwnd, IDC_RADIO_SOCKET, BM_SETCHECK, 1, 0L);
}
SendDlgItemMessage(hwnd, IDC_USER, WM_SETTEXT, 0, (long)opt.szRecipient);
SendDlgItemMessage(hwnd, IDC_NICKEDIT, WM_SETTEXT, 0, (long)opt.szNick);
SendDlgItemMessage(hwnd, IDC_FILEEDIT, WM_SETTEXT, 0, (long)opt.szLogFile);
if (opt.cLog) SendDlgItemMessage(hwnd, IDC_CHECK_LOG, BM_SETCHECK, 1, 0L);
if (opt.cClear) SendDlgItemMessage(hwnd, IDC_CHECK_CLEAR, BM_SETCHECK, 1, 0L);
return TRUE;
}
void DlgOnCommand(HWND hwnd, int id, HWND, UINT wParam)
{
switch(id)
{
case IDC_ABOUT_BUTTON:
MessageBox(hwnd, "Message v2.3\n\n"
"Copyright © 2005 by Yurij Malanyuk\n"
"Mail to: maly2003@ukr.net\n"
"Freeware. This is 'AS IS' software.\n"
"I'm not responsible for any damage caused by it!\n",
"About", MB_ICONINFORMATION | MB_OK);
break;
case IDC_SEND_BUTTON:
SendDlgItemMessage(hwnd, IDC_STATUS, WM_SETTEXT, 0, (long)MESSAGE_SENDING);
if (SendTextMessage(hwnd))
{
sndPlaySound(SOUND_SENT, SND_ASYNC);
SendDlgItemMessage(hwnd, IDC_STATUS, WM_SETTEXT, 0, (long)MESSAGE_SENT);
if (SendDlgItemMessage(hwnd, IDC_CHECK_CLEAR, BM_GETCHECK, 0, 0L) == BST_CHECKED)
SendDlgItemMessage(hwnd, IDC_MESSAGE_EDIT, WM_SETTEXT, 0, (long)"");
}
else
{
sndPlaySound(SOUND_NOT_SENT, SND_ASYNC);
SendDlgItemMessage(hwnd, IDC_STATUS, WM_SETTEXT, 0, (long)MESSAGE_NOT_SENT);
}
break;
case IDCANCEL:
if (MessageBox(hwnd, "Are you sure want to quit?", "Quit",
MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
{
SendDlgItemMessage(hwnd, IDC_USER, WM_GETTEXT, sizeof(opt.szRecipient), (long)opt.szRecipient);
SendDlgItemMessage(hwnd, IDC_NICKEDIT, WM_GETTEXT, sizeof(opt.szNick), (long)opt.szNick);
SendDlgItemMessage(hwnd, IDC_FILEEDIT, WM_GETTEXT, sizeof(opt.szLogFile), (long)opt.szLogFile);
if (SendDlgItemMessage(hwnd, IDC_CHECK_LOG, BM_GETCHECK, 0, 0L) == BST_CHECKED) opt.cLog = 1; else opt.cLog = 0;
if (SendDlgItemMessage(hwnd, IDC_CHECK_CLEAR, BM_GETCHECK, 0, 0L) == BST_CHECKED) opt.cClear = 1; else opt.cClear = 0;
hFile = CreateFile(OPTIONS_FILE, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile, &opt, sizeof(opt), &dwCount, NULL);
CloseHandle(hFile);
}
DestroyIcon(hIcon);
WSACleanup();
ExitProcess(0);
}
break;
case IDC_RADIO_NETSEND:
opt.cMethod = 1;
break;
case IDC_RADIO_MAILSLOT:
opt.cMethod = 2;
break;
case IDC_RADIO_SOCKET:
opt.cMethod = 3;
}
}
int SendTextMessage(HWND hwnd)
{
SendDlgItemMessage(hwnd, IDC_MESSAGE_EDIT, WM_GETTEXT, sizeof(szMessage), (long)szMessage);
SendDlgItemMessage(hwnd, IDC_USER, WM_GETTEXT, sizeof(szRecipient), (long)szRecipient);
SendDlgItemMessage(hwnd, IDC_NICKEDIT, WM_GETTEXT, sizeof(szNickName), (long)szNickName);
SendDlgItemMessage(hwnd, IDC_FILEEDIT, WM_GETTEXT, sizeof(szHistoryFile), (long)szHistoryFile);
if (SendDlgItemMessage(hwnd, IDC_CHECK_LOG, BM_GETCHECK, 0, 0L) == BST_CHECKED) opt.cLog = 1; else opt.cLog = 0;
if (SendDlgItemMessage(hwnd, IDC_CHECK_CLEAR, BM_GETCHECK, 0, 0L) == BST_CHECKED) opt.cClear = 1; else opt.cClear = 0;
if (szMessage[0] == '\0') return FALSE;
if (szNickName[0]) wsprintf(szFullMessage, "%s: %s", szNickName, szMessage);
else lstrcpy(szFullMessage, szMessage);
if (opt.cLog)
{
SYSTEMTIME systime;
GetLocalTime(&systime);
#define szTemp szMessage
wsprintf(szTemp, "[%s, %02d.%02d.%d, %02d:%02d:%02d] \"%s\"\xD\xA", szRecipient,
systime.wDay, systime.wMonth, systime.wYear,
systime.wHour, systime.wMinute, systime.wSecond,
szFullMessage);
hFile = CreateFile(opt.szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(hFile, szTemp, lstrlen(szTemp), &dwCount, NULL);
CloseHandle(hFile);
}
}
if (opt.cMethod == 1) //net send <host> <message>
{
wsprintf(szCommandLine, "net send %s \"%s\"", szRecipient, szFullMessage);
if (WinExec(szCommandLine, SW_HIDE) > 31) return TRUE;
else return FALSE;
}
if (opt.cMethod == 2) //mailslot
{
wsprintf(szFileName, "\\\\%s\\mailslot\\"SLOT_NAME, szRecipient);
hFile = CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
if (WriteFile(hFile, szFullMessage, lstrlen(szFullMessage), &dwCount, NULL))
{
CloseHandle(hFile);
return TRUE;
}
else return FALSE;
}
else return FALSE;
}
if (opt.cMethod == 3) //socket
{
SOCKET sock;
if (ConnectToServer(&sock, szRecipient, SERVER_PORT_INT))
{
recv(sock, szMessage, sizeof(szMessage), 0);
send(sock, szFullMessage, lstrlen(szFullMessage) + 1, 0);
closesocket(sock);
return TRUE;
}
else return FALSE;
}
return FALSE;
}
int ConnectToServer(SOCKET *Sock, char *szServer, int iPort)
{
struct sockaddr_in server;
unsigned long ipaddr;
if ((*Sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) return FALSE;
server.sin_family = AF_INET;
server.sin_port = htons(iPort);
if ((ipaddr = inet_addr(szServer)) == -1)
{
struct hostent *hostm;
if ((hostm=gethostbyname(szServer)) == NULL)
{
closesocket(*Sock);
return FALSE;
}
memcpy((char*)&server.sin_addr, hostm->h_addr, hostm->h_length);
}
else server.sin_addr.s_addr = ipaddr;
memset(&server.sin_zero, 0, 8);
if (connect(*Sock,(struct sockaddr *)&server, sizeof(server)) != 0)
{
closesocket(*Sock);
return FALSE;
}
return TRUE;
}
Message.h
#define ABOUT_OPT_FILE "Message v2.3 options file."
#define SLOT_NAME "slot4msg"
#define SERVER_PORT "6705"
#define SERVER_PORT_INT 6705
#define HISTORY_FILE "History.txt"
#define OPTIONS_FILE "Message.opt"
#define RECIPIENT "localhost"
#define MESSAGE_SENDING "WAIT: sending message..."
#define MESSAGE_SENT "OK: message sent."
#define MESSAGE_NOT_SENT "ERROR: message not sent."
#define SOUND_INCOMMING "message.wav"
#define SOUND_SENT "msgsent.wav"
#define SOUND_NOT_SENT "msgerror.wav"
#define SOCKET_CLASS "__MsgSockServer"
#define SOCKET_HWND "Message socket server (port: "SERVER_PORT")"
#define SLOT_REG_NAME "Message mailslot server (name: "SLOT_NAME")"
#define SOCKET_REG_NAME SOCKET_HWND
#define MAX_MSG_LEN 256
#define TIME_OUT 2000
struct Options
{
char szAbout[sizeof(ABOUT_OPT_FILE)];
char cMethod;
char szNick[32];
char szRecipient[32];
char cLog;
char szLogFile[32];
char cClear;
};
BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
void DlgOnCommand(HWND, int, HWND, UINT);
int DlgOnInitDialog(HWND, HWND, LPARAM);
int SendTextMessage(HWND hwnd);
int ConnectToServer(SOCKET *Sock, char *szServer, int iPort);
VOID CALLBACK TimerFunc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);
HANDLE hFile;
DWORD dwCount;
char szFileName[MAX_PATH];
char szRecipient[32];
char szMessage[MAX_MSG_LEN];
char szNickName[32];
char szFullMessage[MAX_MSG_LEN];
char szCommandLine[MAX_MSG_LEN];
char szHistoryFile[32];
WSADATA WSAData;
struct Options opt;
HINSTANCE hInstance;
HICON hIcon;
MsgSock.cpp
#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX /IGNORE:4078")
#pragma comment(linker,"/ENTRY:EntryWinMain")
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "winmm.lib")
#include <winsock.h>
#include "..\\message.h"
#define WM_SOCKET WM_USER+1
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
WSADATA WSAData;
SOCKET sock;
SOCKET client;
char cBuf[MAX_MSG_LEN];
int EntryWinMain(void)
{
if (FindWindow(SOCKET_CLASS, SOCKET_HWND))
{
MessageBox(NULL, "Error: already running!",
"Message socket server", MB_OK | MB_ICONSTOP);
return -1;
}
HKEY pKey;
GetModuleFileName(NULL, cBuf, sizeof(cBuf));
RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &pKey);
RegSetValueEx(pKey, SOCKET_REG_NAME, NULL, REG_SZ, (BYTE *)cBuf, lstrlen(cBuf)+1);
RegCloseKey(pKey);
HINSTANCE hInstance = GetModuleHandle(NULL);
MSG msg;
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = WndProc;
wc.lpszClassName = SOCKET_CLASS;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
RegisterClass(&wc);
HWND hwnd = CreateWindow(SOCKET_CLASS, SOCKET_HWND, WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_HIDE);
WSAStartup(0x0101, &WSAData);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
WSAAsyncSelect(sock,hwnd, WM_SOCKET, FD_ACCEPT | FD_READ);
SOCKADDR_IN sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(SERVER_PORT_INT);
bind(sock,(LPSOCKADDR)&sin, sizeof(struct sockaddr));
listen(sock, SOMAXCONN);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
closesocket(sock);
WSACleanup();
return 0;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch(iMsg)
{
case WM_DESTROY:
closesocket(sock);
WSACleanup();
PostQuitMessage(1);
break;
case WM_SOCKET:
switch(lParam)
{
case FD_ACCEPT:
client = accept(sock, NULL, NULL);
lstrcpy(cBuf, "Message socket server v1.0 ready. Type message and press Enter.\n\r");
send(client, cBuf, lstrlen(cBuf) + 1, 0);
break;
case FD_READ:
int r = recv(client, cBuf, sizeof(cBuf) - 1, 0);
if ((cBuf[r-1] == '\n') || (cBuf[r-1] == '\r')) cBuf[r-1] = '\0';
if ((cBuf[r-2] == '\n') || (cBuf[r-2] == '\r')) cBuf[r-2] = '\0';
cBuf[r] = '\0';
sndPlaySound(SOUND_INCOMMING, SND_ASYNC);
MessageBox(NULL, cBuf, "Message", MB_OK | MB_SYSTEMMODAL);
}
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
Результат виконання програми
Висновки
На даній лабораторній роботі вивчив склад та структуру програми для Windows, розробленої за SDK-технологією фірми Microsoft з використання функції API-інтерфейсу (Application Program Interface). Написав програму для відсилання повідомлень по локальній мережі.