On 11/3/05, James Liggett <[EMAIL PROTECTED]> wrote: > On Tue, 2005-11-01 at 23:34 -0200, Matheus Izvekov wrote: > > yes, i develop it in a windows xp environment. > > what kind of stack problem do you think might be related? > > i think its unlikely that its because of stack overflow, it uses very > > little stack, but ill investigate. > > If it works on Windows, then the stack problems I'm referring to aren't > in your code but in wine. I'll have some free time for the next few > days, so send your code and I'll try and see if I can help. By the way, > does this program do? > > James >
Its used for generating a 2 dimension float array dumped on a file. You start with a bitmap and assign a float value for each color. its still WIP and a bit messed up, but i believe it will be enough for the purpose of testing. Beware that this program does not use the C runtime. The entry point is "WinMainStartup" in gui.c.
/* Copyright 2005 Matheus Izvekov */ #define UNICODE #include <windows.h> #include <commctrl.h> #include "imageviewer.h" const WCHAR g_szClassName[] = L"myWindowClass"; enum { IDT_TIMER1 = 10001, ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE, ID_FILE_CLOSE, ID_FILE_EXIT, ID_FILE_EXPORT, ID_FILE_SAVE_AS, ID_VIEW_ORIG, ID_VIEW_FIT, ID_VIEW_STRETCH, ID_HELP_ABOUT, }; #define CVR_FILE_HEADER_MAGIC 'FRVC' LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); typedef struct { BYTE b; BYTE g; BYTE r; BYTE pad; } sBGR; typedef sBGR *pBGR; typedef struct { DWORD magic; DWORD nx; DWORD ny; DWORD tsize; } CVRfileHeader; typedef struct { sBGR c; float v; } TTableItem; typedef struct { TTableItem *t; DWORD size; } TTable; typedef struct { DWORD nx, ny; TTable table; pBGR image; } CVR; typedef struct { HWND hwndToolTip, hwndList, hwndStatic, hwndToolbar, hwndStatusbar; HANDLE hImage, hImageInv; HMENU hMenu, hMenuArq, hMenuView, hMenuHelp; WCHAR szFileName[MAX_PATH]; WCHAR szTitle[MAX_PATH]; WCHAR szExportFileName[MAX_PATH]; BOOLEAN bModified; CVR *cvr; } MainWD; TTable* GetColorTable(pBGR img, DWORD nx, DWORD ny); /* Gera um campo de velocidades */ float* GenerateField(CVR *cvr, int *size); HANDLE hConsole = NULL; void UpdateTableList(HWND hwnd, TTable *t); HBITMAP GetBitmapFromColorArray(pBGR buf, int nx, int ny); pBGR GetColorArray(HBITMAP hBmp, DWORD *nx, DWORD *ny); pBGR InvertColor(pBGR img, DWORD nx, DWORD ny, sBGR color); INT GetColorIndexFromTable(TTable table, sBGR color); void gui_update(HWND hwnd, MainWD *wd); void gui_update_title(HWND hwnd, MainWD *wd); BOOLEAN gui_export(LPWSTR file, CVR *cvr); BOOLEAN cvr_save(LPWSTR file, CVR *cvr); CVR* cvr_new(HBITMAP hBMP); CVR* cvr_open(LPWSTR file); void cvr_free(CVR **cvr); /* void PRINT(char *FMT, ...) { DWORD TEMP; va_list ARG; char BUF[512]; va_start(ARG, FMT); vsprintf(BUF, FMT, ARG); va_end(ARG); WriteConsole(hConsole, BUF, (DWORD)strlen(BUF), &TEMP, 0); } */ HANDLE ProcHeap; int _fltused = 1; void ErrorMsg(HWND hwnd, WCHAR *error) { WCHAR szBuf[80]; LPVOID lpMsgBuf; DWORD dw = GetLastError(); if (dw != 0) { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); wsprintfW(szBuf, L"%s\nErro %d: %s", error, dw, lpMsgBuf); MessageBox(hwnd, szBuf, L"Erro!", MB_ICONEXCLAMATION | MB_OK); LocalFree(lpMsgBuf); } else MessageBox(hwnd, error, L"Erro!", MB_ICONEXCLAMATION | MB_OK); } BOOL simple_mode = FALSE; WCHAR bmpName[MAX_PATH], binName[MAX_PATH]; WINAPI WinMainStartup(void) { WNDCLASSEX wc; MSG Msg; INITCOMMONCONTROLSEX InitCtrls; HWND hwndWin; int nArgs, i; HINSTANCE hInstance; LPWSTR lpCmdLine; STARTUPINFOW si; GetStartupInfoW(&si); ProcHeap = GetProcessHeap(); hInstance = GetModuleHandle(NULL); lpCmdLine = GetCommandLineW(); hConsole = GetStdHandle((DWORD)-11); simple_mode = FALSE; bmpName[0] = binName[0] = '\0'; if (lpCmdLine == NULL) ErrorMsg(NULL, L"lpCmdLine == NULL"); else { LPWSTR *szArglist; szArglist = CommandLineToArgvW(lpCmdLine, &nArgs); if (szArglist == NULL) ErrorMsg(NULL, L"szArglist == NULL"); else { for(i=0;i<nArgs;i++) { if (szArglist[i] == NULL) ErrorMsg(NULL, L"szArglist[i] == NULL"); else { if (szArglist[i][0] == '-' && szArglist[i][1] == '-') { if (lstrcmpW(szArglist[i]+2, L"simple") == 0) simple_mode = TRUE; else if (lstrcmpW(szArglist[i]+2, L"console") == 0) AllocConsole(); } else { LPWSTR ext = NULL, tmp; lstrcpyn(bmpName, szArglist[i], MAX_PATH); lstrcpyn(binName, bmpName, MAX_PATH); for(tmp=binName;*tmp!='\0';tmp++) if (*tmp=='.') ext = tmp; if (ext == NULL) ext = tmp; lstrcpy(ext, L".bin"); } } } LocalFree(szArglist); } } InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX); InitCtrls.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES; if (InitCommonControlsEx(&InitCtrls) == FALSE) ErrorMsg(NULL, L"Não foi possivel inicializar as classes dos controles TOOLBAR e LISTVIEW"); if (InitImView(hInstance) == FALSE) ErrorMsg(NULL, L"Não foi possivel inicializar a classe do controle IMVIEW"); wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(MainWD*); wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { ErrorMsg(NULL, L"Não foi possivel registrar a classe da janela principal"); return 0; } if ((hwndWin = CreateWindowEx( 0, g_szClassName, L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1000, 600, NULL, NULL, hInstance, NULL)) == NULL) { ErrorMsg(NULL, L"Não foi possível criar a janela principal"); return 0; } ShowWindow(hwndWin, si.wShowWindow); UpdateWindow(hwndWin); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return (DWORD)Msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { MainWD *wd; HINSTANCE hInstance; wd = (MainWD*)GetWindowLong(hwnd, 0); hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE); switch(msg) { case WM_CREATE: { wd = GlobalAlloc(GMEM_FIXED, sizeof(MainWD)); SetWindowLong(hwnd, 0, (LONG)wd); if ((wd->hwndToolTip = CreateWindowEx(0, TOOLTIPS_CLASSW, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, NULL, NULL)) != NULL) { SetWindowPos(wd->hwndToolTip, HWND_TOPMOST,0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } else ErrorMsg(hwnd, L"ToolTip Creation Failed!"); if ((wd->hMenu = CreateMenu()) != NULL) { if (simple_mode == FALSE) if ((wd->hMenuArq = CreatePopupMenu()) != NULL) { AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_NEW, L"&Novo"); AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_OPEN, L"A&brir"); AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_CLOSE, L"&Fechar"); AppendMenu(wd->hMenuArq, MF_SEPARATOR, 0, NULL); AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_SAVE, L"&Salvar"); AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_SAVE_AS, L"Salvar &como..."); AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_EXPORT, L"&Exportar"); AppendMenu(wd->hMenuArq, MF_SEPARATOR, 0, NULL); AppendMenu(wd->hMenuArq, MF_STRING, ID_FILE_EXIT, L"Sai&r"); AppendMenu(wd->hMenu, MF_STRING | MF_POPUP, (UINT_PTR)wd->hMenuArq, L"&Arquivo"); } else ErrorMsg(hwnd, L"MenuArq Creation Failed!"); if ((wd->hMenuView = CreatePopupMenu()) != NULL) { AppendMenu(wd->hMenuView, MF_STRING, ID_VIEW_ORIG, L"&Tamanho Original"); AppendMenu(wd->hMenuView, MF_STRING, ID_VIEW_FIT, L"F&it"); AppendMenu(wd->hMenuView, MF_STRING, ID_VIEW_STRETCH, L"Stretc&h Total"); AppendMenu(wd->hMenu, MF_STRING | MF_POPUP, (UINT_PTR)wd->hMenuView, L"&Visualização"); } else ErrorMsg(hwnd, L"MenuView Creation Failed!"); if ((wd->hMenuHelp = CreatePopupMenu()) != NULL) { AppendMenu(wd->hMenuHelp, MF_STRING, ID_HELP_ABOUT, L"&About"); AppendMenu(wd->hMenu, MF_STRING | MF_POPUP, (UINT_PTR)wd->hMenuHelp, L"A&juda"); } else ErrorMsg(hwnd, L"MenuHelp Creation Failed!"); SetMenu(hwnd, wd->hMenu); } else ErrorMsg(hwnd, L"Menu Creation Failed!"); if ((wd->hwndStatic = CreateWindowEx(0, IMVIEWCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 0, 0, hwnd, NULL, hInstance, NULL)) != NULL) { SendMessage(hwnd, WM_COMMAND, ID_VIEW_FIT, 0); } else ErrorMsg(hwnd, L"Static Creation Failed!"); if (simple_mode == FALSE) if ((wd->hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | CCS_NODIVIDER, 0, 0, 0, 0, hwnd, NULL, hInstance, NULL)) != NULL) { TBADDBITMAP tbab; BYTE bstyle = BTNS_BUTTON | BTNS_SHOWTEXT; TBBUTTON tbb[] = { {STD_FILENEW, ID_FILE_NEW, TBSTATE_ENABLED, bstyle, 0, 0, 0, (INT_PTR)L"Novo"}, {STD_FILEOPEN, ID_FILE_OPEN, TBSTATE_ENABLED, bstyle, 0, 0, 0, (INT_PTR)L"Abrir"}, {STD_FILESAVE, ID_FILE_SAVE, TBSTATE_ENABLED, bstyle, 0, 0, 0, (INT_PTR)L"Salvar"}, {0, ID_FILE_EXPORT, TBSTATE_ENABLED, bstyle, 0, 0, 0, (INT_PTR)L"Exportar"}, }; SendMessage(wd->hwndToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_MIXEDBUTTONS); SendMessage(wd->hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); tbab.hInst = HINST_COMMCTRL; tbab.nID = IDB_STD_SMALL_COLOR; SendMessage(wd->hwndToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab); SendMessage(wd->hwndToolbar, TB_ADDBUTTONSW, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM)&tbb); SendMessage(wd->hwndToolbar, TB_AUTOSIZE, 0, 0); } else ErrorMsg(hwnd, L"Toolbar Creation Failed!"); if ((wd->hwndStatusbar = CreateWindowEx(0, STATUSCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwnd, NULL, hInstance, NULL)) != NULL) { int statwidths[] = {150, 250, -1}; SendMessage(wd->hwndStatusbar, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths); SendMessage(wd->hwndStatusbar, SB_SETTEXTW, 2, (LPARAM)L"Selecione um item na lista, clique novamente e altere o valor"); } else ErrorMsg(hwnd, L"Statusbar Creation Failed!"); if ((wd->hwndList = CreateWindowEx( 0, WC_LISTVIEWW, L"ListView", WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | LVS_OWNERDATA | LVS_EDITLABELS | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER, 0, 0, 0, 0, hwnd, NULL, hInstance, NULL)) != NULL) { LVCOLUMN col; ListView_SetExtendedListViewStyle(wd->hwndList, LVS_EX_SUBITEMIMAGES | LVS_EX_FLATSB); FlatSB_EnableScrollBar(wd->hwndList, SB_BOTH, ESB_ENABLE_BOTH); col.mask = LVCF_WIDTH | LVCF_SUBITEM; col.cx = 100; col.iSubItem = 0; SendMessage(wd->hwndList, (UINT)LVM_INSERTCOLUMNW, (WPARAM)(int)0, (LPARAM)(LPLVCOLUMN)&col); } else ErrorMsg(hwnd, L"List Creation Failed!"); wd->cvr = NULL; wd->bModified = FALSE; wd->szFileName[0] = '\0'; wd->szTitle[0] = '\0'; wd->szExportFileName[0] = '\0'; gui_update_title(hwnd, wd); if (simple_mode == TRUE) { HANDLE hImage = LoadImage(NULL, bmpName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (hImage == NULL) { ErrorMsg(hwnd, L"Arquivo de Imagem inválido"); DestroyWindow(hwnd); } else { wd->cvr = cvr_new(hImage); wd->hImage = hImage; wd->bModified = TRUE; lstrcpyn(wd->szTitle, bmpName, MAX_PATH); gui_update(hwnd, wd); } } } break; case WM_CLOSE: if (simple_mode == TRUE) { if (gui_export(binName, wd->cvr) == FALSE) ErrorMsg(hwnd, L"Arquivo não pode ser exportado"); DestroyWindow(hwnd); } else if (SendMessage(hwnd, WM_COMMAND, ID_FILE_CLOSE, 0) == TRUE) { DestroyWindow(hwnd); } break; case WM_DESTROY: GlobalFree(wd); PostQuitMessage(0); break; case WM_SIZE: { int sbheight; RECT tbrect, sbrect, ssrect, lvrect, mwrect; SendMessage(wd->hwndStatusbar, WM_SIZE, 0, 0); SendMessage(wd->hwndToolbar, WM_SIZE, 0, 0); GetClientRect(hwnd, &mwrect); GetClientRect(wd->hwndToolbar, &tbrect); if (simple_mode) memset(&tbrect, 0, sizeof(RECT)); GetClientRect(wd->hwndStatusbar, &sbrect); tbrect.right = mwrect.right; sbheight = sbrect.bottom - sbrect.top; sbrect.bottom = mwrect.bottom; sbrect.top = mwrect.bottom - sbheight; lvrect.left = mwrect.left + GetSystemMetrics(SM_CXBORDER); lvrect.top = tbrect.bottom;// + GetSystemMetrics(SM_CYBORDER); lvrect.right = lvrect.left + 116 - GetSystemMetrics(SM_CXBORDER); lvrect.bottom = sbrect.top - GetSystemMetrics(SM_CYBORDER); ssrect.left = lvrect.right + GetSystemMetrics(SM_CXBORDER); ssrect.top = tbrect.bottom;// + GetSystemMetrics(SM_CYBORDER); ssrect.right = mwrect.right - GetSystemMetrics(SM_CXBORDER); ssrect.bottom = sbrect.top - GetSystemMetrics(SM_CYBORDER); MoveWindow(wd->hwndList, lvrect.left, lvrect.top, lvrect.right - lvrect.left, lvrect.bottom - lvrect.top, TRUE); MoveWindow(wd->hwndStatic, ssrect.left, ssrect.top, ssrect.right - ssrect.left, ssrect.bottom - ssrect.top, TRUE); //MoveWindow(wd->hwndRebar, tbrect.left, tbrect.top, tbrect.right - tbrect.left, tbrect.bottom - tbrect.top, TRUE); } break; case WM_TIMER: { if (wParam == IDT_TIMER1) { int layer = SendMessage(wd->hwndStatic, IVM_GETLAYER, 0, 0); if (layer == 0) SendMessage(wd->hwndStatic, IVM_SETLAYER, 1, 0); else SendMessage(wd->hwndStatic, IVM_SETLAYER, 0, 0); } } break; case WM_NOTIFY: { NMHDR *pnmh = (NMHDR *)lParam; if (pnmh->hwndFrom == wd->hwndStatic) { switch(pnmh->code) { case NM_RCLICK: { LPNMMOUSE lpnmmouse; POINT pt; lpnmmouse = (LPNMMOUSE)lParam; pt = lpnmmouse->pt; MapWindowPoints(lpnmmouse->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&pt, 1); TrackPopupMenuEx(wd->hMenuView, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL, pt.x, pt.y, hwnd, NULL); } break; case WM_MOUSEMOVE: case WM_LBUTTONDOWN: { INT i; LPNMIVPOS ivp = (LPNMIVPOS)lParam; sBGR color; if (wd->cvr != NULL) { if ((ivp->x < wd->cvr->nx)&&(ivp->y < wd->cvr->ny)) { color = wd->cvr->image[ivp->x + (ivp->y)*(wd->cvr->nx)]; i = GetColorIndexFromTable(wd->cvr->table, color); } else i = -1; if (i != -1) { switch(pnmh->code) { case WM_LBUTTONDOWN: { SetFocus(wd->hwndList); ListView_EditLabel( wd->hwndList, i ); } break; case WM_MOUSEMOVE: { WCHAR tmp[65]; wsprintfW(tmp, L"\tR:%d G:%d B:%d", color.r, color.g, color.b); SendMessage(wd->hwndStatusbar, SB_SETTEXTW, 0, (LPARAM)tmp); } break; } } } } break; } } else if (pnmh->hwndFrom == wd->hwndList) { NMLVDISPINFO *pnmv = (NMLVDISPINFO*)lParam; int i = pnmv->item.iItem; if (wd->cvr == NULL) break; switch(pnmh->code) { case NM_CLICK: { LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam; ListView_EditLabel( wd->hwndList, lpnmitem->iItem ); } break; case LVN_ITEMCHANGED: { LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam; if (pnmv->uNewState & LVIS_SELECTED) { /* Bota pra piscar e Atualiza a status bar com a cor selecionada na lista */ pBGR buf; sBGR color; WCHAR tmp[65]; if (wd->hImageInv != NULL) DeleteObject(wd->hImageInv); color = wd->cvr->table.t[pnmv->iItem].c; wsprintfW(tmp, L"\tR:%d G:%d B:%d", color.r, color.g, color.b); SendMessage(wd->hwndStatusbar, SB_SETTEXTW, 0, (LPARAM)tmp); buf = InvertColor(wd->cvr->image, wd->cvr->nx, wd->cvr->ny, color); wd->hImageInv = GetBitmapFromColorArray(buf, wd->cvr->nx, wd->cvr->ny); HeapFree(ProcHeap, 0 , buf); SendMessage(wd->hwndStatic, IVM_SETPICTURE, (WPARAM)wd->hImageInv, 1); KillTimer(hwnd, IDT_TIMER1); SetTimer(hwnd, IDT_TIMER1, 500, (TIMERPROC) NULL); SendMessage(wd->hwndStatic, IVM_SETLAYER, 1, 0); } return FALSE; } break; case LVN_GETDISPINFO: { if (pnmv->item.mask & LVIF_STATE) pnmv->item.state = 0; if (pnmv->item.mask & LVIF_IMAGE) pnmv->item.iImage = i; if (pnmv->item.mask & LVIF_TEXT) lstrcpyW(pnmv->item.pszText, L"todo"); //swprintf(pnmv->item.pszText, L"%5.4f", wd->cvr->table.t[i].v); } break; /* case LVN_BEGINLABELEDIT: { HWND hEdit; DWORD id; hEdit = ListView_GetEditControl(wd->hwndList); id = GetWindowLong(hEdit, GWL_ID); //PRINT("%d\n", id); SendMessage(wd->hwndList, WM_NOTIFY, (WPARAM)(LOWORD(id) | HIWORD(EN_CHANGE)), (LPARAM)hEdit); SendMessage(hEdit, EM_SETMODIFY, (WPARAM)TRUE, (LPARAM)0); return FALSE; } break; */ case LVN_ENDLABELEDIT: { if (pnmv->item.pszText == NULL) return FALSE; if (/*swscanf(pnmv->item.pszText, L"%f", &(wd->cvr->table.t[i].v)) == 1*/0) { if (wd->bModified != TRUE) { wd->bModified = TRUE; gui_update_title(hwnd, wd); } PostMessage(wd->hwndList, LVM_EDITLABELW, (WPARAM)i+1, (LPARAM)0); return TRUE; } else { //PostMessage(wd->hwndList, LVM_EDITLABELW, (WPARAM)i, (LPARAM)0); return FALSE; } } break; } } else if (pnmh->hwndFrom == wd->hwndToolbar) { switch(pnmh->code) { case TBN_GETINFOTIPW: { LPNMTBGETINFOTIP lptbgit; lptbgit = (LPNMTBGETINFOTIP)lParam; switch (lptbgit->iItem) { case ID_FILE_NEW: lstrcpyn(lptbgit->pszText, L"Criar novo arquivo de projeto", lptbgit->cchTextMax); break; case ID_FILE_OPEN: lstrcpyn(lptbgit->pszText, L"Abrir novo arquivo de projeto", lptbgit->cchTextMax); break; case ID_FILE_SAVE: lstrcpyn(lptbgit->pszText, L"Salvar arquivo de projeto", lptbgit->cchTextMax); break; case ID_FILE_EXPORT: lstrcpyn(lptbgit->pszText, L"Exportar para formato binário", lptbgit->cchTextMax); break; } } break; } } } break; case WM_COMMAND: switch(LOWORD(wParam)) { case ID_FILE_NEW: { OPENFILENAME ofn; WCHAR szFileName[MAX_PATH]; ZeroMemory(&ofn, sizeof(ofn)); ZeroMemory(szFileName, sizeof(szFileName)); ofn.lStructSize = sizeof(ofn); ofn.lpstrTitle = L"Escolha um Bitmap"; ofn.hwndOwner = hwnd; ofn.lpstrFilter = L"Bitmap Files (*.bmp)\0*.bmp\0"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = L"bmp"; if(GetOpenFileName(&ofn)) { HANDLE hImage = LoadImage(NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (hImage != 0) { CVR *cvr; cvr = cvr_new(hImage); if (SendMessage(hwnd, WM_COMMAND, ID_FILE_CLOSE, 0) == FALSE) cvr_free(&cvr); else { wd->cvr = cvr; wd->hImage = hImage; wd->bModified = TRUE; wd->szExportFileName[0] = '\0'; wd->szFileName[0] = '\0'; lstrcpyn(wd->szTitle, L"novo", MAX_PATH); gui_update(hwnd, wd); } } else ErrorMsg(hwnd, L"Arquivo de Imagem inválido"); } } break; case ID_FILE_SAVE_AS: { OPENFILENAME ofn; WCHAR szFileName[MAX_PATH]; if (wd->cvr == NULL) return FALSE; ZeroMemory(szFileName, sizeof(szFileName)); ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwnd; ofn.lpstrTitle = L"Salvar como..."; ofn.lpstrFilter = L"Conversion Files (*.cvr)\0*.cvr\0"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; ofn.lpstrDefExt = L"cvr"; if(GetSaveFileName(&ofn)) if (cvr_save(szFileName, wd->cvr) == FALSE) { ErrorMsg(hwnd, L"Arquivo não pode ser salvo"); return FALSE; } else { WCHAR tmp[65 + MAX_PATH]; lstrcpyn(wd->szFileName, szFileName, MAX_PATH); wsprintfW(tmp, L"Conversor - %s", wd->szFileName); SetWindowText(hwnd, tmp); if (wd->bModified != FALSE) { wd->bModified = FALSE; gui_update_title(hwnd, wd); } return TRUE; } } break; case ID_FILE_SAVE: if (wd->cvr == NULL) return FALSE; if (wd->bModified == TRUE) if (wd->szFileName[0] == '\0') return SendMessage(hwnd, WM_COMMAND, ID_FILE_SAVE_AS, 0); else if (cvr_save(wd->szFileName, wd->cvr) == FALSE) { ErrorMsg(hwnd, L"Arquivo não pode ser salvo"); ErrorMsg(hwnd, wd->szFileName); return FALSE; } else { wd->bModified = FALSE; gui_update_title(hwnd, wd); return TRUE; } break; case ID_FILE_EXPORT: { OPENFILENAME ofn; if (wd->cvr == NULL) return FALSE; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwnd; ofn.lpstrTitle = L"Exportar"; ofn.lpstrFilter = L"Bitmap Files (*.bin)\0*.bin\0"; ofn.lpstrFile = wd->szExportFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; ofn.lpstrDefExt = L"bmp"; if(GetSaveFileName(&ofn)) if (gui_export(wd->szExportFileName, wd->cvr) == FALSE) ErrorMsg(hwnd, L"Arquivo não pode ser exportado"); } break; case ID_FILE_OPEN: { OPENFILENAME ofn; WCHAR szFileName[MAX_PATH]; ZeroMemory(&ofn, sizeof(ofn)); ZeroMemory(szFileName, sizeof(szFileName)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwnd; ofn.lpstrFilter = L"Convert Files (*.cvr)\0*.cvr\0"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = L"cvr"; if(GetOpenFileName(&ofn)) { CVR *cvr; cvr = cvr_open(szFileName); if (cvr == NULL) ErrorMsg(hwnd, L"Arquivo de conversão não pode ser aberto"); else { if (SendMessage(hwnd, WM_COMMAND, ID_FILE_CLOSE, 0) == TRUE) { wd->cvr = cvr; wd->bModified = FALSE; wd->hImage = GetBitmapFromColorArray(wd->cvr->image, wd->cvr->nx, wd->cvr->ny); lstrcpyn(wd->szFileName, szFileName, MAX_PATH); wd->szExportFileName[0] = '\0'; lstrcpyn(wd->szTitle, wd->szFileName, MAX_PATH); gui_update(hwnd, wd); } else { cvr_free(&cvr); } } } } break; case ID_FILE_CLOSE: { if (wd->bModified == TRUE) { //perguntar se deseja salvar switch(MessageBox(hwnd, L"Deseja salvar o arquivo agora?", L"Arquivo não foi salvo", MB_YESNOCANCEL | MB_ICONQUESTION)) { case IDYES: if (SendMessage(hwnd, WM_COMMAND, ID_FILE_SAVE, 0) == FALSE) return FALSE; break; case IDNO: break; case IDCANCEL: return FALSE; } } cvr_free(&wd->cvr); if (wd->hImage != NULL) {DeleteObject(wd->hImage); wd->hImage = NULL;} if (wd->hImageInv != NULL) {DeleteObject(wd->hImageInv); wd->hImageInv = NULL;} wd->szFileName[0] = '\0'; wd->szTitle[0] = '\0'; gui_update_title(hwnd, wd); KillTimer(hwnd, IDT_TIMER1); SendMessage(wd->hwndStatic, IVM_SETPICTURE, 0, 0); SendMessage(wd->hwndStatic, IVM_SETPICTURE, 0, 1); UpdateTableList(wd->hwndList, NULL); return TRUE; } break; case ID_FILE_EXIT: SendMessage(hwnd, WM_CLOSE, 0, 0); break; case ID_VIEW_ORIG: { SendMessage(wd->hwndStatic, IVM_SETSTRETCH, (WPARAM)FALSE, 0); CheckMenuRadioItem(wd->hMenuView, ID_VIEW_ORIG, ID_VIEW_STRETCH, ID_VIEW_ORIG, MF_BYCOMMAND); } break; case ID_VIEW_FIT: { SendMessage(wd->hwndStatic, IVM_SETSTRETCH, (WPARAM)TRUE, 0); SendMessage(wd->hwndStatic, IVM_SETKEEPASPECT, (WPARAM)TRUE, 0); CheckMenuRadioItem(wd->hMenuView, ID_VIEW_ORIG, ID_VIEW_STRETCH, ID_VIEW_FIT, MF_BYCOMMAND); } break; case ID_VIEW_STRETCH: { SendMessage(wd->hwndStatic, IVM_SETSTRETCH, (WPARAM)TRUE, 0); SendMessage(wd->hwndStatic, IVM_SETKEEPASPECT, (WPARAM)FALSE, 0); CheckMenuRadioItem(wd->hMenuView, ID_VIEW_ORIG, ID_VIEW_STRETCH, ID_VIEW_STRETCH, MF_BYCOMMAND); } break; } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } void gui_update(HWND hwnd, MainWD *wd) { WCHAR tmp[33]; wsprintfW(tmp, L"\t%dx%d", wd->cvr->ny, wd->cvr->nx); SendMessage(wd->hwndStatusbar, SB_SETTEXTW, 1, (LPARAM)tmp); gui_update_title(hwnd, wd); SendMessage(wd->hwndStatic, IVM_SETPICTURE, (WPARAM)wd->hImage, 0); SendMessage(wd->hwndStatic, IVM_SETLAYER, 0, 0); UpdateTableList(wd->hwndList, &wd->cvr->table); SendMessage(hwnd, WM_SIZE, 0, 0); } void gui_update_title(HWND hwnd, MainWD *wd) { WCHAR tmp[65 + MAX_PATH]; if (wd->szTitle[0] != '\0') { wsprintf(tmp, L"Conversor - %s%c", wd->szTitle, wd->bModified ? '*' : '\0'); SetWindowText(hwnd, tmp); } else SetWindowText(hwnd, L"Conversor"); } BOOLEAN gui_export(LPWSTR file, CVR *cvr) { HANDLE hFile; BOOLEAN ret; hFile = CreateFile(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) ret = FALSE; else { float *field; DWORD size; field = GenerateField(cvr, &size); if (field == NULL) ret = FALSE; else { DWORD rsize; WriteFile(hFile, (LPCVOID)field, size*sizeof(float), &rsize, NULL); HeapFree(ProcHeap, 0 , field); ret = TRUE; } CloseHandle(hFile); } return ret; } BOOLEAN cvr_save(LPWSTR file, CVR *cvr) { HANDLE hFile; hFile = CreateFileW(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; else { DWORD rsize; CVRfileHeader header; header.magic = CVR_FILE_HEADER_MAGIC; header.nx = cvr->nx; header.ny = cvr->ny; header.tsize = cvr->table.size; WriteFile(hFile, (LPCVOID)&header, sizeof(CVRfileHeader), &rsize, NULL); WriteFile(hFile, (LPCVOID)cvr->table.t, cvr->table.size * sizeof(TTableItem), &rsize, NULL); WriteFile(hFile, (LPCVOID)cvr->image, cvr->nx * cvr->ny * sizeof(sBGR), &rsize, NULL); CloseHandle(hFile); return TRUE; } } CVR* cvr_new(HBITMAP hBMP) { CVR *cvr; cvr = HeapAlloc(ProcHeap, 0, sizeof(CVR)); cvr->image = GetColorArray(hBMP, &cvr->nx, &cvr->ny); cvr->table = *GetColorTable(cvr->image, cvr->nx, cvr->ny); return cvr; } CVR* cvr_open(LPWSTR file) { HANDLE hFile; CVR* ret; hFile = CreateFile(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) ret = NULL; else { CVRfileHeader header; DWORD rsize; if ((ReadFile(hFile, (LPVOID)&header, sizeof(CVRfileHeader), &rsize, NULL) == FALSE) || (rsize != sizeof(CVRfileHeader))) ret = NULL; else { if (header.magic != CVR_FILE_HEADER_MAGIC) ret = NULL; else { CVR *cvr; cvr = HeapAlloc(ProcHeap, 0, sizeof(CVR)); if (cvr == NULL) ret = NULL; else { cvr->table.size = header.tsize; cvr->nx = header.nx; cvr->ny = header.ny; cvr->table.t = HeapAlloc(ProcHeap, 0, header.tsize*sizeof(TTableItem)); cvr->image = HeapAlloc(ProcHeap, 0, header.nx*header.ny*sizeof(sBGR)); if ((cvr->table.t == NULL) || (cvr->image == NULL)) { if (cvr->table.t != NULL) HeapFree(ProcHeap, 0 , cvr->table.t); if (cvr->image != NULL) HeapFree(ProcHeap, 0 , cvr->image); HeapFree(ProcHeap, 0 , cvr); ret = NULL; } else if ((ReadFile(hFile, (LPVOID)cvr->table.t, header.tsize*sizeof(TTableItem), &rsize, NULL) == FALSE) || (rsize != header.tsize*sizeof(TTableItem)) || (ReadFile(hFile, (LPVOID)cvr->image, header.nx*header.ny*sizeof(sBGR), &rsize, NULL) == FALSE) || (rsize != header.nx*header.ny*sizeof(sBGR))) { HeapFree(ProcHeap, 0 , cvr->table.t); HeapFree(ProcHeap, 0 , cvr->image); HeapFree(ProcHeap, 0 , cvr); ret = NULL; } else ret = cvr; } } } CloseHandle(hFile); } return ret; } void cvr_free(CVR **cvr) { if (*cvr == NULL) return; if ((*cvr)->image != NULL) HeapFree(ProcHeap, 0 , (*cvr)->image); if ((*cvr)->table.t != NULL) HeapFree(ProcHeap, 0 , (*cvr)->table.t); HeapFree(ProcHeap, 0 , *cvr); *cvr = NULL; } void UpdateTableList(HWND hwnd, TTable *t) { DWORD sizex, sizey, i; HDC hDCimg = GetDC(hwnd); HDC hDC = CreateCompatibleDC(hDCimg); HIMAGELIST hImageList; HBITMAP hBMP; RECT rect; HGDIOBJ hOld; if (t == NULL) { ListView_SetItemCount(hwnd, 0); ListView_SetImageList(hwnd, NULL, LVSIL_SMALL); return; } ListView_SetItemCount(hwnd, t->size); if (t->size == 0) { ListView_SetImageList(hwnd, NULL, LVSIL_SMALL); } else { sizex = GetSystemMetrics (SM_CXSMICON)*2; sizey = GetSystemMetrics (SM_CYSMICON); hImageList = ImageList_Create(sizex, sizey, ILC_COLORDDB, t->size, 0); hBMP = CreateCompatibleBitmap(hDCimg, sizex, sizey); hOld = SelectObject(hDC, hBMP); rect.top = rect.left = 0; rect.bottom = sizey; rect.right = sizex; FillRect(hDC, &rect, (HBRUSH)(COLOR_WINDOW)); rect.top += 2; rect.left += 2; rect.bottom -= 2; rect.right -= 2; SelectObject(hDC, hOld); for(i=0;i<t->size;i++) { sBGR color = t->t[i].c; HBRUSH hbr = CreateSolidBrush(RGB(color.r,color.g,color.b)); SelectObject(hDC, hBMP); FillRect(hDC, &rect, hbr); SelectObject(hDC, hOld); ImageList_Add(hImageList, hBMP, NULL); DeleteObject(hbr); } DeleteDC(hDC); ReleaseDC(hwnd, hDCimg); DeleteObject(hBMP); ListView_SetImageList(hwnd, hImageList, LVSIL_SMALL); } } TTable* GetColorTable(pBGR img, DWORD nx, DWORD ny) { DWORD x,y; TTable *table; int tsize; int count = 0; unsigned char rgb[4]; unsigned char * tb; int index1, index2; tsize = 256; table = HeapAlloc(ProcHeap, 0, sizeof(TTable)); table->t = HeapAlloc(ProcHeap, 0, tsize*sizeof(TTableItem)); tb = HeapAlloc(ProcHeap, HEAP_ZERO_MEMORY, ((256*256*256)/8)*sizeof(BYTE)); for (y=0;y<ny;y++) for (x=0;x<nx;x++) { *(pBGR)rgb = img[x+y*nx]; index1 = (rgb[0]>>3) | (rgb[1]<<5) | (rgb[2]<<13); index2 = rgb[0]&0x07; if (!(tb[index1] & 1<<index2)) { tb[index1] |= 1<<index2; if (count > tsize) table->t = HeapReAlloc(ProcHeap, HEAP_ZERO_MEMORY, table->t, (tsize *= 2)*sizeof(TTableItem)); table->t[count].v = 0.0f; table->t[count++].c = *(pBGR)rgb; } } HeapFree(ProcHeap, 0 ,tb); table->t = HeapReAlloc(ProcHeap, HEAP_ZERO_MEMORY, table->t, count*sizeof(TTableItem)); table->size = count; return table; } pBGR InvertColor(pBGR img, DWORD nx, DWORD ny, sBGR color) { DWORD x, y; sBGR white = {255,255,255,0}; sBGR black = {0,0,0,0}; pBGR res; res = HeapAlloc(ProcHeap, 0, nx*ny*sizeof(sBGR)); for (y=0;y<ny;y++) for (x=0;x<nx;x++) { sBGR cur = img[x+y*nx]; if (cur.r == color.r && cur.g == color.g && cur.b == color.b) cur = (cur.r+cur.g+cur.b < 384) ? white : black; res[x+y*nx] = cur; } return res; } INT GetColorIndexFromTable(TTable table, sBGR color) { INT i; for(i=0;i<(INT)table.size;i++) { sBGR cur = table.t[i].c; if (cur.r == color.r && cur.g == color.g && cur.b == color.b) break; } if (i >= (INT)table.size) i = -1; return i; } float* GenerateField(CVR *cvr, int *size) { DWORD x,y; INT i; sBGR color; float *field; *size = cvr->nx*cvr->ny; field = HeapAlloc(ProcHeap, 0, *size*sizeof(float)); for (y=0;y<cvr->ny;y++) for (x=0;x<cvr->nx;x++) { color = cvr->image[x+y*cvr->nx]; i = GetColorIndexFromTable(cvr->table, color); if (i != -1) field[x*cvr->ny+y] = cvr->table.t[i].v; } return field; } pBGR GetColorArray(HBITMAP hBMP, DWORD *nx, DWORD *ny) { DWORD snx, sny; BITMAPINFO bi; BOOL bRes; pBGR res; HDC hDC; HGDIOBJ hOld; BITMAP bm; GetObject(hBMP, sizeof(BITMAP), &bm); hDC = CreateCompatibleDC(NULL); hOld = SelectObject(hDC, hBMP); if (nx == NULL) nx = &snx; if (ny == NULL) ny = &sny; *nx = bm.bmWidth; *ny = bm.bmHeight; bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = *nx; bi.bmiHeader.biHeight = - (LONG)*ny; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = *nx * 4 * *ny; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; res = HeapAlloc(ProcHeap, 0, (*nx)*(*ny)*sizeof(sBGR)); bRes = GetDIBits(hDC, hBMP, 0, *ny, res, &bi, DIB_RGB_COLORS); SelectObject(hDC, hOld); DeleteDC(hDC); if (!bRes) { HeapFree(ProcHeap, 0 , res); res = NULL; } return res; } HBITMAP GetBitmapFromColorArray(pBGR buf, int nx, int ny) { BITMAPINFO bi; HBITMAP res; HDC hDC, hDCd; HGDIOBJ hOld; hDCd = GetDC(NULL); hDC = CreateCompatibleDC(hDCd); res = CreateCompatibleBitmap(hDCd, nx, ny); ReleaseDC(NULL, hDCd); hOld = SelectObject(hDC, res); bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = nx; bi.bmiHeader.biHeight = -ny; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = nx*ny*sizeof(sBGR); bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; SetDIBits(hDC, res, 0, ny, buf, &bi, DIB_RGB_COLORS); SelectObject(hDC, hOld); DeleteDC(hDC); return res; }
/* Copyright 2005 Matheus Izvekov */ #define UNICODE #include <windows.h> #include <commctrl.h> #include "imageviewer.h" static LRESULT CALLBACK ImViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); typedef struct { HBITMAP hBMP[2]; BITMAP BM[2]; HDC hDC; ULONG curlayer; BOOL stretch, keepaspect; double scalex, scaley; LONG dx, dy, width, height; } ImViewWD; /* static void CalcScale(ImViewWD* wd, LONG t_height, LONG t_width) { if (wd->stretch == TRUE) { wd->dx = 0; wd->dy = 0; wd->height = t_height; wd->width = t_width; if (wd->keepaspect == TRUE) { double scalex = (double)t_height / (double)wd->BMimg.bmHeight; double scaley = (double)t_width / (double)wd->BMimg.bmWidth; if (scalex < scaley) { wd->width = wd->BMimg.bmWidth * scalex; wd->dx = (t_width - wd->width)/2; } else { wd->height = wd->BMimg.bmHeight * scaley; wd->dy = (t_height - wd->height)/2; } } } else { wd->height = wd->BMimg.bmHeight; wd->width = wd->BMimg.bmWidth; wd->dx = (t_width - wd->width)/2; wd->dy = (t_height - wd->height)/2; } } */ BOOL InitImView(HINSTANCE hinstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = ImViewProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(ImViewWD*); wc.hInstance = hinstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.lpszClassName = IMVIEWCLASSNAME; wc.hIconSm = NULL; if(!RegisterClassEx(&wc)) return FALSE; else return TRUE; } static LRESULT CALLBACK ImViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImViewWD *wd; HWND hwndParent = GetParent(hwnd); wd = (ImViewWD *)GetWindowLong(hwnd, 0); switch(msg) { case WM_CREATE: { HDC hDC; wd = GlobalAlloc(GMEM_FIXED, sizeof(ImViewWD)); wd->hBMP[0] = NULL; wd->hBMP[1] = NULL; wd->keepaspect = FALSE; wd->stretch = FALSE; wd->curlayer = 0; hDC = GetDC(hwnd); wd->hDC = CreateCompatibleDC(hDC); ReleaseDC(hwnd, hDC); SetWindowLong(hwnd, 0, (LONG)wd); } break; case WM_DESTROY: { DeleteDC(wd->hDC); GlobalFree(wd); } break; case WM_SIZE: { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); } break; case WM_PAINT: { HDC hDC; PAINTSTRUCT paint; BITMAP bm; HBRUSH hbBG; hbBG = (HBRUSH)GetClassLong(hwnd, GCL_HBRBACKGROUND); hDC = BeginPaint(hwnd, &paint); if (GetObject(GetCurrentObject(wd->hDC, OBJ_BITMAP), sizeof(BITMAP), &bm) != 0) { RECT wrect, trect1, trect2, trect3, trect4; LONG t_height, t_width; GetWindowRect(hwnd, &wrect); t_height = wrect.bottom - wrect.top; t_width = wrect.right - wrect.left; if (wd->stretch == TRUE) { wd->dx = 0; wd->dy = 0; wd->height = t_height; wd->width = t_width; wd->scaley = (double)t_height / (double)bm.bmHeight; wd->scalex = (double)t_width / (double)bm.bmWidth; if (wd->keepaspect == TRUE) { if (wd->scalex > wd->scaley) { wd->width = (LONG)(bm.bmWidth * wd->scaley); wd->scalex = (double)wd->width / (double)bm.bmWidth; wd->dx = (t_width - wd->width)/2; trect1.top = trect2.top = 0; trect1.bottom = trect2.bottom = t_height; trect1.left = 0; trect1.right = wd->dx; trect2.left = wd->dx + wd->width; trect2.right = t_width; FillRect(hDC, &trect1, hbBG); FillRect(hDC, &trect2, hbBG); } else { wd->height = (LONG)(bm.bmHeight * wd->scaley); wd->scaley = (double)wd->height / (double)bm.bmHeight; wd->dy = (t_height - wd->height)/2; trect1.left = trect2.left = 0; trect1.right = trect2.right = t_width; trect1.top = 0; trect1.bottom = wd->dy; trect2.top = wd->dy + wd->height; trect2.bottom = t_width; FillRect(hDC, &trect1, hbBG); FillRect(hDC, &trect2, hbBG); } } StretchBlt(hDC, wd->dx, wd->dy, wd->width, wd->height, wd->hDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); } else { wd->scalex = wd->scaley = 1.0f; wd->height = min(bm.bmHeight, t_height); wd->width = min(bm.bmWidth, t_width); wd->dx = (t_width - wd->width)/2; wd->dy = (t_height - wd->height)/2; trect1.top = trect2.top = trect3.top = 0; trect1.bottom = trect3.bottom = trect4.bottom = t_height; trect2.bottom = wd->dy; trect4.top = wd->dy + wd->height; trect1.left = 0; trect3.right = t_width; trect1.right = trect2.left = trect4.left = wd->dx; trect2.right = trect4.right = trect3.left = wd->dx + wd->width; FillRect(hDC, &trect1, hbBG); FillRect(hDC, &trect2, hbBG); FillRect(hDC, &trect3, hbBG); FillRect(hDC, &trect4, hbBG); StretchBlt(hDC, wd->dx, wd->dy, wd->width, wd->height, wd->hDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); //BitBlt(hDC, wd->dx, wd->dy, wd->width, wd->height, wd->hDC, 0, 0, SRCCOPY); } } EndPaint(hwnd, &paint); } break; case WM_RBUTTONUP: if (hwndParent != NULL) { NMMOUSE tmp; tmp.hdr.code = NM_RCLICK; tmp.hdr.hwndFrom = hwnd; tmp.hdr.idFrom = 0/*INCOMPLETE*/; tmp.pt.x = LOWORD(lParam); tmp.pt.y = HIWORD(lParam); SendMessage(hwndParent, WM_NOTIFY, (WPARAM)NULL, (LPARAM)&tmp); } break; case WM_LBUTTONDOWN: case WM_MOUSEMOVE: if (hwndParent != NULL) { NMIVPOS tmp; tmp.hdr.code = msg; tmp.hdr.hwndFrom = hwnd; tmp.hdr.idFrom = 0/*INCOMPLETE*/; //SetPixel(GetDC(hwnd), LOWORD(lParam), HIWORD(lParam), RGB(0,0,0)); tmp.x = (WORD)((LOWORD(lParam) - wd->dx)/wd->scalex); tmp.y = (WORD)((HIWORD(lParam) - wd->dy)/wd->scaley); if ((tmp.x >= 0) && (tmp.y >= 0) /*&& (tmp.x < wd->width) && (tmp.y < wd->height)*/) SendMessage(hwndParent, WM_NOTIFY, (WPARAM)NULL, (LPARAM)&tmp); } break; case IVM_SETPICTURE: { LRESULT ret; RECT wrect; LONG t_height, t_width; LONG layer; GetWindowRect(hwnd, &wrect); t_height = wrect.bottom - wrect.top; t_width = wrect.right - wrect.left; layer = (LONG)lParam; ret = (LRESULT)wd->hBMP[layer]; wd->hBMP[layer] = (HBITMAP)wParam; if (wd->curlayer == layer) { SelectObject(wd->hDC, (HGDIOBJ)wParam); RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); } return ret; } break; case IVM_GETPICTURE: { return (WPARAM)wd->hBMP[wd->curlayer]; } break; case IVM_SETKEEPASPECT: { RECT wrect; LONG t_height, t_width; GetWindowRect(hwnd, &wrect); t_height = wrect.bottom - wrect.top; t_width = wrect.right - wrect.left; wd->keepaspect = (BOOL)wParam; RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); } break; case IVM_GETKEEPASPECT: { return (WPARAM)wd->keepaspect; } break; case IVM_SETSTRETCH: { RECT wrect; LONG t_height, t_width; GetWindowRect(hwnd, &wrect); t_height = wrect.bottom - wrect.top; t_width = wrect.right - wrect.left; wd->stretch = (BOOL)wParam; RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); } break; case IVM_GETSTRETCH: { return (WPARAM)wd->stretch; } break; case IVM_SETLAYER: { wd->curlayer = (ULONG)wParam; SelectObject(wd->hDC, wd->hBMP[wParam]); RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); } break; case IVM_GETLAYER: { return wd->curlayer; } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); break; } return FALSE; }
/* Copyright 2005 Matheus Izvekov */ #ifndef _IMVIEWER_ #define _IMVIEWER_ #include <windows.h> typedef struct { NMHDR hdr; WORD x, y; } NMIVPOS, *LPNMIVPOS; #define IMVIEWCLASSNAME L"IMVIEW" #define IVM_SETPICTURE 0x0170 #define IVM_GETPICTURE 0x0171 #define IVM_SETKEEPASPECT 0x0173 #define IVM_GETKEEPASPECT 0x0174 #define IVM_SETSTRETCH 0x0175 #define IVM_GETSTRETCH 0x0176 #define IVM_SETLAYER 0x0177 #define IVM_GETLAYER 0x0178 BOOL InitImView(HINSTANCE hinstance); #endif