#ifndef JDECAPP_HPP_ #define JDECAPP_HPP_ #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 #endif #include "classes.hpp" #include "fstream.hpp" #include "jdecoder.hpp" #include "pixels.hpp" /////////////////////////////////////////////////////////////////////////////// class Scrollable { public: virtual void setHScrollRange( int min, int max ) = 0; virtual void setVScrollRange( int min, int max ) = 0; virtual void setHScrollPage( int page ) = 0; virtual void setVScrollPage( int page ) = 0; virtual void setHScrollPos( int pos ) = 0; virtual void setVScrollPos( int pos ) = 0; virtual int getHScrollPos() const = 0; virtual int getVScrollPos() const = 0; }; // 一通りの実装を持つ scroll adapter クラスを作ってもよかった? /////////////////////////////////////////////////////////////////////////////// class JDecForm : public MainForm, public Scrollable { Pixels pix_; mutable SCROLLINFO si_; protected: //! coerrided LRESULT doPaint( PAINTSTRUCT *ps ) { if (! pix_.pixels) return 0; BITMAPINFOHEADER bmi = { sizeof( BITMAPINFOHEADER ), pix_.getWidth(), pix_.getHeight(), 1, // WORD biPlanes pix_.getDepth(), BI_RGB, 0, // DWORD biSizeImage 0, // LONG biXPelsPerMeter 0, // LONG biYPelsPerMeter 0, // DWORD biClrUsed 0 // DWORD biClrImportant }; int r = ::SetDIBitsToDevice ( ps->hdc, 0, 0, pix_.getWidth(), pix_.getHeight(), getHScrollPos(), 0, getVScrollPos(), pix_.getHeight(), pix_.pixels, (CONST BITMAPINFO *)&bmi, DIB_RGB_COLORS ); if (r == 0) { static char buf[256]; sprintf( buf, "SetDIBitsToDevice error %d", ::GetLastError() ); puts( buf ); setCaption( buf ); //MessageBox( windowHandle, buf, "error", 0 ); } return 0; } //! overrided LRESULT doDropFiles( HDROP hDrop ) { static char cap[256]; unsigned char *image = 0; char filename[256]; ::DragQueryFile( hDrop, 0, filename, 255 ); try { unsigned char *line_ptr; int line_size; FileInputStream fis( filename ); JPEG::Decoder jpeg( &fis ); setHScrollPos( 0 ); setVScrollPos( 0 ); sprintf( cap, "展開中 %d x %d, %d bit(s)", jpeg.getWidth(), jpeg.getHeight(), jpeg.getDepth() ); setCaption( cap) ; pix_.setSize( jpeg.getWidth(), jpeg.getHeight() ); setHScrollRange( 0, jpeg.getWidth() ); setVScrollRange( 0, jpeg.getHeight() ); line_size = pix_.getBPL(); if (jpeg.getBPL() < line_size) line_size = jpeg.getBPL(); int y = 0; while ( (y = jpeg.getScanLine( (void**)&line_ptr )) >= 0 ) { if (pix_.scanPixel( y )) memcpy( pix_.scanPixel( y ), line_ptr, line_size ); if (((y + 1) & 0xf) == 0) update(); } sprintf( cap, "%d x %d, %d bit(s)", jpeg.getWidth(), jpeg.getHeight(), jpeg.getDepth() ); } catch(const char *e) { strcpy( cap, "エラー" ); puts( e ); } catch(...) { strcpy( cap, "エラー" ); puts( "exception!" ); } setCaption( cap ); update(); ::DragFinish( hDrop ); return 0; } public: bool create( int x, int y, int w, int h ) { if (! MainForm::create( x, y, w, h )) return false; si_.cbSize = sizeof( SCROLLINFO ); ::DragAcceptFiles( getWindowHandle(), TRUE ); setHScrollPage( getClientWidth() ); setVScrollPage( getClientHeight() ); setHScrollRange( 0, 0 ); setVScrollRange( 0, 0 ); return true; } ////// scrollable 実装 void setHScrollRange( int min, int max ) { si_.fMask = SIF_RANGE; si_.nMin = min; si_.nMax = max; ::SetScrollInfo( getWindowHandle(), SB_HORZ, &si_, TRUE ); } void setVScrollRange( int min, int max ) { si_.fMask = SIF_RANGE; si_.nMin = min; si_.nMax = max; ::SetScrollInfo( getWindowHandle(), SB_VERT, &si_, TRUE ); } void setHScrollPage( int page ) { si_.fMask = SIF_PAGE; si_.nPage = page; ::SetScrollInfo( getWindowHandle(), SB_HORZ, &si_, TRUE); } void setVScrollPage( int page ) { si_.fMask = SIF_PAGE; si_.nPage = page; ::SetScrollInfo( getWindowHandle(), SB_VERT, &si_, TRUE); } void setHScrollPos( int pos ) { si_.fMask = SIF_POS; si_.nPos = pos; ::SetScrollInfo( getWindowHandle(), SB_HORZ, &si_, TRUE); InvalidateRect( getWindowHandle(), 0, FALSE ); } void setVScrollPos( int pos ) { si_.fMask = SIF_POS; si_.nPos = pos; ::SetScrollInfo( getWindowHandle(), SB_VERT, &si_, TRUE); InvalidateRect( getWindowHandle(), 0, FALSE ); } int getHScrollPos() const { si_.fMask = SIF_POS; if (::GetScrollInfo( getWindowHandle(), SB_HORZ, &si_ )) { return si_.nPos; } return 0; } int getVScrollPos() const { si_.fMask = SIF_POS; if (::GetScrollInfo( getWindowHandle(), SB_VERT, &si_ )) { return si_.nPos; } return 0; } protected: LRESULT whenWMSize( Message *m ) { m->handled = true; setHScrollPage( getClientWidth() ); setVScrollPage( getClientHeight() ); return 0; } LRESULT whenWMHScroll( Message *m ) { switch (LOWORD( m->wp )) { case SB_THUMBTRACK: { setHScrollPos( HIWORD( m->wp ) ); return 0; } case SB_LINELEFT: { int pos = getHScrollPos(); if (pos) { --pos; setHScrollPos( pos ); } return 0; } case SB_LINERIGHT: { int pos = getHScrollPos(); pos++; setHScrollPos( pos ); return 0; } case SB_PAGELEFT: { int page = getClientWidth(); int pos = getHScrollPos(); if ( page < pos ) pos -= page; else pos = 0; setHScrollPos( pos ); return 0; } case SB_PAGERIGHT: { int page = getClientWidth(); int pos = getHScrollPos(); if ( page < pix_.getWidth() - pos ) pos += page; else pos = pix_.getWidth() - page; setHScrollPos( pos ); return 0; } } return 0; } LRESULT whenWMVScroll( Message *m ) { switch (LOWORD( m->wp )) { case SB_THUMBTRACK: { setVScrollPos( HIWORD( m->wp ) ); return 0; } case SB_LINEUP: { int pos = getVScrollPos(); if (pos) { --pos; setVScrollPos( pos ); } return 0; } case SB_LINEDOWN: { int pos = getVScrollPos(); pos++; setVScrollPos( pos ); return 0; } case SB_PAGEUP: { int page = getClientHeight(); int pos = getVScrollPos(); if ( page < pos ) pos -= page; else pos = 0; setVScrollPos( pos ); return 0; } case SB_PAGEDOWN: { int page = getClientHeight(); int pos = getVScrollPos(); if ( page < pix_.getHeight() - pos ) pos += page; else pos = pix_.getHeight() - page; setVScrollPos( pos ); return 0; } } return 0; } LRESULT whenWMMouseWheel( Message *m ) { setVScrollPos( getVScrollPos() - (short)HIWORD(m->wp) ); return 0; } BEGIN_MESSAGE_MAP() MAP_MESSAGE( WM_SIZE, whenWMSize ) MAP_MESSAGE( WM_HSCROLL, whenWMHScroll ) MAP_MESSAGE( WM_VSCROLL, whenWMVScroll ) MAP_MESSAGE( WM_MOUSEWHEEL, whenWMMouseWheel ) END_MESSAGE_MAP( MainForm ) }; /////////////////////////////////////////////////////////////////////////////// class JDecApplication : public Application { protected: bool initialize( LPSTR cline, int showCmd ) { mainForm = new JDecForm(); if (! mainForm->create( 10, 10, 400, 300 )) return false; mainForm->show( showCmd ); return true; } public: JDecForm *mainForm; JDecApplication() { mainForm = 0; } ~JDecApplication() { delete mainForm; } }; // main.cpp からの include 以外は全て extern 宣言する -> インスタンスは一つのみ #ifndef MAIN_CPP_ extern #endif JDecApplication application; #endif // JDECAPP_APP_