📄 winspec.cpp
字号:
//WinSpec.cpp, Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005 R.Lackner
//the entire code of this module is highly specific to Windows!
//
// This file is part of RLPlot.
//
// RLPlot 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.
//
// RLPlot 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 RLPlot; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include <stdio.h>
#include <math.h>
#include "rlplot.h"
#include "WinSpec.h"
#include "rlplot.rc"
#include "TheDialog.h"
extern int dlgtxtheight;
HINSTANCE hInstance;
HWND MainWnd = 0L;
HACCEL accel;
bool isWIN95 = false;
extern tag_Units Units[];
extern GraphObj *CurrGO; //Selected Graphic Objects
extern Graph *CurrGraph;
extern char *WWWbrowser;
extern char *LoadFile;
extern Default defs;
extern char TmpTxt[];
extern UndoObj Undo;
const char name[] = "RLPLOT1";
static unsigned int cf_rlpgraph = RegisterClipboardFormat("rlp_graph");
static unsigned int cf_rlpobj = RegisterClipboardFormat("rlp_obj");
static unsigned int cf_rlpxml = RegisterClipboardFormat("rlp_xml");
long FAR PASCAL WndProc(HWND, UINT, UINT, LONG);
PrintWin *Printer = 0L;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// I/O File name dialogs
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get a new file name to store data in
char *SaveDataAsName(char *oldname)
{
static char szFile[500], szFileTitle[256];
static char szFilter[] = "RLPlot workbook (*.rlw)\0*.rlw\0data files (*.csv)\0*.csv\0tab separated (*tsv)\0"
"*.tsv\0XML (*.xml)\0*.xml\0";
OPENFILENAME ofn;
szFile[0] = '\0';
if(oldname)strcpy(szFile, oldname);
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetFocus();
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = defs.currPath;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
ofn.lpstrTitle = "Save Data As";
if(GetSaveFileName(&ofn)){
defs.FileHistory(szFile);
return szFile;
}
else return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get a new file name to store graph
char *SaveGraphAsName(char *oldname)
{
static char szFile[500], szFileTitle[256];
static char szFilter[] = "RLPlot Graph (*.RLP)\0*.rlp\0";
OPENFILENAME ofn;
szFile[0] = '\0';
if(oldname)strcpy(szFile, oldname);
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetFocus();
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = defs.currPath;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
ofn.lpstrTitle = "Save Graph As";
if(GetSaveFileName(&ofn)){
defs.FileHistory(szFile);
return szFile;
}
else return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get file name to read graph
char *OpenGraphName(char *oldname)
{
static char szFile[500], szFileTitle[256];
static char szFilter[] = "RLPlot Graph (*.RLP)\0*.rlp\0";
OPENFILENAME ofn;
szFile[0] = '\0';
if(oldname)strcpy(szFile, oldname);
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetFocus();
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = defs.currPath;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrTitle = "Open Graph";
if(GetOpenFileName(&ofn)){
defs.FileHistory(szFile);
return szFile;
}
else return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get a file name to load data
char *OpenDataName(char *oldname)
{
static char szFile[500], szFileTitle[256];
static char szFilter[] = "RLPlot workbook (*rlw)\0*.rlw\0data files (*.csv)\0*.csv\0"
"tab separated file (*.tsv)\0*.tsv\0"
"RLPlot Graph (*.rlp)\0*.rlp\0all files (*.*)\0*.*\0";
OPENFILENAME ofn;
szFile[0] = '\0';
if(oldname)strcpy(szFile, oldname);
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetFocus();
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = defs.currPath;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrTitle = "Open Data File";
if(GetOpenFileName(&ofn)){
defs.FileHistory(szFile);
return szFile;
}
else return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get a file name to export graph
void OpenExportName(GraphObj *g, char *oldname)
{
static char szFile[500], szFileTitle[256];
static char szFilter[] = "Scalable Vector Graphics (*.svg)\0*.svg\0"
"Encapsulated Post Script (*.eps)\0*.eps\0"
"MSWindows MetaFile(*.wmf)\0*.wmf\0Tag Image File Format (*.tif)\0*.tif\0";
OPENFILENAME ofn;
int i;
szFile[0] = '\0';
if(!g) return;
if(oldname)strcpy(szFile, oldname);
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetFocus();
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = defs.currPath;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
ofn.lpstrTitle = "Export Graph";
if(g && GetSaveFileName(&ofn)){
i = strlen(szFile);
g->Command(CMD_BUSY, 0L, 0L);
if(0==stricmp(".svg", szFile+i-4)) {
DoExportSvg(g, szFile, 0L);
}
else if(0==stricmp(".wmf", szFile+i-4)) {
DoExportWmf(g, szFile, 600.0f, 0L);
}
else if(0==stricmp(".eps", szFile+i-4)) {
DoExportEps(g, szFile, 0L);
}
else if(0==stricmp(".tif", szFile+i-4)) {
DoExportTif(g, szFile, 0L);
}
else if(0==stricmp(".tiff", szFile+i-5)) {
DoExportTif(g, szFile, 0L);
}
else ErrorBox("Unknown file extension or format");
g->Command(CMD_MOUSECURSOR, 0L, 0L);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Common alert boxes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void InfoBox(char *Msg)
{
MessageBox(0, Msg, "Info", MB_OK | MB_ICONINFORMATION);
}
void ErrorBox(char *Msg)
{
MessageBox(0, Msg, "ERROR", MB_OK | MB_ICONSTOP);
}
bool YesNoBox(char *Msg)
{
if(IDYES == MessageBox(0, Msg, "RLPlot", MB_YESNO | MB_ICONQUESTION)) return true;
return false;
}
int YesNoCancelBox(char *Msg)
{
int res;
res = MessageBox(0, Msg, "RLPlot", MB_YESNOCANCEL | MB_ICONQUESTION);
switch(res) {
case IDYES: return 1;
case IDNO: return 0;
default: return 2;
}
return 0;
}
void Qt_Box()
{
MessageBox(0, "No Qt installed\nunder Windows", "Error", MB_OK | MB_ICONQUESTION);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Display blinking text cursor
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anyOutput *oTxtCur = 0L, *oCopyMark = 0L;
RECT rTxtCur, rCopyMark;
bool bTxtCur = false, bTxtCurIsVis = false;
DWORD cTxtCur = 0x0L;
HWND hwndTxtCur = 0L;
int iTxtCurCount = 0;
POINT ptTxtCurLine[2];
BitMapWin *bmCopyMark = 0L;
void HideTextCursor()
{
if(oTxtCur) {
bTxtCur = false;
oTxtCur->UpdateRect(&rTxtCur, false);
}
oTxtCur = 0L;
}
void HideTextCursorObj(anyOutput *out)
{
if(oTxtCur && oTxtCur == out) HideTextCursor();
}
void ShowTextCursor(anyOutput *out, RECT *disp, DWORD color)
{
HWND wnd = GetFocus();
cTxtCur = color;
HideTextCursor();
oTxtCur = out;
iTxtCurCount = -2;
memcpy(&rTxtCur, disp, sizeof(RECT));
ptTxtCurLine[0].x = rTxtCur.left; ptTxtCurLine[0].y = rTxtCur.top;
ptTxtCurLine[1].x = rTxtCur.right; ptTxtCurLine[1].y = rTxtCur.bottom;
rTxtCur.bottom++; rTxtCur.right++;
oTxtCur->ShowLine(ptTxtCurLine, 2, cTxtCur);
bTxtCurIsVis = bTxtCur = true;
}
void HideCopyMark()
{
if(bmCopyMark && oCopyMark) {
oCopyMark->UpdateRect(&rCopyMark, false);
delete bmCopyMark;
}
bmCopyMark = 0L; oCopyMark = 0L;
}
void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec)
{
int i;
HideCopyMark();
if(!out || !mrk || !nRec) return;
oCopyMark = out;
rCopyMark.left = mrk[0].left; rCopyMark.right = mrk[0].right;
rCopyMark.top = mrk[0].top; rCopyMark.bottom = mrk[0].bottom;
for(i = 1; i < nRec; i++) {
UpdateMinMaxRect(&rCopyMark, mrk[i].left, mrk[i].top);
UpdateMinMaxRect(&rCopyMark, mrk[i].right, mrk[i].bottom);
}
bmCopyMark = new BitMapWin(rCopyMark.right - rCopyMark.left,
rCopyMark.bottom - rCopyMark.top, out->hres, out->vres);
}
LineDEF liCopyMark1 = {0.0f, 1.0f, 0x00ffffffL, 0L};
LineDEF liCopyMark2 = {0.0f, 6.0f, 0x0L, 0xf0f0f0f0L};
long FAR PASCAL TimerWndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
static POINT line[5];
static int cp_mark = 0;
switch(message) {
case WM_TIMER:
if(bmCopyMark && oCopyMark) {
bmCopyMark->CopyBitmap(0, 0, oCopyMark, rCopyMark.left, rCopyMark.top,
rCopyMark.right - rCopyMark.left, rCopyMark.bottom - rCopyMark.top, false);
bmCopyMark->SetLine(&liCopyMark1);
line[0].x = line[1].x = line[4].x = 0;
line[0].y = line[3].y = line[4].y = 0;
line[1].y = line[2].y = rCopyMark.bottom-rCopyMark.top-1;
line[2].x = line[3].x = rCopyMark.right-rCopyMark.left-1;
bmCopyMark->oPolyline(line, 5);
bmCopyMark->SetLine(&liCopyMark2);
bmCopyMark->RLP.finc = 1.0; bmCopyMark->RLP.fp = (cp_mark & 0x7);
bmCopyMark->oPolyline(line, 5);
oCopyMark->ShowBitmap(rCopyMark.left, rCopyMark.top, bmCopyMark);
cp_mark++;
if(bTxtCurIsVis && oTxtCur && ptTxtCurLine[0].y != ptTxtCurLine[1].y &&
oTxtCur == oCopyMark && OverlapRect(&rCopyMark, &rTxtCur)){
oTxtCur->ShowLine(ptTxtCurLine, 2, cTxtCur);
}
}
if(!oTxtCur || (ptTxtCurLine[0].x == ptTxtCurLine[1].x &&
ptTxtCurLine[0].y == ptTxtCurLine[1].y)) return 0;
iTxtCurCount++;
if(iTxtCurCount<0) oTxtCur->ShowLine(ptTxtCurLine, 2, cTxtCur);
if(iTxtCurCount < 4) return 0;
iTxtCurCount = 0;
if(bTxtCur && oTxtCur) {
if(!bTxtCurIsVis) {
oTxtCur->ShowLine(ptTxtCurLine, 2, cTxtCur);
bTxtCurIsVis = true;
}
else {
oTxtCur->UpdateRect(&rTxtCur, false);
bTxtCurIsVis = false;
}
}
return 0;
case WM_QUERYOPEN:
case WM_SIZE:
return 0;
case WM_DESTROY:
KillTimer(hwnd, 1);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void InitTextCursor(bool init)
{
WNDCLASS wndclass;
if (init) {
wndclass.style = CS_BYTEALIGNWINDOW | CS_DBLCLKS;
wndclass.lpfnWndProc = TimerWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = 0L;
wndclass.hCursor = 0L;
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = 0L;
wndclass.lpszClassName = "RLP_TIMER";
RegisterClass(&wndclass);
if((hwndTxtCur = CreateWindow("RLP_TIMER", 0L, WS_OVERLAPPEDWINDOW,
0, 0, 0, 0, NULL, NULL, hInstance, NULL))){
SetTimer(hwndTxtCur, 1, 150, 0L);
}
}
else if(hwndTxtCur) {
DestroyWindow(hwndTxtCur);
hwndTxtCur = 0L;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Process paste command: check for clipboard contents
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TestClipboard(GraphObj *g)
{
HANDLE hmem = 0;
unsigned char *ptr;
if(!g) return;
OpenClipboard(MainWnd);
if(g->Id == GO_SPREADDATA) {
if((hmem = GetClipboardData(cf_rlpxml)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) g->Command(CMD_PASTE_XML, ptr, 0L);
else if((hmem = GetClipboardData(CF_TEXT)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) ProcMemData(g, ptr, true);
else if((hmem = GetClipboardData(cf_rlpobj)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr);
else if((hmem = GetClipboardData(cf_rlpgraph)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr);
}
else if(g->Id == GO_PAGE) {
if((hmem = GetClipboardData(cf_rlpobj)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr);
else if((hmem = GetClipboardData(cf_rlpgraph)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr);
}
else if(g->Id == GO_GRAPH) TestClipboard(g->parent);
if(hmem) GlobalUnlock(hmem);
CloseClipboard();
}
void EmptyClip()
{
HideCopyMark();
OpenClipboard(MainWnd);
EmptyClipboard();
CloseClipboard();
}
void CopyText(char *txt, int len)
{
HGLOBAL hmem;
unsigned char* buf;
if(!txt || !txt[0]) return;
if(!len) len = strlen(txt);
OpenClipboard(MainWnd);
EmptyClipboard();
if(hmem = GlobalAlloc(GMEM_MOVEABLE, len+2)) {
if(buf = (unsigned char *)GlobalLock(hmem)) {
memcpy(buf, txt, len); buf[len] = 0;
GlobalUnlock(hmem);
SetClipboardData(CF_TEXT, hmem);
}
}
CloseClipboard();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -