Простой графический редактор

Автор работы: Пользователь скрыл имя, 09 Января 2013 в 09:11, курсовая работа

Описание

Цель курсового проекта: получение навыков по разработке программы на языке C\C++ , с использованием WinAPI, для реализации пользовательского интерфейса, а также реализация простенького графического редактора.
Программный продукт написан на языке программирования С++. Реализация темы курсовой работ

Содержание

Введение 4
1. Анализ задания и постановка задач 5
2. Теоретическая часть 6
3. Проектирование программы 11
4. Реализация программы 12
5. Тестирование программы 14
Заключение 21
Литература 22

Работа состоит из  1 файл

ПЗ СПО.doc

— 1.06 Мб (Скачать документ)

 

void Spray(int iDens) – обработчик инструмента «Распылитель».

Функция осуществляет генерацию точек распылителя, определение координат вывода и вывод точек на экран(лист рисования).

Функция не возвращает значений.

 

void ClearChecks() – обнуление выбора.

Функция по идентификатору обнуляет выбор размеров кисти.

В функцию не передаются значения и она не возвращает значений.

 

void ZeroMem(char* ptr, int len) – обнуление памяти.

Функция по передаваемому указателю  и длине обнуляет память.

Функция не возвращает значений.

 

bool OpenSaveDlg(bool bSave, HWND hDlg) – диалог открытия/сохранения файла.

Функция осуществляет подготовку и  вызов диалога открытия/сохранения графического файла.

В функцию передается признак сохранения. Возвращаемым значением является сам  диалог сохранения/открытия.

 

void UpdateMenuBmp(HBITMAP bmp, COLORREF clr) – обновление области рисования.

 

int __stdcall WMain() – инициализация главного окна программы.

Функция осуществляет создание главного окна программы, инициализацию заголовка  окна.

В функцию не передается параметров.

 

int __stdcall WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ) – функция вызова главного окна программы.

Функция осуществляет вызов  главного окна программы и оно  же является возвращаемым значением.

 

5. Тестирование программы

При запуске программы открывается главное окно программы(Рисунок 1). По умолчанию программа создает пустую область рисования.

Рисунок 1 – Главное  окно программы

Меню «Файл»(Рисунок 2) и его подпункты позволяют  создать графический файл, открыть  существующий, сохранить созданный  или измененный графический файл. Диалог сохранения/открытия файла приведен на рисунке 3.

Рисунок 2 – Меню «Файл»

Рисунок 3 – Диалог открытия/сохранения файла

 

Рисунок 4 позволяет увидеть  главное окно программы с загруженным  графическим файлом.

Рисунок 4 – Загруженный  файл

Меню «Правка», подпункт «Отмена» позволяет осуществить откат произведенных изменений(Рисунок 5).

Рисунок 5 – Меню «Правка->Отмена»

Меню «Цвет» позволяет  выбрать цвета пера, соответствующих  правой и левой кнопке мыши, а  также производить обмен цветами  между кнопками(Рисунок 6).

Рисунок 6 – Меню «Цвет»

Диалог выбора цвета  приведен на рисунке 7.

Рисунок 7 – Диалог выбора цвета пера

Для выбора толщины кисти  нужно воспользоваться меню «Толщина кисти»(Рисунок 8), где можно выбрать  один из множества вариантов. На рисунке 9 приведен пример всех возможных вариантов толщины кисти программы.

Рисунок 8 – Меню «Толщина кисти»

Рисунок 9 – Примеры толщин кистей

Меню «Инструменты»(Рисунок 10) позволяет выбрать один из возможных  инструментов рисования, таких как  кисть, прямоугольник, окружность, примая, а также инструменты заливки и рапылителя.

Рисунок 10 – Меню «Инструменты»

На рисунке 11 приведены  примеры всех инструментов рисования  доступных в программе.

Рисунок 11 – Примеры инструментов рисования

Для просмотра инвормации о программе надо выбрать пункт меню «О программе…»(Рисунок 12).

Рисунок 12 – Сообщение «О программе»

Для выхода из программы необходимо воспользоваться пунктом меню «Файл->Выход».

 

Заключение

В курсовом проекте была реализована программа, позволяющая  производить операции открытия, создания, редактирования и сохранения графических файлов, позволяет рисовать прямоугольники, окружности, прямые, рисовать кистью и распылителем. Поддерживаются выбираемые два цвета (фоновый и главный), смена размера кисти, загрузка картинок в формате JPG, GIF, PNG, BMP и сохранение в GIF, PNG, BMP. Были получены навыки и умения проектирования программного продукта на WinAPI.

Программа была протестирована, проверена на правильность выполнения операций: открытия, создания, редактирования и сохранения графических файлов и рисования с помощью графических примитивов.

Меню программы доступно и понятно пользователю.

 

Литература

  1. Ганеев Р. М. Проектирование интерфейса пользователя средствами Win32 API  / Р. М. Ганеев. – М. : Горячая Линия – Телеком, 2001. – 336 с.
  2. Литвиненко Н. А. – Технология программирования на C++. Win32 API-приложения.  / Н. А. Литвиненко – СПб. : БХВ-Петербург, 2010. – 288 с.
  3. Румянцев П.В. – Азбука программирования в Win32 API /П.В. Румянцев. М. : Горячая Линия - Телеком, 2004 г. 312 с.
  4. Румянцев П.В. – Работа с файлами в Win32 API / П.В. Румянцев. М. : Горячая Линия – Телеком,2002.216 с.

 

Приложение А

Функциональная  схема программы

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Приложение Б

Листинг программы

Модуль Main.cpp

#include "StdAfx.h"

#include "Main.h"

#include <math.h>

#ifdef NDEBUG

#pragma comment(linker,"/ALIGN:4096")

#pragma comment(linker,"/SUBSYSTEM:WINDOWS")

#pragma comment(linker,"/MERGE:.rdata=.text")

#pragma comment(linker,"/ENTRY:WMain")

#pragma comment(linker,"/NODEFAULTLIB")

#endif

#define CANVASWIDTH 1600

#define CANVASHEIGHT 1200

bool bDraw;

int x, y, x2, y2, x3, y3;

int px = 0, py = 0;

HBITMAP bmpBack, bmpUndo, bmpRedo, bmpForeMenu, bmpBackMenu;

HDC dcBack, dcMenuBmp, dcUndo, dcRedo, dcItemPaint;

HPEN pen;

HBRUSH brush;

wchar_t cBuf[1024];

OPENFILENAMEW ofn;

HDC dc;

int i, j;

DRAWITEMSTRUCT* disItem = NULL;

RECT rcTmp;

Gdiplus::GdiplusStartupInput gpsiGPSI;

Gdiplus::ImageCodecInfo iciArray[20];

ULONG_PTR upGDIP = 0;

Gdiplus::Bitmap* bmpLoaded;

Gdiplus::Graphics* grBack;

CHOOSECOLOR ccColor;

COLORREF crBrushColor, crBackColor, crTmp;

COLORREF ccArray[16];

char cFormat;

int iPenWidth = 3;

int iTool = 0;

HMENU mnuMain;

bool bFore = true;

int rad, dist;

HCRYPTPROV hProv;

SCROLLINFO sinfo;

 

template<typename T> int cmpstr(T* str1, T* str2, int iLen)

{

while (iLen > 0)

{

if (*str1 > *str2)

return 1;

if (*str1 < *str2)

return -1;

str1++;

str2++;

iLen--;

}

return 0;

}

 

template<typename T> void cpystr(T* dst, T* src, int iLen)

{

while (iLen > 0)

{

*dst++ = *src++;

iLen--;

}

}

 

template<typename T> int lenstr(T* str)

{

int iRes = 0;

while (*str)

{

str++;

iRes++;

}

return iRes;

}

 

void Spray(int iDens)

{

for (i = 0; i < iDens; i++)

{

CryptGenRandom(hProv, sizeof(x3), (BYTE*)&x3);

CryptGenRandom(hProv, sizeof(y3), (BYTE*)&y3);

x3 = x3 % iPenWidth;

y3 = y3 % iPenWidth;

SetPixel(dcBack, x3 + x2 + px, y3 + y2 + py, bFore ? crBrushColor : crBackColor);

SetPixel(dc, x3 + x2, y3 + y2, bFore ? crBrushColor : crBackColor);

}

}

 

void ClearChecks()

{

for (i = ID_40016; i <= ID_40028; i++)

CheckMenuItem(mnuMain, i, MF_UNCHECKED);

}

 

void ZeroMem(char* ptr, int len)

{

while (len--)

{

if (len) *ptr = 0;

ptr++;

}

}

 

bool OpenSaveDlg(bool bSave, HWND hDlg)

{

ZeroMem((char*)&ofn, sizeof(ofn));

cBuf[0] = '\0';

 

ofn.lStructSize       = sizeof(OPENFILENAMEW);

ofn.hwndOwner         = hDlg;        

ofn.hInstance         = GetModuleHandle(NULL); 

if (!bSave)

ofn.lpstrFilter = L"Картинки (*.bmp;*.jpg;*.gif;*.png)\0*.bmp;*.jpg;*.gif;*.png\0\0";

else

ofn.lpstrFilter = L"BMP\0*.bmp\0GIF\0*.gif\0PNG\0*.png\0\0";

ofn.nMaxFile          = sizeof(cBuf);

ofn.lpstrFile    = &cBuf[0];

if (bSave)

ofn.lpstrTitle    = L"Сохранить  файл";

else

ofn.lpstrTitle    = L"Открыть файл";

ofn.Flags             = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;

if (bSave)

ofn.Flags |=  OFN_OVERWRITEPROMPT;

ofn.nFilterIndex   = 1;

ofn.lpstrInitialDir   = L".\\";

 

if (bSave)

{

if (!GetSaveFileNameW(&ofn)) return false;

}

else

{

if (!GetOpenFileNameW(&ofn)) return false;

}

return true;

}

 

void UpdateMenuBmp(HBITMAP bmp, COLORREF clr)

{

HDC dcTmp = CreateCompatibleDC(dcMenuBmp);

SelectObject(dcTmp, bmp);

rcTmp.left = 0;

rcTmp.right = 16;

rcTmp.top = 0;

rcTmp.bottom = 16;

brush = CreateSolidBrush(clr);

FillRect(dcTmp, &rcTmp, brush);

FrameRect(dcTmp, &rcTmp, (HBRUSH)GetStockObject(BLACK_BRUSH));

DeleteObject(brush);

DeleteDC(dcTmp);

}

 

BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{

switch(message)

{

case WM_INITDIALOG:

dcItemPaint = GetDC(GetDlgItem(hDlg, IDC_STATICPAINT));

bmpBack = CreateCompatibleBitmap(dcItemPaint, CANVASWIDTH, CANVASHEIGHT);

bmpUndo = CreateCompatibleBitmap(dcItemPaint, CANVASWIDTH, CANVASHEIGHT);

bmpRedo = CreateCompatibleBitmap(dcItemPaint, CANVASWIDTH, CANVASHEIGHT);

dcBack = CreateCompatibleDC(dcItemPaint);

dcUndo = CreateCompatibleDC(dcBack);

dcRedo = CreateCompatibleDC(dcBack);

SelectObject(dcBack, bmpBack);

SelectObject(dcUndo, bmpUndo);

SelectObject(dcRedo, bmpRedo);

rcTmp.left = 0;

rcTmp.right = CANVASWIDTH;

rcTmp.top = 0;

rcTmp.bottom = CANVASHEIGHT;

FillRect(dcBack, &rcTmp, (HBRUSH)GetStockObject(WHITE_BRUSH));

FillRect(dcUndo, &rcTmp, (HBRUSH)GetStockObject(WHITE_BRUSH));

FillRect(dcRedo, &rcTmp, (HBRUSH)GetStockObject(WHITE_BRUSH));

Gdiplus::GdiplusStartup(&upGDIP, &gpsiGPSI, NULL);

cFormat = 'g';

crBrushColor = 0x000000;

crBackColor = 0xFFFFFF;

mnuMain = GetMenu(hDlg);

CheckMenuItem(mnuMain, ID_40013, MF_CHECKED);

CheckMenuItem(mnuMain, ID_40018, MF_CHECKED);

CheckMenuItem(mnuMain, ID_40031, MF_CHECKED);

dc = GetDC(hDlg);

bmpForeMenu = CreateCompatibleBitmap(dc, 16, 16);

bmpBackMenu = CreateCompatibleBitmap(dc, 16, 16);

dcMenuBmp = CreateCompatibleDC(dc);

ModifyMenu(mnuMain, ID_40011, MF_BITMAP, ID_40011, (LPCSTR)bmpForeMenu);

ModifyMenu(mnuMain, ID_40100, MF_BITMAP, ID_40100, (LPCSTR)bmpBackMenu);

UpdateMenuBmp(bmpForeMenu, crBrushColor);

UpdateMenuBmp(bmpBackMenu, crBackColor);

sinfo.cbSize = sizeof(sinfo);

sinfo.fMask = SIF_ALL;

sinfo.nMin = 0;

sinfo.nPage = 10;

sinfo.nPos = 0;

sinfo.nTrackPos = 0;

GetClientRect(hDlg, &rcTmp);

sinfo.nMax = CANVASWIDTH - rcTmp.right;

SetScrollInfo(hDlg, SB_HORZ, &sinfo, TRUE);

sinfo.nMax = CANVASHEIGHT - rcTmp.bottom;

SetScrollInfo(hDlg, SB_VERT, &sinfo, TRUE);

CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);

ReleaseDC(GetDlgItem(hDlg, IDC_STATICPAINT), dcItemPaint);

ReleaseDC(hDlg, dc);

return (TRUE);

case WM_CLOSE:

Gdiplus::GdiplusShutdown(upGDIP);

CryptReleaseContext(hProv, 0);

DestroyWindow(hDlg);

ExitProcess(0);

return (TRUE);

case WM_LBUTTONDOWN:

case WM_RBUTTONDOWN:

SetCapture(hDlg);

bDraw = true;

x = LOWORD(lParam);

y = HIWORD(lParam);

x3 = x;

y3 = y;

bFore = message == WM_LBUTTONDOWN;

BitBlt(dcUndo, 0, 0, CANVASWIDTH, CANVASHEIGHT, dcBack, 0, 0, SRCCOPY);

break;

case WM_LBUTTONUP:

case WM_RBUTTONUP:

if (!bDraw)

return FALSE;

ReleaseCapture();

bDraw = false;

x2 = (signed short)LOWORD(lParam);

y2 = (signed short)HIWORD(lParam);

pen = CreatePen(PS_SOLID, iPenWidth, bFore ? crBrushColor : crBackColor);

SelectObject(dcBack, pen);

SelectObject(dcBack, GetStockObject(HOLLOW_BRUSH));

switch (iTool)

{

case 0:

MoveToEx(dcBack, x + px, y + py, NULL);

LineTo(dcBack, x2 + px, y2 + py);

break;

case 1:

Rectangle(dcBack, x3 + px, y3 + py, x2 + px, y2 + py);

break;

case 2:

Ellipse(dcBack, x3 + px, y3 + py, x2 + px, y2 + py);

break;

case 3:

MoveToEx(dcBack, x3 + px, y3 + py, NULL);

LineTo(dcBack, x2 + px, y2 + py);

break;

case 4:

brush = CreateSolidBrush(bFore ? crBrushColor : crBackColor);

SelectObject(dcBack, brush);

ExtFloodFill(dcBack, x2 + px, y2 + py, GetPixel(dcBack, x2 + px, y2 + py), FLOODFILLSURFACE);

DeleteObject(brush);

break;

case 5:

Spray(iPenWidth);

break;

}

DeleteObject(pen);

InvalidateRect(GetDlgItem(hDlg, IDC_STATICPAINT), NULL, FALSE);

return TRUE;

case WM_MOUSEMOVE:

if (!bDraw)

break;

x2 = (signed short)LOWORD(lParam);

y2 = (signed short)HIWORD(lParam);

if (x2 > CANVASWIDTH - iPenWidth)

x2 = CANVASWIDTH - iPenWidth;

if (y2 > CANVASHEIGHT - iPenWidth)

y2 = CANVASHEIGHT - iPenWidth;

dc = GetDC(GetDlgItem(hDlg, IDC_STATICPAINT));

pen = CreatePen(PS_SOLID, iPenWidth, bFore ? crBrushColor : crBackColor);

SelectObject(dc, pen);

SelectObject(dcBack, pen);

switch (iTool)

{

case 0:

MoveToEx(dc, x, y, NULL);

LineTo(dc, x2, y2);

MoveToEx(dcBack, x + px, y + py, NULL);

LineTo(dcBack, x2 + px, y2 + py);

break;

case 1:

i = SetROP2(dc, R2_NOTXORPEN);

Rectangle(dc, x3, y3, x, y);

Rectangle(dc, x3, y3, x2, y2);

SetROP2(dc, i);

break;

case 2:

i = SetROP2(dc, R2_NOTXORPEN);

SelectObject(dc, GetStockObject(HOLLOW_BRUSH));

Ellipse(dc, x3, y3, x, y);

Ellipse(dc, x3, y3, x2, y2);

SetROP2(dc, i);

break;

case 3:

i = SetROP2(dc, R2_NOTXORPEN);

MoveToEx(dc, x3, y3, NULL);

LineTo(dc, x2, y2);

MoveToEx(dc, x3, y3, NULL);

LineTo(dc, x, y);

SetROP2(dc, i);

break;

case 5:

Spray(iPenWidth);

break;

}

x = x2;

y = y2;

DeleteObject(pen);

ReleaseDC(hDlg, dc);

break;

case WM_HSCROLL:

case WM_VSCROLL:

sinfo.fMask = SIF_POS | SIF_RANGE;

GetScrollInfo(hDlg, message == WM_HSCROLL ? SB_HORZ : SB_VERT, &sinfo);

switch(LOWORD(wParam))

{

case SB_PAGEUP:

i = sinfo.nPos - sinfo.nPage;

break;

case SB_PAGEDOWN:

i = sinfo.nPos + sinfo.nPage;

break;

case SB_LINEUP:

i = sinfo.nPos - 10;

break;

case SB_LINEDOWN:

i = sinfo.nPos + 10;

break;

case SB_THUMBPOSITION:

case SB_THUMBTRACK:

i = HIWORD(wParam);

break;

}

i < 0 ? i = 0 : i = i;

i > sinfo.nMax ? i = sinfo.nMax : i = i;

sinfo.fMask = SIF_POS;

sinfo.nPos = i;

SetScrollInfo(hDlg, message == WM_HSCROLL ? SB_HORZ : SB_VERT, &sinfo, TRUE);

if (message == WM_HSCROLL)

px = i;

else

py = i;

InvalidateRect(GetDlgItem(hDlg, IDC_STATICPAINT), NULL, FALSE);

return FALSE;

case WM_COMMAND:

switch (LOWORD(wParam))

{

case ID_40005:

case ID_ACCELERATOR40055:

rcTmp.left = 0;

rcTmp.right = CANVASWIDTH;

rcTmp.top = 0;

rcTmp.bottom = CANVASHEIGHT;

FillRect(dcBack, &rcTmp, (HBRUSH)GetStockObject(WHITE_BRUSH));

InvalidateRect(GetDlgItem(hDlg, IDC_STATICPAINT), NULL, FALSE);

return TRUE;

case ID_40006:

case ID_ACCELERATOR40056:

if (!OpenSaveDlg(false, hDlg)) return FALSE;

rcTmp.left = 0;

rcTmp.right = CANVASWIDTH;

rcTmp.top = 0;

rcTmp.bottom = CANVASHEIGHT;

FillRect(dcBack, &rcTmp, (HBRUSH)GetStockObject(WHITE_BRUSH));

InvalidateRect(GetDlgItem(hDlg, IDC_STATICPAINT), NULL, FALSE);

bmpLoaded = Gdiplus::Bitmap::FromFile(ofn.lpstrFile, FALSE);

grBack = Gdiplus::Graphics::FromHDC(dcBack);

grBack->DrawImage(bmpLoaded, 0, 0);

delete bmpLoaded;

delete grBack;

InvalidateRect(GetDlgItem(hDlg, IDC_STATICPAINT), NULL, FALSE);

return TRUE;

case ID_40007:

case ID_ACCELERATOR40057:

if (!OpenSaveDlg(true, hDlg)) return FALSE;

switch(ofn.nFilterIndex)

{

case 1:

if (cmpstr<wchar_t>(&ofn.lpstrFile[ofn.nFileExtension], L"bmp", 3))

cpystr<wchar_t>(&ofn.lpstrFile[lenstr(ofn.lpstrFile)], L".bmp", 4);

cFormat = 'b';

break;

case 2:

if (cmpstr<wchar_t>(&ofn.lpstrFile[ofn.nFileExtension], L"gif", 3))

cpystr<wchar_t>(&ofn.lpstrFile[lenstr(ofn.lpstrFile)], L".gif", 4);

cFormat = 'g';

break;

case 3:

if (cmpstr<wchar_t>(&ofn.lpstrFile[ofn.nFileExtension], L"png", 3))

cpystr<wchar_t>(&ofn.lpstrFile[lenstr(ofn.lpstrFile)], L".png", 4);

cFormat = 'p';

break;

}

DeleteFileW(ofn.lpstrFile);

bmpLoaded = Gdiplus::Bitmap::FromHBITMAP(bmpBack, NULL);

Gdiplus::GetImageEncodersSize((UINT*)&i, (UINT*)&j);

Gdiplus::GetImageEncoders(i, j, &iciArray[0]);

i = 0;

while (iciArray[i].MimeType[6] != cFormat) i++;

bmpLoaded->Save(ofn.lpstrFile, &iciArray[i].Clsid, NULL);

delete bmpLoaded;

return TRUE;

case ID_40009:

case ID_ACCELERATOR40058:

SendMessage(hDlg, WM_CLOSE, 0, 0);

return TRUE;

case ID_40010:

MessageBox(hDlg, "MicroPaint\nВерсия 2.0", "О  программе...", MB_ICONINFORMATION);

return TRUE;

case ID_40011:

case ID_40100:

ZeroMem((char*)&ccColor, sizeof(ccColor));

ccColor.lStructSize = sizeof(ccColor);

ccColor.hwndOwner = hDlg;

Информация о работе Простой графический редактор