📄 win32_drawing.cpp
字号:
/*
This file is part of SWAIN (http://sourceforge.net/projects/swain).
Copyright (C) 2006 Daniel Lindstr鰉 and Daniel Nilsson
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "stdafx.h"
#include "win32_drawing.h"
#include "win32_client.h"
#include "win32_buddies.h"
#include "../common/network.h"
#include "../common/coords.h"
#include "../common/ViewPort.h"
#include "../common/BitmapObject.h"
#include "../common/BackgroundObject.h"
#include "../common/ArrowObject.h"
#include "../common/PolylineObject.h"
#include "../common/BoundsObject.h"
#include "../common/ZoomTool.h"
#include "../common/PanTool.h"
#include "../common/PolylineTool.h"
#include "../common/ArrowTool.h"
#include "Win32Bitmap.h"
#define DRAG_THRESHOLD 8.0
#define SHMenuBar_GetMenu(hWndMB,idMenu) (HMENU)SendMessage((hWndMB), SHCMBM_GETSUBMENU, (WPARAM)0, (LPARAM)idMenu)
enum TOOLS {
TOOL_ZOOM,
TOOL_PAN,
TOOL_LINE,
TOOL_POINTER,
NUM_TOOLS
};
// Global variables
HWND g_hWndDrawingWindow; // window handle
// Module variables
//static HWND g_hWndDrawingMenuBar;
static ViewPort *vp;
static Canvas *canvas;
static ObjectManager *objectman;
static Tool *tools[NUM_TOOLS];
static WCHAR *filename = NULL;
static ConnectionHandler *connhand;
static bool rotate;
static HANDLE ready_semaphore = NULL;
static bool ready_success = false;
static int peer_cid = -1;
static bool delete_file = false;
static bool followMe = false;
// Forward declaration of functions
static bool CreateDrawingWindow(void);
static void CleanUpSession(void);
static void ChangeTool(int idm);
static void ChangeColor(int idm);
static void ChangeFollowMe(void);
LRESULT CALLBACK DrawingWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
POINT pt;
static POINT oldpt;
static BOOL mbdown = false;
// static SHACTIVATEINFO s_sai;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{/*
case IDM_DRAWING_MENU_EXIT:
SendBye(peer_cid);
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
*/
case IDM_DRAWING_TOOLS_LINE:
case IDM_DRAWING_TOOLS_POINTER:
case IDM_DRAWING_TOOLS_PAN:
case IDM_DRAWING_TOOLS_ZOOM:
ChangeTool(wmId);
break;
case IDM_DRAWING_TOOLS_CLEARALL:
if (objectman != NULL) {
PacketClear *packet = new PacketClear();
packet->setCId(peer_cid);
connhand->sendPacket(packet);
objectman->clearLayer(LAYER_NORMAL);
}
break;
case IDM_DRAWING_TOOLS_FOLLOWME:
ChangeFollowMe();
break;
case IDM_DRAWING_COLOR_BLACK:
ChangeColor(IDM_DRAWING_COLOR_BLACK);
break;
case IDM_DRAWING_COLOR_WHITE:
ChangeColor(IDM_DRAWING_COLOR_WHITE);
break;
case IDM_DRAWING_COLOR_RED:
ChangeColor(IDM_DRAWING_COLOR_RED);
break;
case IDM_DRAWING_COLOR_GREEN:
ChangeColor(IDM_DRAWING_COLOR_GREEN);
break;
case IDM_DRAWING_COLOR_BLUE:
ChangeColor(IDM_DRAWING_COLOR_BLUE);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PACKET_ARROW:
{
PacketArrow *packet = (PacketArrow *)lParam;
FPOINT fp;
packet->getPoint(&fp);
ArrowObject *arrow = dynamic_cast<ArrowObject *>(objectman->getObject(packet->getOid()));
if (arrow == NULL) {
arrow = new ArrowObject(objectman, vp, &fp);
objectman->addObject(arrow, LAYER_FRONT, packet->getOid());
} else {
arrow->setPoint(&fp);
}
delete packet;
}
break;
case WM_PACKET_POLYLINE:
{
PacketPolyline *packet = (PacketPolyline *)lParam;
FPOINT fp;
packet->getPoint(&fp);
PolylineObject *polyline = dynamic_cast<PolylineObject *>(objectman->getObject(packet->getOid()));
if(polyline == NULL){
polyline = new PolylineObject(vp, objectman, &fp, packet->getColor());
objectman->addObject(polyline, LAYER_NORMAL, packet->getOid());
}
else{
polyline->addPoint(&fp);
}
delete packet;
}
break;
case WM_PACKET_CLEAR:
{
PacketClear *packet = (PacketClear *)lParam;
objectman->clearLayer(LAYER_NORMAL);
delete packet;
}
break;
case WM_PACKET_BOUNDS:
{
static int bounds_oid = -1;
PacketBounds *packet = (PacketBounds *)lParam;
FRECT rect;
packet->getBounds(&rect);
bool follow = packet->getFollowMe();
BoundsObject *bo = dynamic_cast<BoundsObject *>(objectman->getObject(bounds_oid));
if(bo == NULL){
bo = new BoundsObject(objectman, vp, rect.left, rect.top, rect.right, rect.bottom);
bounds_oid = objectman->addObject(bo, LAYER_FRONT);
}
else{
bo->changeBounds(rect.left, rect.top, rect.right, rect.bottom);
}
delete packet;
if(follow){
vp->setBounds(&rect);
vp->getBounds(&rect);
packet = new PacketBounds(rect, false);
packet->setCId(peer_cid);
connhand->sendPacket(packet);
}
}
break;
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
if (vp != NULL) {
vp->redraw(&ps.rcPaint);
}
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
pt.x = (signed short)LOWORD(lParam);
pt.y = (signed short)HIWORD(lParam);
SetCapture(hWnd);
mbdown = true;
if (vp != NULL) {
vp->mouseDown(&pt);
}
oldpt = pt;
break;
case WM_LBUTTONUP:
pt.x = (signed short)LOWORD(lParam);
pt.y = (signed short)HIWORD(lParam);
ReleaseCapture();
mbdown = false;
if (vp != NULL) {
vp->mouseUp(&pt);
}
break;
case WM_MOUSEMOVE:
pt.x = (signed short)LOWORD(lParam);
pt.y = (signed short)HIWORD(lParam);
if(mbdown && vp != NULL && distance(&oldpt, &pt) >= DRAG_THRESHOLD) {
vp->mouseDragged(&pt);
oldpt = pt;
}
break;
case WM_CLOSE:
SendBye(peer_cid);
DestroyWindow(hWnd);
break;
case WM_DESTROY:
CleanUpSession();
break;
case WM_ACTIVATE:
break;
case WM_SETTINGCHANGE:
break;
case WM_SIZE:
if (vp != NULL) {
vp->screenResized();
FRECT rc;
vp->getBounds(&rc);
PacketBounds *pb = new PacketBounds(rc, followMe);
pb->setCId(peer_cid);
connhand->sendPacket(pb);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
static void ChangeTool(int idm) {
static int oldidm = -1;
int tool;
HMENU hmnu;
switch (idm) {
case IDM_DRAWING_TOOLS_LINE: tool = TOOL_LINE; break;
case IDM_DRAWING_TOOLS_PAN: tool = TOOL_PAN; break;
case IDM_DRAWING_TOOLS_POINTER: tool = TOOL_POINTER; break;
case IDM_DRAWING_TOOLS_ZOOM: tool = TOOL_ZOOM; break;
default: break;
}
canvas->setTool(tools[tool]);
hmnu = GetMenu(g_hWndDrawingWindow);
if (oldidm != -1) {
CheckMenuItem(hmnu, oldidm, MF_BYCOMMAND | MF_UNCHECKED);
}
CheckMenuItem(hmnu, idm, MF_BYCOMMAND | MF_CHECKED);
oldidm = idm;
}
static void ChangeFollowMe(void) {
HMENU hmnu;
followMe = !followMe;
((ZoomTool *)tools[TOOL_ZOOM])->setFollowMe(followMe);
((PanTool *)tools[TOOL_PAN])->setFollowMe(followMe);
hmnu = GetMenu(g_hWndDrawingWindow);
CheckMenuItem(hmnu, IDM_DRAWING_TOOLS_FOLLOWME, MF_BYCOMMAND | followMe ? MF_CHECKED : MF_UNCHECKED);
}
static bool CreateDrawingWindow(void) {
HWND hWnd = CreateWindow(szDrawingWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 800, NULL, NULL, g_hInst, NULL);
if (!hWnd)
{
return FALSE;
}
// HACK: Save the window handle in a global so it doesn't need to be passed around so much!
g_hWndDrawingWindow = hWnd;
return true;
}
void StartNewSession(ConnectionHandler *ch, ClientPacketHandler *cph,
int cid, IMAGE_TYPE imagetype){
WCHAR fsFile[512] = L"";
OPENFILENAME of;
switch(imagetype){
case(IMAGE_FILE):
ZeroMemory(&of, sizeof(OPENFILENAME));
of.lStructSize = sizeof(OPENFILENAME);
of.hwndOwner = g_hWndMainWindow;
of.lpstrFilter = L"Jpeg (*.jpg)\0*.JPG\0Bitmap (*.bmp)\0*.BMP\0Gif (*.gif)\0*.GIF\0"
L"All images\0*.JPG;*.BMP;*.GIF\0Show all files (*.*)\0*.*\0";
of.nFilterIndex = 4;
//of.lpstrInitialDir =
of.lpstrFile = fsFile;
of.nMaxFile = sizeof(fsFile);
of.lpstrFileTitle = NULL;
of.nMaxFileTitle = 0;
if(GetOpenFileName(&of))
filename = _wcsdup(fsFile);
else{
changeMyStatus(STATUS_ONLINE);
return;
}
rotate = false;
delete_file = false;
break;
case(IMAGE_NONE):
filename = NULL;
rotate = false;
delete_file = false;
break;
}
ready_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
do{
ready_success = false;
if (!ChooseBuddy(ch, cph, cid)) {
changeMyStatus(STATUS_ONLINE);
return;
}
}while((WaitForSingleObject(ready_semaphore, 20000) == WAIT_TIMEOUT ||!ready_success) &&
MessageBox(NULL, L"Connection not accepted.", L"Error", MB_OK));
PacketFile *pf = new PacketFile(filename, false);
pf->setCId(peer_cid);
ch->sendPacket(pf);
CreateSession(ch, cph, 1);
CloseHandle(ready_semaphore);
}
void CreateSession(ConnectionHandler *ch, ClientPacketHandler *cph, int clientid){
FPOINT fp = {0, 0};
if (!CreateDrawingWindow()) {
changeMyStatus(STATUS_ONLINE);
return;
}
printf("Creating session...");
vp = new ViewPort(g_hWndDrawingWindow);
objectman = new ObjectManager(clientid);
canvas = new Canvas(objectman, vp);
vp->setCanvas(canvas);
vp->setOverzoom(3.0);
vp->setZoomPan(1.0, &fp);
objectman->setCanvas(canvas);
connhand = ch;
tools[TOOL_ZOOM] = new ZoomTool(vp, ch, peer_cid);
tools[TOOL_PAN] = new PanTool(vp, ch, peer_cid);
tools[TOOL_LINE] = new PolylineTool(vp, objectman, ch, peer_cid);
tools[TOOL_POINTER] = new ArrowTool(objectman, vp, ch, peer_cid);
ChangeTool(IDM_DRAWING_TOOLS_LINE);
ChangeColor(IDM_DRAWING_COLOR_BLACK);
Object *bgObj = NULL;
RECT ext = { 0, 0, 1280, 1280 };
if (filename) {
try {
bgObj = new BitmapObject(new Win32Bitmap(filename, rotate));
((BitmapObject *)bgObj)->getPixelBounds(&ext);
} catch (char *str) {
printf("Error: %s\n", str);
if(delete_file){
DeleteFile(filename);
filename = NULL;
}
}
}
if (!bgObj) {
bgObj = new BackgroundObject();
}
FRECT fext;
bgObj->getBounds(&fext);
canvas->setExtents(&fext, &ext);
objectman->addObject(bgObj, LAYER_BACK);
ShowWindow(g_hWndMainWindow, SW_HIDE); //GetParent(g_hWndDrawingWindow)
ShowWindow(g_hWndDrawingWindow, SW_SHOWNORMAL);
UpdateWindow(g_hWndDrawingWindow);
}
static void CleanUpSession(void) {
int i;
if (filename && delete_file) {
DeleteFile(filename);
filename = NULL;
}
objectman->setCanvas(NULL);
vp->setCanvas(NULL);
delete canvas;
canvas = NULL;
delete objectman;
objectman = NULL;
delete vp;
vp = NULL;
for (i = 0; i < NUM_TOOLS; i++) {
delete tools[i];
tools[i] = NULL;
}
changeMyStatus(STATUS_ONLINE);
ShowWindow(g_hWndMainWindow, SW_SHOWNORMAL);
}
void setSessionReady(int cid, bool success){
peer_cid = cid;
ready_success = success;
ReleaseSemaphore(ready_semaphore, 1, NULL);
}
void joinSession(int cid, WCHAR *fname, bool rot){
peer_cid = cid;
filename = _wcsdup(fname);
rotate = rot;
wprintf(L"in join session: filename = %s.\n", filename);
PostMessage(g_hWndMainWindow, WM_CREATESESSION, 0, 0);
delete_file = true;
}
void closeSession(void){
MessageBox(g_hWndDrawingWindow, L"Client left the session.", L"Disconnected", MB_OK);
PostMessage(g_hWndDrawingWindow, WM_CLOSE, NULL, NULL);
}
static void ChangeColor(int idm) {
static int oldidm = -1;
COLORREF color;
HMENU hmnu;
switch (idm) {
case IDM_DRAWING_COLOR_BLACK: color = RGB(0, 0, 0); break;
case IDM_DRAWING_COLOR_WHITE: color = RGB(255, 255, 255); break;
case IDM_DRAWING_COLOR_RED: color = RGB(255, 0, 0); break;
case IDM_DRAWING_COLOR_GREEN: color = RGB(0, 255, 0); break;
case IDM_DRAWING_COLOR_BLUE: color = RGB(0, 0, 255); break;
default: break;
}
((PolylineTool *)tools[TOOL_LINE])->setColor(color);
hmnu = GetMenu(g_hWndDrawingWindow);
if (oldidm != -1) {
CheckMenuItem(hmnu, oldidm, MF_BYCOMMAND | MF_UNCHECKED);
}
CheckMenuItem(hmnu, idm, MF_BYCOMMAND | MF_CHECKED);
oldidm = idm;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -