mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
1292 lines
31 KiB
C++
1292 lines
31 KiB
C++
// TWL.CPP
|
|
/*
|
|
* Tiny, Terminal or Toy Windows Library
|
|
* Steve Donovan, Miningtek 1998
|
|
* based on SWL, 1995.
|
|
*/
|
|
|
|
//#define WIN32_LEAN_AND_MEAN
|
|
#define NO_STRICT
|
|
#include <windows.h>
|
|
#ifdef _WIN32
|
|
//# include <commctrl.h>
|
|
//# define COMMCTRL
|
|
# define LOW_WORD LOWORD
|
|
#else
|
|
# define LOW_WORD WORD
|
|
# define GWL_USERDATA 0
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#include "twl.h"
|
|
|
|
#define MAX_CMD_LINE 120
|
|
#define N_CMD_LINE 20
|
|
// *hack 1.2.8 make the window class distinct from YAWL;
|
|
// in general, it should be unique per process.
|
|
#define EW_CLASSNAME "EVNTWNDCLSS0"
|
|
#define POP_WNDCLSS "WNDCLSS"
|
|
|
|
static HINSTANCE hInst;
|
|
static int CmdShow;
|
|
static HANDLE hAccel=0,hModeless=0;
|
|
char obuff[BUFSIZE];
|
|
static char buff[MAX_CMD_LINE];
|
|
|
|
typedef unsigned char byte;
|
|
|
|
// Miscelaneous functions!!
|
|
long RGBF(float r, float g, float b)
|
|
//-------------------------------------
|
|
{ return RGB(byte(255*r),byte(255*g),byte(255*b)); }
|
|
|
|
long RGBI(int r, int g, int b)
|
|
{ return RGB(r,g,b); }
|
|
|
|
int exec(pchar s, int mode, bool do_wait)
|
|
//--------------------------------------
|
|
{
|
|
// return WinExec(s,mode);
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si;
|
|
TWin *lastw = TWin::get_active_window();
|
|
ZeroMemory(&si,sizeof(STARTUPINFO));
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = mode;
|
|
BOOL bRet = CreateProcess(NULL, s, NULL,NULL, // no security!
|
|
FALSE, // inherited handles
|
|
CREATE_NEW_CONSOLE, // creation flags
|
|
NULL,NULL,
|
|
&si, &pi);
|
|
if (!bRet) return 0;
|
|
if (do_wait) {
|
|
WaitForSingleObject(pi.hProcess,1000);
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
}
|
|
//process_id = pi.dwProcessId;
|
|
lastw->set_focus();
|
|
delete lastw;
|
|
return 1;
|
|
}
|
|
|
|
long current_time()
|
|
{ return GetTickCount(); }
|
|
|
|
bool get_key_state(int keycode)
|
|
{ return GetKeyState(keycode) < 0; }
|
|
|
|
int message(char *format,bool was_warning)
|
|
//----------------------------------------
|
|
{
|
|
//char *Args;
|
|
int ret;
|
|
|
|
// Args = (char *) &format + sizeof format;
|
|
// vsprintf(obuff,format,Args);
|
|
// ret = MessageBox(NULL,obuff,"Message",MB_ICONEXCLAMATION | MB_OKCANCEL);
|
|
|
|
ret = MessageBox(NULL,format,"Message",MB_ICONEXCLAMATION | MB_OKCANCEL);
|
|
if (ret == IDCANCEL) return 0; else return 1;
|
|
}
|
|
|
|
|
|
/// TDC ///////////////
|
|
|
|
TDC::TDC()
|
|
{
|
|
m_hdc = m_pen = m_font = m_brush = NULL;
|
|
m_twin = NULL;
|
|
}
|
|
|
|
TDC::~TDC()
|
|
{ }
|
|
|
|
void TDC::get(TWin *pw)
|
|
//---------------------
|
|
{
|
|
if(!pw) pw = m_twin;
|
|
m_hdc = GetDC(pw->handle());
|
|
}
|
|
|
|
void TDC::release(TWin *pw)
|
|
//--------------------------
|
|
{
|
|
if(!pw) pw = m_twin;
|
|
ReleaseDC(pw->handle(),m_hdc);
|
|
}
|
|
|
|
void TDC::kill()
|
|
//--------------
|
|
{ DeleteDC(m_hdc); }
|
|
|
|
Handle TDC::select(Handle obj)
|
|
//---------------------------
|
|
{ return SelectObject(m_hdc,obj); }
|
|
|
|
void TDC::select_stock(int val)
|
|
//----------------------------
|
|
{ select(GetStockObject(val)); }
|
|
|
|
void TDC::xor_pen()
|
|
//-----------------
|
|
{ SetROP2(m_hdc, GetROP2(m_hdc)==R2_XORPEN ? R2_COPYPEN : R2_XORPEN); }
|
|
|
|
void TDC::to_logical(Point *pt, int sz)
|
|
{ DPtoLP(m_hdc,(LPPOINT)pt,sz); }
|
|
|
|
void TDC::to_device(Point *pt, int sz)
|
|
{ LPtoDP(m_hdc,(LPPOINT)pt,sz); }
|
|
|
|
void TDC::set_colour(long colour)
|
|
{
|
|
COLORREF rgb = (COLORREF)colour;
|
|
get();
|
|
SetTextColor(m_hdc,rgb);
|
|
if(m_pen) DeleteObject(m_pen);
|
|
m_pen = CreatePen(PS_SOLID,0,rgb);
|
|
select(m_pen);
|
|
release();
|
|
}
|
|
|
|
void TDC::set_back_colour(long colour)
|
|
{
|
|
COLORREF rgb = (COLORREF)colour;
|
|
SetBkColor(m_hdc,rgb);
|
|
if(m_brush) DeleteObject(m_brush);
|
|
m_brush = CreateSolidBrush(rgb);
|
|
select(m_brush);
|
|
}
|
|
|
|
|
|
// this changes both the _pen_ and the _text_ colour
|
|
void TDC::set_colour(float r, float g, float b)
|
|
//----------------------------
|
|
{
|
|
set_colour(RGBF(r,g,b));
|
|
}
|
|
|
|
void TDC::set_back_colour(float r, float g, float b)
|
|
{
|
|
set_back_colour(RGBF(r,g,b));
|
|
}
|
|
|
|
void TDC::set_text_colour(long colour)
|
|
{ SetTextColor(m_hdc,colour); }
|
|
|
|
|
|
void TDC::set_text_align(int flags, bool update_cp)
|
|
//-------------------------------------------------
|
|
{
|
|
get();
|
|
SetTextAlign(m_hdc, flags | (update_cp ? TA_UPDATECP : 0));
|
|
release();
|
|
}
|
|
|
|
void TDC::get_text_extent(pchar text, int& w, int& h, TFont *font)
|
|
//----------------------------------------------------------------
|
|
{
|
|
SIZE sz;
|
|
HFONT oldfont;
|
|
get();
|
|
if (font) oldfont = select(*font);
|
|
#ifdef _WIN32
|
|
GetTextExtentPoint32(m_hdc,text,lstrlen(text),&sz);
|
|
#else
|
|
DWORD res = GetTextExtent(m_hdc,text,lstrlen(text));
|
|
sz.cx = LOWORD(res);
|
|
sz.cy = HIWORD(res);
|
|
#endif
|
|
if (font) select(oldfont);
|
|
release();
|
|
w = sz.cx;
|
|
h = sz.cy;
|
|
}
|
|
|
|
// wrappers around common graphics calls
|
|
void TDC::draw_text(pchar msg)
|
|
//---------------------------------------------------
|
|
{ TextOut(m_hdc,0,0,msg,lstrlen(msg)); }
|
|
|
|
void TDC::text_out(int x, int y, char *buff, int sz)
|
|
{
|
|
TextOut(m_hdc,x,y,buff,sz);
|
|
}
|
|
|
|
void TDC::move_to(int x, int y)
|
|
//----------------------------
|
|
{ MoveToEx(m_hdc,x,y,NULL); }
|
|
|
|
void TDC::line_to(int x, int y)
|
|
//-----------------------------
|
|
{ LineTo(m_hdc,x,y/*,NULL*/); }
|
|
|
|
void TDC::rectangle(const Rect& rt)
|
|
//---------------------------------
|
|
{ Rectangle(m_hdc, rt.left,rt.top,rt.right,rt.bottom); }
|
|
|
|
void TDC::ellipse(const Rect& rt)
|
|
//---------------------------------
|
|
{ Ellipse(m_hdc, rt.left,rt.top,rt.right,rt.bottom); }
|
|
|
|
void TDC::invert_rect(const Rect& rt)
|
|
//-----------------------------------
|
|
{ InvertRect(m_hdc,(RECT *)&rt); }
|
|
|
|
|
|
TClientDC::TClientDC(TEventWindow *ew)
|
|
{
|
|
set_hdc(ew->get_dc()->get_hdc());
|
|
set_twin(ew);
|
|
get();
|
|
}
|
|
|
|
TClientDC::~TClientDC()
|
|
{
|
|
release();
|
|
}
|
|
|
|
//// TGDIObj
|
|
|
|
void TGDIObj::destroy()
|
|
//---------------
|
|
{ if (m_hand) DeleteObject(m_hand); m_hand = NULL; }
|
|
|
|
//// TFont ////////
|
|
#define PLF ((LOGFONT *)m_pfont)
|
|
|
|
TFont::TFont()
|
|
{
|
|
m_pfont = (void *) new LOGFONT;
|
|
}
|
|
|
|
TFont::~TFont()
|
|
{
|
|
delete (LOGFONT *) m_pfont;
|
|
}
|
|
|
|
|
|
void TFont::set(pchar spec, int sz, int ftype)
|
|
//-------------------------------------------
|
|
{
|
|
LOGFONT&lf = *(LOGFONT *)m_pfont; // define an alias...
|
|
int wt = FW_NORMAL;
|
|
lf.lfHeight = sz;
|
|
if (ftype & BOLD) wt = FW_BOLD;
|
|
lf.lfWeight = wt;
|
|
lf.lfItalic = (ftype & ITALIC) ? TRUE: FALSE;
|
|
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
lf.lfCharSet = ANSI_CHARSET;
|
|
lf.lfQuality = PROOF_QUALITY;
|
|
lf.lfEscapement = 0;
|
|
lf.lfOrientation = 0;
|
|
lf.lfUnderline = 0;
|
|
lf.lfStrikeOut = 0;
|
|
lstrcpy(lf.lfFaceName,spec);
|
|
create();
|
|
}
|
|
|
|
/// copy constructor
|
|
TFont& TFont::operator = (const TFont& f)
|
|
//--------------------------------------
|
|
{
|
|
memcpy(m_pfont,f.m_pfont,sizeof(LOGFONT));
|
|
create();
|
|
return *this;
|
|
}
|
|
|
|
void TFont::create()
|
|
//------------------
|
|
{
|
|
destroy();
|
|
m_hand = CreateFontIndirect((LOGFONT *)m_pfont);
|
|
}
|
|
|
|
void TFont::set_name(pchar name)
|
|
//-------------------------------
|
|
{ lstrcpy(PLF->lfFaceName,name); create(); }
|
|
|
|
|
|
void TFont::set_size(int pts)
|
|
//----------------------------
|
|
{ PLF->lfHeight = pts; create(); }
|
|
|
|
void TFont::set_bold()
|
|
//-----------------------
|
|
{ PLF->lfWeight = FW_BOLD; create(); }
|
|
|
|
void TFont::set_italic()
|
|
//-----------------------
|
|
{ PLF->lfItalic = TRUE; create(); }
|
|
|
|
////// TWin ///////////
|
|
|
|
static void check_error()
|
|
{
|
|
LPVOID lpMsgBuf;
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
GetLastError(),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPTSTR) &lpMsgBuf,
|
|
0,
|
|
NULL
|
|
);
|
|
// Process any inserts in lpMsgBuf.
|
|
// ...(?)
|
|
// Display the string.
|
|
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
|
|
// Free the buffer.
|
|
LocalFree( lpMsgBuf );
|
|
}
|
|
|
|
TWin::TWin(TWin *parent, pchar winclss, pchar text, int id, dword styleEx)
|
|
//------------------------------------------------------------------------
|
|
{
|
|
DWORD style = WS_CHILD | WS_VISIBLE | styleEx;
|
|
HWND hwndChild = CreateWindowEx(WS_EX_LEFT,winclss,text,style,
|
|
0,0,CW_USEDEFAULT,CW_USEDEFAULT,
|
|
parent->m_hwnd, (HMENU)id, hInst,NULL);
|
|
set(hwndChild);
|
|
check_error();
|
|
}
|
|
|
|
void TWin::update()
|
|
//-----------------
|
|
{
|
|
UpdateWindow(m_hwnd);
|
|
}
|
|
|
|
static inline bool as_bool(int val)
|
|
{ return val ? true : false; }
|
|
|
|
static inline bool as_bool(void *ptr)
|
|
{ return ptr ? true : false; }
|
|
|
|
bool TWin::is_visible()
|
|
{
|
|
return as_bool(IsWindowVisible(m_hwnd));
|
|
}
|
|
|
|
void TWin::invalidate(Rect *lprt)
|
|
{ InvalidateRect(m_hwnd,(LPRECT)lprt,TRUE); }
|
|
|
|
void TWin::get_rect(Rect &rt)
|
|
//---------------------------
|
|
{
|
|
GetWindowRect(m_hwnd,(LPRECT)&rt);
|
|
}
|
|
|
|
void TWin::get_client_rect(Rect &rt)
|
|
{
|
|
GetClientRect(m_hwnd,(LPRECT)&rt);
|
|
}
|
|
|
|
Point TWin::to_screen(Point pt)
|
|
{ ClientToScreen(m_hwnd,(LPPOINT)&pt); return pt; }
|
|
|
|
Point TWin::to_client(Point pt)
|
|
{ ScreenToClient(m_hwnd,(LPPOINT)&pt); return pt; }
|
|
|
|
|
|
int TWin::width()
|
|
//---------------
|
|
{
|
|
Rect rt; get_rect(rt); return rt.right - rt.left;
|
|
}
|
|
|
|
int TWin::height()
|
|
//----------------
|
|
{
|
|
Rect rt; get_rect(rt); return rt.bottom - rt.top;
|
|
}
|
|
|
|
void TWin::set_text(pchar str)
|
|
//---------------------------
|
|
{ SetWindowText(m_hwnd, str); }
|
|
|
|
pchar TWin::get_text(pchar str, int sz)
|
|
//-------------------------------------
|
|
{ GetWindowText(m_hwnd,str,sz); return str; }
|
|
|
|
// These guys work with the specified _child_ of the window
|
|
|
|
void TWin::set_text(int id, pchar str)
|
|
//-------------------------------------
|
|
{ SetDlgItemText(m_hwnd,id,str); }
|
|
|
|
void TWin::set_int(int id, int val)
|
|
//-------------------------------------
|
|
{ SetDlgItemInt(m_hwnd,id,val,TRUE); }
|
|
|
|
pchar TWin::get_text(int id, pchar str, int sz)
|
|
//--------------------------------------------
|
|
{ GetDlgItemText(m_hwnd,id,str,sz); return str; }
|
|
|
|
void TWin::scroll(int dx, int dy)
|
|
{ ScrollWindow(m_hwnd,dx,dy,NULL,NULL); }
|
|
|
|
int TWin::get_int(int id)
|
|
//-----------------------
|
|
{ BOOL success;
|
|
return (int)GetDlgItemInt(m_hwnd,id,&success,TRUE);
|
|
}
|
|
|
|
TWin *
|
|
TWin::get_twin(int id)
|
|
//--------------------
|
|
{
|
|
HWND hwnd = GetDlgItem(m_hwnd,id);
|
|
if (hwnd) {
|
|
// Extract the 'this' pointer, if it exists
|
|
TWin *pwin = (TWin *)GetWindowLong(hwnd,0);
|
|
// if not, then just wrap up the handle
|
|
if (!pwin) pwin = new TWin(hwnd);
|
|
return pwin;
|
|
}
|
|
else return NULL;
|
|
}
|
|
|
|
TWin *
|
|
TWin::get_active_window()
|
|
{
|
|
return new TWin(GetActiveWindow());
|
|
}
|
|
|
|
void TWin::set_focus()
|
|
{
|
|
SetFocus((HWND)m_hwnd);
|
|
}
|
|
|
|
int
|
|
TWin::get_id()
|
|
//------------
|
|
{ return GetWindowLong(m_hwnd,GWL_ID); }
|
|
|
|
void TWin::close()
|
|
{
|
|
DestroyWindow(m_hwnd);
|
|
}
|
|
|
|
void TWin::resize(int x0, int y0, int w, int h)
|
|
//--------------------------------------------
|
|
{
|
|
MoveWindow(m_hwnd,x0,y0,w,h,TRUE);
|
|
//*SJD* This is a hack to ensure that WCON child console
|
|
// windows do indeed appear on the top on Win95 systems.
|
|
on_top();
|
|
}
|
|
|
|
void TWin::on_top() // *add 0.9.4
|
|
{
|
|
SetWindowPos(handle(),HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
|
}
|
|
|
|
void TWin::resize(int w, int h)
|
|
//------------------------------
|
|
{ SetWindowPos(handle(),NULL,0,0,w,h,SWP_NOMOVE); }
|
|
|
|
void TWin::move(int x0, int y0)
|
|
//------------------------------
|
|
{ SetWindowPos(handle(),NULL,x0,y0,0,0,SWP_NOSIZE); }
|
|
|
|
void TWin::show(int how)
|
|
//--------------------------------
|
|
{ ShowWindow(m_hwnd,how); }
|
|
|
|
void TWin::set_style(dword s)
|
|
//---------------------------
|
|
{ SetWindowLong(m_hwnd,GWL_STYLE,s); }
|
|
|
|
int TWin::send_msg(int msg, int wparam, int lparam) const
|
|
//---------------------------------------------------
|
|
{ return SendMessage(m_hwnd, msg, wparam, lparam); }
|
|
|
|
int TWin::post_msg(int msg, int wparam, int lparam) const
|
|
{ return PostMessage(m_hwnd, msg, wparam, lparam); }
|
|
|
|
TWin *TWin::create_child(pchar winclss, pchar text, int id, dword styleEx)
|
|
//------------------------------------------------------------------------
|
|
{
|
|
return new TWin(this,winclss,text,id,styleEx);
|
|
}
|
|
|
|
int TWin::message(char *msg, int type)
|
|
//-------------------------------------
|
|
{
|
|
int flags;
|
|
char *title;
|
|
if (type == MSG_ERROR) { flags = MB_ICONERROR | MB_OK; title = "Error"; } else
|
|
if (type == MSG_WARNING) { flags = MB_ICONEXCLAMATION | MB_OKCANCEL; title = "Warning"; }
|
|
else { flags = MB_OK; title = "Message"; }
|
|
return MessageBox(m_hwnd, msg, title,flags);
|
|
}
|
|
|
|
TScrollBar::TScrollBar(Handle hwnd, int type)
|
|
: TWin(hwnd),m_type(type)
|
|
{
|
|
}
|
|
|
|
void TScrollBar::set_range(int rmin, int rmax, bool repaint/*=false*/)
|
|
{
|
|
SetScrollRange(m_hwnd,m_type,rmin,rmax,repaint);
|
|
}
|
|
|
|
void TScrollBar::set_pos(int rpos, bool repaint/*=false*/)
|
|
{
|
|
SetScrollPos(m_hwnd,m_type,rpos,repaint);
|
|
}
|
|
|
|
int TScrollBar::get_pos()
|
|
{
|
|
return GetScrollPos(m_hwnd,m_type);
|
|
}
|
|
|
|
//----TEventWindow class member definitions---------------------
|
|
TEventWindow::TEventWindow(pchar caption, TWin *parent, dword style)
|
|
//-----------------------------------------------------------------
|
|
{
|
|
set_defaults();
|
|
if (style) m_style |= style;
|
|
create_window(caption, parent);
|
|
get_dc()->set_text_align(TA_TOP | TA_LEFT);
|
|
enable_resize(true);
|
|
}
|
|
|
|
TEventWindow::~TEventWindow()
|
|
{
|
|
if (m_timer) kill_timer();
|
|
if (m_dc) delete m_dc;
|
|
DestroyWindow((HWND)m_hwnd);
|
|
}
|
|
|
|
void TEventWindow::pre_create() {}
|
|
|
|
void TEventWindow::vert_scroll()
|
|
{
|
|
m_sb_vert = (TScrollBar *)this; // just to flag!
|
|
}
|
|
|
|
void TEventWindow::create_window(pchar caption, TWin *parent)
|
|
//-------------------------------------------------------------------
|
|
{
|
|
HWND hParent;
|
|
void *CreatParms[2];
|
|
pre_create();
|
|
m_dc = new TDC;
|
|
CreatParms[0] = (void *)this;
|
|
if (parent) hParent = parent->handle(); else hParent = NULL;
|
|
m_hwnd = CreateWindow (EW_CLASSNAME, caption, m_style,
|
|
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
|
|
hParent,NULL, hInst, CreatParms);
|
|
if(m_style & WS_VSCROLL) m_sb_vert = new TScrollBar(m_hwnd,SB_VERT);
|
|
set_window();
|
|
}
|
|
|
|
void TEventWindow::set_defaults()
|
|
//-------------------------------
|
|
{
|
|
m_style = WS_OVERLAPPEDWINDOW | CS_DBLCLKS;
|
|
m_bkgnd_brush = GetStockObject (WHITE_BRUSH /*LTGRAY_BRUSH*/);
|
|
m_bk_color = RGB(192,192,192);
|
|
m_hmenu = NULL;
|
|
m_timer = 0;
|
|
m_dispatcher = NULL;
|
|
m_dc = NULL;
|
|
m_bail_out = false;
|
|
m_sb_vert = NULL;
|
|
}
|
|
|
|
void TEventWindow::add_handler(AbstractMessageHandler *m_hand)
|
|
{
|
|
if (!m_dispatcher) m_dispatcher = m_hand;
|
|
else m_dispatcher->add_handler(m_hand);
|
|
}
|
|
|
|
void TEventWindow::update_data()
|
|
{
|
|
get_handler()->write();
|
|
}
|
|
|
|
void TEventWindow::update_controls()
|
|
{
|
|
get_handler()->read();
|
|
}
|
|
|
|
bool TEventWindow::cant_resize()
|
|
{
|
|
return !m_do_resize;
|
|
}
|
|
|
|
int TEventWindow::metrics(int ntype)
|
|
//----------------------------------
|
|
// Encapsulates what we need from GetSystemMetrics() and GetTextMetrics()
|
|
{
|
|
if (ntype < TM_CAPTION_HEIGHT) { // text metrics
|
|
TEXTMETRIC tm;
|
|
GetTextMetrics(get_dc()->get_hdc(),&tm);
|
|
if (ntype == TM_CHAR_HEIGHT) return tm.tmHeight; else
|
|
if (ntype == TM_CHAR_WIDTH) return tm.tmMaxCharWidth;
|
|
} else {
|
|
switch(ntype) {
|
|
case TM_CAPTION_HEIGHT: return GetSystemMetrics(SM_CYMINIMIZED);
|
|
case TM_MENU_HEIGHT: return GetSystemMetrics(SM_CYMENU);
|
|
case TM_CLIENT_EXTRA:
|
|
return metrics(TM_CAPTION_HEIGHT) + (m_hmenu != NULL) ? metrics(TM_MENU_HEIGHT) : 0;
|
|
case TM_SCREEN_WIDTH: return GetSystemMetrics(SM_CXMAXIMIZED);
|
|
case TM_SCREEN_HEIGHT: return GetSystemMetrics(SM_CYMAXIMIZED);
|
|
default: return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void TEventWindow::client_resize(int cwidth, int cheight)
|
|
{
|
|
// *SJD* This allows for menus etc - really is a frame window method??
|
|
resize(cwidth,cheight + metrics(TM_CLIENT_EXTRA));
|
|
}
|
|
|
|
void TEventWindow::enable_resize(bool do_resize, int w, int h)
|
|
{
|
|
m_do_resize = do_resize;
|
|
m_fixed_size.x = w;
|
|
m_fixed_size.y = h;
|
|
}
|
|
|
|
POINT TEventWindow::fixed_size()
|
|
{
|
|
return m_fixed_size;
|
|
}
|
|
|
|
void TEventWindow::cursor(CursorType curs)
|
|
{
|
|
HCURSOR new_cursor;
|
|
if (curs == RESTORE) new_cursor = m_old_cursor;
|
|
else
|
|
switch(curs) {
|
|
case HOURGLASS: new_cursor = LoadCursor(NULL,IDC_WAIT); break;
|
|
}
|
|
SetCursor(new_cursor);
|
|
}
|
|
|
|
|
|
void TEventWindow::set_window()
|
|
//-----------------------------
|
|
{
|
|
set(m_hwnd);
|
|
|
|
// set_win(*this); //...set up DC part.....??
|
|
}
|
|
|
|
void TEventWindow::set_background(float r, float g, float b)
|
|
//-----------------------------------------
|
|
{
|
|
COLORREF rgb = RGBF(r,g,b);
|
|
m_bkgnd_brush = CreateSolidBrush(rgb);
|
|
get_dc()->get(this);
|
|
SetBkColor(get_dc()->get_hdc(),rgb);
|
|
get_dc()->select(m_bkgnd_brush);
|
|
m_bk_color = rgb;
|
|
get_dc()->release(this);
|
|
invalidate();
|
|
}
|
|
|
|
void TEventWindow::set_menu(char *res)
|
|
//------------------------------------
|
|
{
|
|
if (m_hmenu) DeleteObject(m_hmenu);
|
|
set_menu(LoadMenu(hInst,res));
|
|
}
|
|
|
|
void TEventWindow::set_menu(Handle menu)
|
|
//------------------------------------
|
|
{
|
|
m_hmenu = menu;
|
|
SetMenu(m_hwnd,menu);
|
|
}
|
|
|
|
void TEventWindow::check_menu(int id, bool check)
|
|
{
|
|
CheckMenuItem(m_hmenu,id, MF_BYCOMMAND | (check ? MF_CHECKED : MF_UNCHECKED));
|
|
}
|
|
|
|
void TEventWindow::show(int cmd_show)
|
|
//-----------------------------------
|
|
{
|
|
// default: use the 'nCmdShow' we were _originally_ passed
|
|
if (! cmd_show) cmd_show = CmdShow;
|
|
ShowWindow(m_hwnd,cmd_show);
|
|
}
|
|
|
|
void TEventWindow::create_timer(int msec)
|
|
//---------------------------------------
|
|
{
|
|
if(m_timer) kill_timer();
|
|
m_timer = SetTimer(m_hwnd,1,msec,NULL);
|
|
}
|
|
|
|
void TEventWindow::kill_timer()
|
|
//-----------------------------
|
|
{ KillTimer(m_hwnd, m_timer); }
|
|
|
|
// *fix 1.2.2 (Eric) We were spending an excessive amount of time doing idle processing
|
|
#ifdef BUILD_WITH_GTK
|
|
void special_idle(); // in UCW_GTK
|
|
#else
|
|
void special_idle() { WaitMessage(); }
|
|
#endif
|
|
|
|
// Message Loop!
|
|
// *NB* this loop shd cover ALL cases, controlled by global
|
|
// variables like mdi_sysaccell, accell, hModelessDlg, etc.
|
|
// 31/08/00 - there's a bail out flag - not perhaps the
|
|
// most elegant method, but it'll do.
|
|
int TEventWindow::run()
|
|
//---------------------
|
|
{
|
|
MSG msg;
|
|
while (TRUE) {
|
|
if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE)) {
|
|
if (msg.message == WM_QUIT) break;
|
|
if (m_bail_out) { m_bail_out = false; return -1; }
|
|
if (! hAccel || !TranslateAccelerator(m_hwnd,hAccel,&msg)) {
|
|
if (! hModeless || !IsDialogMessage(hModeless,&msg)) {
|
|
TranslateMessage (&msg) ;
|
|
DispatchMessage (&msg) ;
|
|
}
|
|
}
|
|
}
|
|
else special_idle();
|
|
}
|
|
return msg.wParam ;
|
|
}
|
|
|
|
|
|
static unsigned long mMainThread;
|
|
|
|
void set_main_thread(unsigned long id)
|
|
{
|
|
mMainThread = id; // GetCurrentThreadId();
|
|
}
|
|
|
|
void TEventWindow::quit_loop()
|
|
{
|
|
m_bail_out = true;
|
|
//post_msg(WM_CHAR,' ',1);
|
|
ULONG id = GetWindowThreadProcessId((HWND)handle(),NULL);
|
|
BOOL res = PostThreadMessage(id,WM_CHAR,' ',1);
|
|
}
|
|
|
|
// Place holder functions - no functionality offered at this level!
|
|
void TEventWindow::size(int,int) {}
|
|
void TEventWindow::on_move() {}
|
|
|
|
bool TEventWindow::command(int) { return true; }
|
|
bool TEventWindow::sys_command(int) { return false; }
|
|
void TEventWindow::paint(TDC&) {}
|
|
void TEventWindow::mouse_down(Point&) {}
|
|
void TEventWindow::mouse_up(Point&) { }
|
|
void TEventWindow::right_mouse_down(Point&) {}
|
|
void TEventWindow::mouse_move(Point&) { }
|
|
void TEventWindow::mouse_double_click(Point& pt) { }
|
|
void TEventWindow::focus(bool) {}
|
|
void TEventWindow::keydown(int) { }
|
|
void TEventWindow::on_char(int,int) { }
|
|
void TEventWindow::destroy() { }
|
|
void TEventWindow::timer() { }
|
|
void TEventWindow::vscroll(int code, int posn) { }
|
|
int TEventWindow::handle_user(long lparam, long wparam) { return 0; }
|
|
|
|
////// Members of TFrameWindow
|
|
|
|
TFrameWindow::TFrameWindow(pchar caption, TWin *cli, int style, TWin *parent)
|
|
: TEventWindow(caption,parent,style)
|
|
{
|
|
// int SBParts[2];
|
|
set_client(cli);
|
|
#ifdef COMMCTRL
|
|
/*
|
|
m_status = CreateStatusWindow(WS_CHILD | WS_BORDER | WS_VISIBLE,
|
|
"", m_hwnd, 1);
|
|
if(!m_status) set_text("no status");
|
|
SBParts[0] = width()/2;
|
|
SBParts[1] = -1;
|
|
SendMessage(m_status,SB_SETPARTS,2,(LPARAM)SBParts);
|
|
*/
|
|
m_status = NULL; // for now!!
|
|
#else
|
|
m_status = NULL;
|
|
#endif
|
|
}
|
|
|
|
TFrameWindow::~TFrameWindow()
|
|
{
|
|
delete m_client;
|
|
}
|
|
|
|
void TFrameWindow::set_status_text(int id, pchar txt)
|
|
{
|
|
#ifdef COMMCTRL
|
|
SendMessage(m_status,SB_SETTEXT,id,(LPARAM)txt);
|
|
#endif
|
|
}
|
|
|
|
void TFrameWindow::destroy()
|
|
//....overrides the default w/ application-closing behaviour!!
|
|
{
|
|
PostQuitMessage(0);
|
|
}
|
|
|
|
void TFrameWindow::set_client(TWin *cli)
|
|
{
|
|
m_client = cli;
|
|
if (m_client) {
|
|
m_client->show();
|
|
}
|
|
}
|
|
|
|
void TFrameWindow::size()
|
|
{
|
|
RECT rt;
|
|
HDWP hdwp;
|
|
int n = 0, bottom_extra = 0;
|
|
|
|
if (m_status) n++;
|
|
if (m_client) n++;
|
|
if (n==0) return;
|
|
|
|
GetClientRect(m_hwnd,&rt);
|
|
hdwp = BeginDeferWindowPos(n);
|
|
|
|
if (m_status) {
|
|
DeferWindowPos(hdwp,m_status,NULL,0,0, //???
|
|
rt.right - rt.left, 20, SWP_NOZORDER);
|
|
bottom_extra = 20;
|
|
}
|
|
|
|
if (m_client)
|
|
DeferWindowPos(hdwp,m_client->handle(),NULL,0,0,
|
|
rt.right - rt.left, rt.bottom-rt.top - bottom_extra,
|
|
SWP_NOZORDER | SWP_NOMOVE);
|
|
|
|
EndDeferWindowPos(hdwp);
|
|
}
|
|
|
|
/// Windows controls - TControl ////////////
|
|
|
|
TControl::TControl(TWin *parent, pchar classname, pchar text,int id, long style)
|
|
: TEventWindow(parent,classname,text,id,style)
|
|
{
|
|
m_colour = RGB(0,0,0); //RGB(255,255,255); // shd depend on background!
|
|
m_font = NULL;
|
|
SetWindowLong(m_hwnd,-21 /*GWL_USERDATA*/,(long)this);
|
|
m_parent = (TEventWindow *)parent;
|
|
//calc_size();
|
|
}
|
|
|
|
TControl::~TControl()
|
|
{
|
|
}
|
|
|
|
TControl *
|
|
TControl::user_data(Handle handle)
|
|
{
|
|
return (TControl *)GetWindowLong(handle,-21 /*GWL_USERDATA*/);
|
|
}
|
|
|
|
void TControl::calc_size()
|
|
{
|
|
int cx,cy;
|
|
m_parent->get_dc()->get_text_extent(get_text(),cx,cy,m_font);
|
|
resize(int(1.05*cx),int(1.05*cy));
|
|
}
|
|
|
|
bool TControl::is_type(char *tname)
|
|
{
|
|
return strcmp(type_name(),tname)==0;
|
|
}
|
|
|
|
void TControl::set_font(TFont *fnt)
|
|
{
|
|
m_font = fnt;
|
|
calc_size();
|
|
if (m_font)
|
|
send_msg(WM_SETFONT,(WPARAM)m_font->handle(),(LPARAM)TRUE);
|
|
}
|
|
|
|
void TControl::set_colour(float r, float g, float b)
|
|
{
|
|
m_colour = (long)RGBF(r,g,b);
|
|
update();
|
|
}
|
|
|
|
|
|
TLabel::TLabel(TWin *parent, pchar text, int id)
|
|
//--------------------------------------
|
|
: TControl(parent,"STATIC",text,id,0x0)
|
|
{ }
|
|
|
|
TEdit::TEdit(TWin *parent, pchar text, int id, long style)
|
|
//-----------------------------------------------
|
|
: TControl(parent,"EDIT",text,id,style | WS_BORDER)
|
|
{ }
|
|
|
|
|
|
//-----------------Dialog boxes--------------------------
|
|
TDialog::~TDialog ()
|
|
{ FreeProcInstance((DLGPROC)m_lpfnBox); }
|
|
|
|
bool TDialog::was_successful()
|
|
{
|
|
if (modeless()) return as_bool(handle());
|
|
else return as_bool(m_ret);
|
|
}
|
|
|
|
DLGFN DialogProc (HWND hdlg, UINT msg, UINT wParam,LONG lParam);
|
|
|
|
void TDialog::go ()
|
|
//-----------------
|
|
{
|
|
HWND hdlg,hOwner;
|
|
|
|
hOwner = (m_owner) ? m_owner->handle() : NULL; //GetDesktopWindow();
|
|
m_lpfnBox = (void FAR *)MakeProcInstance((FARPROC)DialogProc,hInst);
|
|
if (modeless()) {
|
|
hdlg = CreateDialogParam(hInst,m_name,hOwner,(DLGPROC)m_lpfnBox,(long)this);
|
|
hModeless = hdlg;
|
|
} else {
|
|
m_ret = DialogBoxParam(hInst,m_name,hOwner,(DLGPROC)m_lpfnBox,(long)this);
|
|
m_hwnd = 0; // thereafter, this object is not a valid window...
|
|
}
|
|
ShowWindow(hdlg,SW_SHOW);
|
|
}
|
|
|
|
|
|
TWin * TDialog::field(int id)
|
|
{
|
|
return new TWin(GetDlgItem(m_hwnd,id));
|
|
}
|
|
|
|
|
|
|
|
//....Modeless Dialog Box procedure.........................
|
|
DLGFN DialogProc (HWND hdlg, UINT msg, UINT wParam,LONG lParam)
|
|
{
|
|
int ret;
|
|
TDialog *This = (TDialog *) GetWindowLong(hdlg,8/*DWL_USER*/);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
//..... 'This' pointer passed as param from CreateDialogParam()
|
|
SetWindowLong(hdlg,8/*DWL_USER*/,lParam);
|
|
This = (TDialog *)lParam;
|
|
if (This->modeless()) hModeless = hdlg;
|
|
This->set(hdlg);
|
|
return This->init();
|
|
|
|
case WM_COMMAND:
|
|
switch(LOW_WORD(wParam)) {
|
|
case IDOK:
|
|
ret = This->finis();
|
|
if (! ret) return FALSE; // no, we're not finished yet!
|
|
case IDCANCEL:
|
|
if (This->modeless()) SendMessage(hdlg,WM_CLOSE,0,0L);
|
|
else EndDialog(hdlg,wParam==IDOK);
|
|
break;
|
|
default:
|
|
This->command(wParam);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_CLOSE:
|
|
DestroyWindow(hdlg);
|
|
hModeless = 0;
|
|
break;
|
|
}
|
|
return FALSE; // we did not process the message...
|
|
}
|
|
|
|
|
|
WNDFN WndProc (HWND hwnd, UINT msg, WPARAM wParam,LPARAM lParam);
|
|
|
|
|
|
//----------------Window Registration----------------------
|
|
|
|
void RegisterEventWindow(HANDLE hIcon=0, HANDLE hCurs=0)
|
|
//------------------------------------------------------
|
|
{
|
|
WNDCLASS wndclass;
|
|
|
|
wndclass.style = CS_HREDRAW | CS_VREDRAW |
|
|
CS_OWNDC | CS_DBLCLKS;
|
|
wndclass.lpfnWndProc = WndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = 4;
|
|
wndclass.hInstance = hInst;
|
|
wndclass.hIcon = hIcon ? hIcon : LoadIcon (NULL, IDI_APPLICATION) ;
|
|
wndclass.hCursor = hCurs ? hCurs : LoadCursor (NULL, IDC_ARROW) ;
|
|
wndclass.hbrBackground = NULL; //GetStockObject(LTGRAY_BRUSH);
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = EW_CLASSNAME;
|
|
|
|
RegisterClass (&wndclass);
|
|
|
|
}
|
|
|
|
char *args[N_CMD_LINE];
|
|
int n_args;
|
|
int ParseCmdLine(LPSTR CmdLine, char **args);
|
|
|
|
int get_argc()
|
|
{ return n_args; }
|
|
|
|
char **get_argv()
|
|
{ return args; }
|
|
|
|
|
|
int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine, int nCmdShow)
|
|
//----------------------------------------------------------------
|
|
{
|
|
|
|
#ifdef COMMCTRL
|
|
InitCommonControls();
|
|
#endif
|
|
|
|
hInst = hInstance;
|
|
CmdShow = nCmdShow;
|
|
|
|
n_args = ParseCmdLine(lpszCmdLine, args);
|
|
|
|
if (! hPrevInstance) RegisterEventWindow();
|
|
|
|
return SMain(n_args,args);
|
|
}
|
|
|
|
|
|
//--------------Default Window Proc for EventWindow-----------------
|
|
|
|
typedef void *PVOID;
|
|
|
|
WNDFN WndProc (HWND hwnd, UINT msg, WPARAM wParam,LPARAM lParam)
|
|
|
|
//----------------------------------------------------------------------------
|
|
{
|
|
// static SWin w;
|
|
static BOOL dragging = FALSE;
|
|
static long MouseTime = 0;
|
|
static UINT size_flags;
|
|
LPMINMAXINFO pSizeInfo;
|
|
long ret;
|
|
|
|
TEventWindow *This = (TEventWindow *) GetWindowLong(hwnd,0);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
LPCREATESTRUCT lpCreat = (LPCREATESTRUCT) lParam;
|
|
PVOID *lpUser;
|
|
lpUser = (PVOID *)lpCreat->lpCreateParams;
|
|
|
|
//..... 'This' pointer passed as first word of creation parms
|
|
SetWindowLong(hwnd,0,(long)lpUser[0]);
|
|
This = (TEventWindow *)lpUser[0];
|
|
This->get_dc()->set_twin(This);
|
|
}
|
|
return 0;
|
|
|
|
case WM_SIZE:
|
|
This->size(LOWORD(lParam),HIWORD(lParam));
|
|
return 0;
|
|
|
|
case WM_MOVE:
|
|
This->on_move();
|
|
return 0;
|
|
|
|
case WM_GETMINMAXINFO:
|
|
if (This && This->cant_resize()) {
|
|
pSizeInfo = (LPMINMAXINFO) lParam;
|
|
pSizeInfo->ptMaxTrackSize = This->fixed_size();
|
|
pSizeInfo->ptMinTrackSize = This->fixed_size();
|
|
}
|
|
return 0;
|
|
|
|
//
|
|
case WM_COMMAND:
|
|
if (This->m_dispatcher) {
|
|
This->m_dispatcher->dispatch(LOW_WORD(wParam),HIWORD(wParam),(Handle)lParam);
|
|
return 0;
|
|
}
|
|
if (This->command(LOW_WORD(wParam))) return 0;
|
|
else break;
|
|
|
|
case WM_USER_PLUS:
|
|
return This->handle_user(wParam,lParam);
|
|
|
|
case WM_KEYDOWN:
|
|
This->keydown(wParam);
|
|
return 0;
|
|
|
|
case WM_CHAR:
|
|
This->on_char(wParam,LOWORD(lParam)); // 1
|
|
return 0;
|
|
|
|
case WM_HSCROLL:
|
|
if (This->m_dispatcher) {
|
|
int id = GetWindowLong((HWND)lParam,GWL_ID);
|
|
This->m_dispatcher->dispatch(id,LOWORD(wParam),(Handle)lParam);
|
|
}
|
|
return 0;
|
|
case WM_VSCROLL:
|
|
This->vscroll(wParam,This->scroll_bar()->get_pos());
|
|
return 0;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
TDC *dc = This->get_dc();
|
|
dc->set_hdc(BeginPaint(hwnd,&ps));
|
|
This->paint(*dc);
|
|
dc->set_hdc(NULL);
|
|
EndPaint(hwnd,&ps);
|
|
}
|
|
return 0;
|
|
|
|
// Mouse messages....
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_LBUTTONDBLCLK:
|
|
{
|
|
Point pt(LOWORD(lParam),HIWORD(lParam));
|
|
//pt.to_logical(*This);
|
|
switch (msg) {
|
|
case WM_LBUTTONDOWN:
|
|
This->mouse_down(pt);
|
|
break;
|
|
case WM_LBUTTONUP:
|
|
This->mouse_up(pt);
|
|
break;
|
|
case WM_RBUTTONDOWN:
|
|
This->right_mouse_down(pt);
|
|
break;
|
|
case WM_LBUTTONDBLCLK:
|
|
This->mouse_double_click(pt);
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
|
|
case WM_MOUSEMOVE: // needs different treatment??
|
|
{
|
|
Point pt(LOWORD(lParam),HIWORD(lParam));
|
|
This->mouse_move(pt);
|
|
}
|
|
return 0;
|
|
|
|
case WM_ERASEBKGND:
|
|
{
|
|
RECT rt;
|
|
GetClientRect(hwnd,&rt);
|
|
FillRect((HDC)wParam,(LPRECT)&rt, This->m_bkgnd_brush);
|
|
}
|
|
return 0;
|
|
|
|
#ifdef _WIN32
|
|
case WM_CTLCOLORSTATIC:
|
|
{
|
|
TControl *ctl = (TControl *)GetWindowLong((HWND)lParam,-21 /*GWL_USERDATA*/);
|
|
SetBkColor((HDC)wParam, (COLORREF)This->m_bk_color);
|
|
SetTextColor((HDC)wParam, ctl->get_colour());
|
|
}
|
|
return (long)This->m_bkgnd_brush;
|
|
#endif
|
|
|
|
case WM_SETFOCUS:
|
|
This->focus(true);
|
|
return 0;
|
|
|
|
case WM_KILLFOCUS:
|
|
This->focus(false);
|
|
return 0;
|
|
|
|
case WM_SYSCOMMAND:
|
|
if (This->sys_command(LOW_WORD(wParam))) return 0; //?
|
|
else break;
|
|
|
|
case WM_TIMER:
|
|
This->timer();
|
|
return 0;
|
|
|
|
case WM_CLOSE:
|
|
if (! This->query_close()) return 0;
|
|
break; // *NOTE* this was not here!!
|
|
|
|
case WM_DESTROY:
|
|
//*fix 1.2.8 This had been commented out; prevents closing via usual window operation.
|
|
This->destroy();
|
|
if (This->m_hmenu) DeleteObject(This->m_hmenu); // but why here?
|
|
return 0 ;
|
|
}
|
|
|
|
ret = DefWindowProc (hwnd , msg, wParam, lParam) ;
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *_quote_strtok(char *str, char str_delim)
|
|
{
|
|
// a specialized version of strtok() which treats quoted strings specially
|
|
// (used for handling command-line parms)
|
|
static char *tok;
|
|
if(str != NULL) tok = str;
|
|
|
|
while (*tok && isspace(*tok)) tok++;
|
|
if (*tok == '\0') return NULL;
|
|
|
|
if (*tok == str_delim) {
|
|
tok++; // skip "
|
|
str = tok;
|
|
while (*tok && *tok != str_delim) tok++;
|
|
} else {
|
|
str = tok;
|
|
while (*tok && ! isspace(*tok)) tok++;
|
|
}
|
|
if (*tok) *tok++ = '\0';
|
|
return str;
|
|
}
|
|
|
|
int ParseCmdLine(LPSTR CmdLine, char **args)
|
|
//-----------------------------------------
|
|
{
|
|
int i;
|
|
char *arg;
|
|
static char app_path[255];
|
|
|
|
GetModuleFileName(NULL,app_path,255);
|
|
|
|
lstrcpy(buff,CmdLine);
|
|
args[0] = app_path;
|
|
args[1] = _quote_strtok(buff,'\"');
|
|
if (! args[1]) return 1; // at least one argument!
|
|
i = 2;
|
|
while (arg = _quote_strtok(NULL,'\"')) args[i++] = arg;
|
|
return i;
|
|
}
|
|
|
|
|
|
|
|
|