📄 wince_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 "wince_drawing.h"
#include "wince_client.h"
#include "wince_buddies.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/ZoomTool.h"
#include "../common/PanTool.h"
#include "../common/PolylineTool.h"
#include "../common/ArrowTool.h"
#include "Camera.h"
#include "WinCEBitmap.h"
#define DRAG_THRESHOLD 4.0
// Choose what parts of the program to compile
#define USE_CAMERA
#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 Camera *camera;
static WCHAR *filename = NULL;
static ConnectionHandler *connhand;
static HANDLE ready_semaphore = NULL;
static bool ready_success = false;
static int peer_cid = -1;
static bool rotate;
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(void);
static void ChangeFollowMe(void);
void setSessionReady(int cid, bool success);
//deceleared in wince_client.cpp
void SendBye(int cid);
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_COLOR:
ChangeColor();
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;
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:
{
PacketBounds *packet = (PacketBounds *)lParam;
bool follow = packet->getFollowMe();
if(follow){
FRECT rect;
packet->getBounds(&rect);
vp->setBounds(&rect);
delete packet;
//the packet is returned just to update the xor-rect in win32 client.
vp->getBounds(&rect);
packet = new PacketBounds(rect, false);
packet->setCId(peer_cid);
connhand->sendPacket(packet);
}
else
delete(packet);
}
break;
case WM_CREATE:
SHMENUBARINFO mbi;
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.dwFlags = SHCMBF_COLORBK | SHCMBF_HIDESIPBUTTON;
mbi.hwndParent = hWnd;
mbi.nToolBarId = IDR_DRAWING_MENU;
mbi.hInstRes = g_hInst;
mbi.nBmpId = IDB_ICONS;
mbi.cBmpImages = 17;
mbi.clrBk = RGB(0, 0, 0);
if (!SHCreateMenuBar(&mbi))
{
g_hWndDrawingMenuBar = NULL;
}
else
{
g_hWndDrawingMenuBar = mbi.hwndMB;
}
// Initialize the shell activate info structure
memset(&s_sai, 0, sizeof (s_sai));
s_sai.cbSize = sizeof (s_sai);
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:
DestroyWindow(g_hWndDrawingWindow);
break;
case WM_DESTROY:
CommandBar_Destroy(g_hWndDrawingMenuBar);
CleanUpSession();
break;
case WM_ACTIVATE:
// Notify shell of our activate message
SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
break;
case WM_SETTINGCHANGE:
SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
break;
#ifdef _DEVICE_RESOLUTION_AWARE
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;
#endif
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
static void ChangeTool(int idm) {
static int oldidm = -1;
int tool;
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;
}
canvas->setTool(tools[tool]);
TBBUTTONINFO tbbi = {0};
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_IMAGE;
if (oldidm != -1) {
SendMessage(g_hWndDrawingMenuBar, TB_GETBUTTONINFO, oldidm, (LPARAM)&tbbi);
tbbi.iImage &= ~1;
SendMessage(g_hWndDrawingMenuBar, TB_SETBUTTONINFO, oldidm, (LPARAM)&tbbi);
}
SendMessage(g_hWndDrawingMenuBar, TB_GETBUTTONINFO, idm, (LPARAM)&tbbi);
tbbi.iImage |= 1;
SendMessage(g_hWndDrawingMenuBar, TB_SETBUTTONINFO, idm, (LPARAM)&tbbi);
oldidm = idm;
}
static void ChangeColor(void) {
static int selected_color = 0;
static const COLORREF colors[] = {
RGB(0, 0, 0),
RGB(255, 255, 255),
RGB(255, 0, 0),
RGB(0, 255, 0),
RGB(0, 0, 255)
};
static const int num_colors = sizeof(colors) / sizeof(colors[0]);
selected_color = (selected_color + 1) % num_colors;
((PolylineTool *)tools[TOOL_LINE])->setColor(colors[selected_color]);
TBBUTTONINFO tbbi = {0};
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_IMAGE;
tbbi.iImage = 10 + selected_color;
SendMessage(g_hWndDrawingMenuBar, TB_SETBUTTONINFO, IDM_DRAWING_COLOR, (LPARAM)&tbbi);
}
static void ChangeFollowMe(void) {
followMe = !followMe;
((ZoomTool *)tools[TOOL_ZOOM])->setFollowMe(followMe);
((PanTool *)tools[TOOL_PAN])->setFollowMe(followMe);
TBBUTTONINFO tbbi = {0};
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_IMAGE;
tbbi.iImage = followMe ? 16 : 15;
SendMessage(g_hWndDrawingMenuBar, TB_SETBUTTONINFO, IDM_DRAWING_TOOLS_FOLLOWME, (LPARAM)&tbbi);
}
static bool CreateDrawingWindow(void) {
HWND hWnd = CreateWindow(szDrawingWindowClass, szTitle, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 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;
// Go fullscreen and adjust size to make room for toolbar.
SHFullScreen(hWnd, SHFS_HIDETASKBAR);
RECT rc;
GetWindowRect(hWnd, &rc);
rc.top = 0;
if (g_hWndDrawingMenuBar)
{
RECT rcMenuBar;
GetWindowRect(g_hWndDrawingMenuBar, &rcMenuBar);
rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
}
MoveWindow(hWnd, rc.left, rc.top, rc.right, rc.bottom, TRUE);
return true;
}
void StartNewSession(ConnectionHandler *ch, ClientPacketHandler *cph, int cid, IMAGE_TYPE imagetype) {
WCHAR fsFile[512] = L"";
OPENFILENAME of;
switch(imagetype){
case(IMAGE_CAMERA):
camera = new Camera(g_hWndMainWindow);
filename = camera->Start();
rotate = true;
if(filename != NULL)
delete_file = true;
else
return;
break;
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
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)) {
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, rotate);
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()) {
return;
}
printf("Creating session...");
vp = new ViewPort(g_hWndDrawingWindow);
objectman = new ObjectManager(clientid);
canvas = new Canvas(objectman, vp);
vp->setCanvas(canvas);
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);
Object *bgObj = NULL;
RECT ext = { 0, 0, 1280, 1280 };
if (filename) {
try {
bgObj = new BitmapObject(new WinCEBitmap(filename, rotate));
((BitmapObject *)bgObj)->getPixelBounds(&ext);
} catch (char *str) {
printf("Error: %s\n", str);
if(delete_file){
DeleteFile(filename);
filename = NULL;
}
}
}
if (!filename) {
bgObj = new BackgroundObject();
}
FRECT fext;
bgObj->getBounds(&fext);
canvas->setExtents(&fext, &ext);
objectman->addObject(bgObj, LAYER_BACK);
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;
}
#ifdef USE_CAMERA
delete camera;
#endif
}
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);
if(filename != NULL)
delete_file = true;
rotate = rot;
wprintf(L"in join session: filename = %s.\n", filename);
PostMessage(g_hWndMainWindow, WM_CREATESESSION, 0, 0);
}
void closeSession(void){
MessageBox(g_hWndDrawingWindow, L"Client left the session.", L"Disconnected", MB_OK);
PostMessage(g_hWndDrawingWindow, WM_CLOSE, NULL, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -