/*
* Square Matrix Editor testing program
* (c) Slava Antonov, 2004
*/
#include
#include
#include "MatrixEd.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
#define ID_CONTROL 1000
/* Идентификаторы горячих клавиш */
#define HK_PLUS 0
#define HK_MINUS 1
#define HK_F1 2
#define HK_F2 3
int** AllocItems(const int nSize);
void FreeItems(int** Items, const int nSize);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "Matrix Editor";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof (wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
RegisterClassEx (&wndclass);
hwnd = CreateWindowEx(WS_EX_CONTROLPARENT | WS_EX_WINDOWEDGE,
szAppName,
// класс окна
"Matrix Editor",
// заголовок окна
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
// стиль окна
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hwnd, &msg))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return msg.wParam;
} // WinMain()
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static int cxClient, cyClient;
static HWND hwndMatrix, hwndText;
PAINTSTRUCT ps;
HDC hdc;
switch (iMsg)
{
case WM_CREATE:
hwndText = CreateWindow("STATIC",
"Клавиши управления: +/-, Tab, Esc, F1, F2",
WS_VISIBLE | WS_CHILD,
10, 10, 300, 21,
hwnd,
NULL,
((LPCREATESTRUCT) lParam)->hInstance,
NULL);
hwndMatrix = CreateMatrix(((LPCREATESTRUCT) lParam)->hInstance,
hwnd,
0, 0, 0, 0,
0,
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
0);
SendMessage(hwndMatrix, MM_SETSIZE, 0, 4);
RegisterHotKey(hwnd, HK_PLUS, 0, VK_ADD);
RegisterHotKey(hwnd, HK_MINUS, 0, VK_SUBTRACT);
RegisterHotKey(hwnd, HK_F1, 0, VK_F1);
RegisterHotKey(hwnd, HK_F2, 0, VK_F2);
return 0;
case WM_DESTROY:
DestroyWindow(hwndMatrix);
DestroyWindow(hwndText);
PostQuitMessage(0);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 2: /* ESCAPE */
if (MessageBox(hwnd,
"Вы действительно хотите занулить все элементы матрицы?",
"Требудется подтверждение",
MB_OKCANCEL) == IDOK)
SendMessage(hwndMatrix, MM_CLEAR, 0, 0);
break;
default:;
}
return 0;
case WM_HOTKEY:
switch(wParam)
{
case HK_PLUS:
SendMessage(hwndMatrix,
MM_SETSIZE,
0,
SendMessage(hwndMatrix, MM_GETSIZE, 0, 0) + 1);
break;
case HK_MINUS:
{
DWORD nSize = SendMessage(hwndMatrix, MM_GETSIZE, 0, 0);
if (nSize > 0)
SendMessage(hwndMatrix,
MM_SETSIZE,
0,
nSize - 1);
}
break;
case HK_F1:
/* Транспонирование матрицы */
if(!SendMessage(hwndMatrix, MM_ISFILLED, 0, 0))
MessageBox(hwnd,
"Некоторые ячейки матрицы не заполнены",
"Ошибка",
MB_ICONERROR);
else
SendMessage(hwndMatrix, MM_TRANSPON, 0, 0);
return 0;
case HK_F2:
/* Вычисление определителя матрицы */
if(!SendMessage(hwndMatrix, MM_ISFILLED, 0, 0))
MessageBox(hwnd,
"Некоторые ячейки матрицы не заполнены",
"Ошибка",
MB_ICONERROR);
else
{
int Det;
SendMessage(hwndMatrix, MM_DETERM, 0, (LPARAM) &Det);
char Buf[33];
itoa(Det, Buf, 10);
MessageBox(hwnd,
Buf,
"Определитель",
MB_ICONINFORMATION);
}
return 0;
defalult:
break;
}
break;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
MoveWindow(hwndMatrix, 10, 30, cxClient / 2, cyClient / 2, TRUE);
return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
/* Matrix Control
(c) Slava Antonov, 2004 */
#ifndef _MATRIX_H
#define _MATRIX_H
#include
#include
#include "matrix.h"
const char* WNDCLASS_MATRIX = "Matrix";
const int MATRIX_ERROR = -1;
const char* PROPERTY_MATRIX = WNDCLASS_MATRIX;
const MMERR_EMPTYCELLS = -1;
/* Сообщения для окон класса "Матрица" */
const MM_SETSIZE = WM_USER + 1;
/* Задает размер квадратной матрицы.
Старые значения сохраняются, а новые
забиваются нулями.
lParam - новый размер
result - MATRIX_ERROR в случае ошибки
иначе, текущий размер матрицы */
const MM_GETSIZE = WM_USER + 3;
/* Возвращает размер матрицы */
const MM_CLEAR = WM_USER + 4;
/* Заменяет все элементы матрицы на нули */
const MM_GETITEMS = WM_USER + 2;
/* Возвращает двумерный массив элементов матрицы
lParam - указатель на двумерный массив N x N целых чисел
где N - текущий размер матрицы
Result - 0 если ошибок нет
MMERR_EMPTYCELLS - если есть пустые ячейки */
const MM_ISFILLED = WM_USER + 5;
/* Указаны ли все элементы матрицы
Если результат - ноль, то указаны есть пустые ячейки */
const MM_TRANSPON = WM_USER + 6;
/* Транспонирование матрицы */
const MM_DETERM = WM_USER + 7;
/* Возвращает определитель матрицы */
const MM_GETITEM = WM_USER + 8;
/* Возвращает элемент матрицы
wParam - номер строки
lParam - номер столбца
Result - элемент */
const MM_SETITEM = WM_USER + 9;
/* Задает элемент матрицы
LOWORD(wParam) - номер строки
HIWORD(wParam) - номер столбца
lParam - новое значение
Result - старое значение */
struct STRUCT_MATRIX
{
DWORD cxClient, cyClient;
/* размеры клиентской области окна */
HWND hwnd;
HINSTANCE hInstance;
DWORD nSize;
/* размер квадратной матрицы */
HFONT hFont;
/* шрифт используемый для отображения матрицы */
HWND** hwndCells;
/* дескрипторы окон ячеек матрицы */
};
typedef STRUCT_MATRIX* PSTRUCT_MATRIX;
/* Объявления фукнций */
LRESULT CALLBACK MatrixWndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
/* оконная процедура */
void CreateCells(PSTRUCT_MATRIX pData, DWORD nSize);
/* выделяет память под массив ячеек и
создает окна для ячеек */
void FreeHandles(PSTRUCT_MATRIX pData);
/* уничтожение окон ячеек и освобождение памяти */
BOOL MoveCells(const PSTRUCT_MATRIX pData);
/* Изменение размеров и позиций ячеек в соотвествии
с указанными шириной и высотой окна */
int** AllocItems(const int nSize);
void FreeItems(int** Items, const int nSize);
/* Оконная процедура */
LRESULT CALLBACK MatrixWndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
PSTRUCT_MATRIX pData;
PAINTSTRUCT ps;
HDC hdc;
LRESULT lres;
pData = (PSTRUCT_MATRIX) GetProp(hwnd, PROPERTY_MATRIX);
// получаем указатель на стуктуру с данными окна
switch (iMsg)
{
case WM_CREATE:
pData = new STRUCT_MATRIX;
pData->hwnd = hwnd;
pData->hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
SetProp(hwnd, PROPERTY_MATRIX, (HANDLE) pData);
/* запоминаем указатель на структуру с
данными текущего окна */
return 0;
case WM_DESTROY:
FreeHandles(pData);
RemoveProp(hwnd, PROPERTY_MATRIX);
delete pData;
return 0;
// говорим, что элемент управления
// будет обрабатывать стрелки и символы
case WM_GETDLGCODE:
if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY)
return DLGC_WANTARROWS;
else
return DLGC_WANTARROWS | DLGC_WANTCHARS;
case WM_SIZE:
// пересчитываем положение и размеры
// ячеек матрицы
pData->cxClient = LOWORD(lParam);
pData->cyClient = HIWORD(lParam);
if (pData->nSize > 0)
MoveCells(pData);
return 0;
case WM_SETFONT:
pData->hFont = (HFONT) wParam;
break;
case WM_GETFONT:
return (LRESULT) pData->hFont;
case MM_CLEAR:
if(pData->nSize > 0)
for(int i = 0; i < pData->nSize; i++)
for(int j = 0; j < pData->nSize; j++)
SetWindowText(pData->hwndCells[i][j], "0");
return 0;
case MM_GETSIZE:
return pData->nSize;
/* Изменение размерности матрицы
Старые значения сохраняются, новые приравниваюся 0 */
case MM_SETSIZE:
if((DWORD)lParam != pData->nSize)
{
lres = pData->nSize;
int** OldItems = AllocItems(lres);
SendMessage(hwnd, MM_GETITEMS, 0, (LPARAM) OldItems);
FreeHandles(pData);
CreateCells(pData, (DWORD) lParam);
/* создает ячейки и запоминает новый размер */
for(int i = 0; i < pData->nSize; i++)
for(int j = 0; j < pData->nSize; j++)
if ((i < lres) && (j < lres))
SendMessage(hwnd,
MM_SETITEM,
MAKELONG(i, j),
OldItems[i][j]);
else
SendMessage(hwnd,
MM_SETITEM,
MAKELONG(i, j),
0);
FreeItems(OldItems, lres);
MoveCells(pData);
} else
lres = pData->nSize;
return lres;
case MM_GETITEM:
{
DWORD i = (DWORD) wParam;
DWORD j = (DWORD) lParam;
if((i < pData->nSize) || (j < pData->nSize))
{
char* a_ij;
DWORD Len = GetWindowTextLength(pData->hwndCells[i][j]);
a_ij = new char[Len + 1];
GetWindowText(pData->hwndCells[i][j], a_ij, Len + 1);
int Res = atoi(a_ij);
delete []a_ij;
return Res;
} else
return 0;
}
case MM_SETITEM:
{
DWORD i = LOWORD(wParam);
DWORD j = HIWORD(wParam);
if ((i < pData->nSize) && (j < pData->nSize))
{
char Buf[33];
DWORD nLen = GetWindowTextLength(hwnd) + 1;
char* pText = new char[nLen];
GetWindowText(hwnd, pText, nLen);
int OldValue = atoi(pText);
delete[] pText;
itoa(lParam, Buf, 10);
SetWindowText(pData->hwndCells[i][j], Buf);
return OldValue;
} else
return MATRIX_ERROR;
}
case MM_GETITEMS:
if(pData->nSize > 0)
{
if(!SendMessage(hwnd, MM_ISFILLED, 0, 0)) return MMERR_EMPTYCELLS;
int** Items = (int**) lParam;
for(int i = 0; i < pData->nSize; i++)
for(int j = 0; j < pData->nSize; j++)
Items[i][j] = SendMessage(hwnd, MM_GETITEM, i, j);
}
return 0;
/* все ли ячейки заполнены? */
case MM_ISFILLED:
if(pData->nSize > 0)
{
for(int i = 0; i < pData->nSize; i++)
for(int j = 0; j < pData->nSize; j++)
if (GetWindowTextLength(pData->hwndCells[i][j]) == 0)
return 0;
}
return !0;
/* Транспонирование матрицы */
case MM_TRANSPON:
{
if(pData->nSize == 0) return 0;
char* a_ij;
char* a_ji;
for(int i = 0; i < pData->nSize; i++)
for(int j = i + 1; j < pData->nSize; j++)
{
int nLen = GetWindowTextLength(pData->hwndCells[i][j]) + 1;
a_ij = new char[nLen];
GetWindowText(pData->hwndCells[i][j], a_ij, nLen);
nLen = GetWindowTextLength(pData->hwndCells[j][i]) + 1;
a_ji = new char[nLen];
GetWindowText(pData->hwndCells[j][i], a_ji, nLen);
if(strcmp(a_ij, a_ji) != 0)
{
SetWindowText(pData->hwndCells[i][j], a_ji);
SetWindowText(pData->hwndCells[j][i], a_ij);
}
delete []a_ij;
delete []a_ji;
}
}
return 0;
/* Вычисление определителя матрицы */
case MM_DETERM:
{
if(pData->nSize <= 0) return 0;
if(!SendMessage(hwnd, MM_ISFILLED, 0, 0)) return 0;
CMatrix Matrix(pData->nSize, pData->nSize);
for(DWORD i = 0; i < pData->nSize; i++)
for(DWORD j = 0; j < pData->nSize; j++)
Matrix[i][j] = SendMessage(hwnd, MM_GETITEM, i, j);
*((int*) lParam) = Matrix.determinant();
}
return !0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam);
}
void CreateCells(PSTRUCT_MATRIX pData, DWORD nSize)
{
if (nSize == pData->nSize) return;
pData->nSize = nSize;
if (!nSize) return;
pData->hwndCells = new HWND*[nSize];
for (int i = 0; i < nSize; i++)
{
pData->hwndCells[i] = new HWND[nSize];
for(int j = 0; j < nSize; j++)
pData->hwndCells[i][j] = CreateWindowEx(0,
"EDIT",
NULL,
WS_VISIBLE | WS_CHILD | WS_TABSTOP | ES_NUMBER | ES_CENTER,
0,
0,
0,
0,
pData->hwnd,
(HMENU) (i * nSize + j),
pData->hInstance,
0);
}
}
void FreeHandles(PSTRUCT_MATRIX pData)
{
if(!pData->nSize) return;
for(int i = 0; i < pData->nSize; i++)
{
for(int j = 0; j < pData->nSize; j++)
DestroyWindow(pData->hwndCells[i][j]);
delete []pData->hwndCells[i];
}
delete []pData->hwndCells;
pData->hwndCells = NULL;
}
BOOL MoveCells(const PSTRUCT_MATRIX pData)
{
if (pData->nSize != 0)
{
int Space = 1; /* размер зазора между ячейками */
int CellWidth = (pData->cxClient - (pData->nSize-1) * Space) / pData->nSize;
int CellHeight = (pData->cyClient - (pData->nSize-1) * Space) / pData->nSize;
for (int i = 0; i < pData->nSize; i++)
for(int j = 0; j < pData->nSize; j++)
MoveWindow(pData->hwndCells[i][j],
j * CellWidth + j * Space, i * CellHeight + i * Space,
CellWidth, CellHeight,
TRUE);
}
return TRUE;
}
int** AllocItems(const int nSize)
{
if(nSize <= 0) return NULL;
int** Items = new int*[nSize];
for (int i = 0; i < nSize; i++)
Items[i] = new int[nSize];
return Items;
}
void FreeItems(int** Items, const int nSize)
{
if((!Items) || (nSize <= 0)) return;
for (int i = 0; i < nSize; i++)
delete []Items[i];
delete []Items;
}
HWND CreateMatrix(HINSTANCE hInstance, HWND hwndParent,
int x, int y, int width, int height, unsigned id,
DWORD fStyle, DWORD fExStyle)
{
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MatrixWndProc;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance;
wndclass.hIcon = 0;
wndclass.hCursor = NULL;
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = WNDCLASS_MATRIX;
wndclass.hIconSm = 0;
RegisterClassEx (&wndclass);
HWND hwnd = CreateWindowEx(fExStyle | WS_EX_CONTROLPARENT,
WNDCLASS_MATRIX,
"",
fStyle | WS_CLIPCHILDREN,
x, y,
width, height,
hwndParent,
(HMENU) id,
hInstance,
NULL);
return hwnd;
}
#endif