加载图片可滚动&鼠标点击时获取x,y [英] load picture scrollable & get x,y when mouseclick
问题描述
我需要使用Visual C ++ 2008在C语言中使用window api 32位编程帮助。
在窗口中从命令行加载图片路径/文件名。
但是如果工作滚动条更大的话。
鼠标点击图片的xy不是来自窗口客户区。
有没有人提出建议或示例?
今晚我在等待某人的时候有点闲暇,所以决定有一点一出戏我没有打扰错误检查,你应该自己添加。我还选择了一种类似于编程许多不同窗口类时使用的MS的样式,如(重新设计的)Wine项目的部分内容。 ( https://github.com/wine-mirror/wine/tree/master/dlls/comctl32 [ ^ ] )
我试图让它与之交互变得非常简单。
首先,您必须注册课程 - 您可以在程序启动期间,在屏幕上显示任何内容之前执行此操作。
接下来,我定义了两条消息。 IM_SETIMAGE和IM_GETCLICKPOS。您可以显式发送这些消息,也可以使用提供的宏。
如果您选择自己发送这些消息,您只需要知道:
IM_SETIMAGE期望lParam保留新图像的HBITMAP 。返回值是前一个图像(如果有的话,否则为NULL)
IM_GETCLICKPOS没有参数并返回最后一次点击图像中的位置(您会收到通知通过WM_COMMAND消息的点击次数)。 lo阶词包含X位置,hi阶词包含Y位置。图像左侧/上方的位置返回负值。
背景颜色不能从包含的应用程序中自定义,但您可以轻松添加代码来处理此问题情况,或者更简单地说,编辑onImgWindowEraseBackground上的函数。
代码远非完美,但应该有助于提供一个良好的起点。你还有一些工作要做。虽然你提到将文件的名称传递给程序以便选择图像,但我建议你稍微复杂一点,然后创建一个配置文件。在此文件中,您可以包括以下内容:(1)图像文件的名称(2)感兴趣区域的数量(3)包围这些区域的多边形点的坐标对。
也许是这样的:
------------ config.txt ----------- -
图片:image.bmp
保利数:3
Apple:10,10,20,10,20,20,10, 20
西瓜:100,100,200,100,200,200,100,200
三角形:50,50,75,75,25,75
- --------------------------------
对于一个基本的使用示例,我将以下对话框应用程序放在一起。 (用Code :: Blocks编写,用MinGW构建)
main.cpp
#include < windows.h >
#include < commctrl.h >
#include < stdio.h >
#include resource.h
#include ../ scrollImage / imgWindow.h
HINSTANCE hInst ;
BOOL CALLBACK DlgMain(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch (uMsg )
{
case WM_INITDIALOG:
{
HBITMAP img;
img =(HBITMAP)LoadImage(hInst, image.bmp,IMAGE_BITMAP,< span class =code-digit> 0 , 0 ,LR_LOADFROMFILE);
ImageWindow_SetImage(GetDlgItem(hwndDlg,IDC_IMAGE_WINDOW),img);
}
return TRUE;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0 < /跨度>);
}
return TRUE;
case WM_COMMAND:
{
switch ( LOWORD(wParam))
{
case IDC_IMAGE_WINDOW:
LPARAM clickPos = ImageWindow_GetClickPos((HWND)lParam);
short xPos = LOWORD(clickPos);
short yPos = HIWORD(clickPos);
char msg [ 32 ];
sprintf(msg, 点击pos:%d,%d \ n, xPos,yPos);
SetDlgItemText(hwndDlg,IDC_CLICKPOS_OUTPUT,msg);
break ;
}
}
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
hInst = hInstance;
InitCommonControls();
IMGWINDOW_Register();
return DialogBox(hInst,MAKEINTRESOURCE(DLG_MAIN),NULL,(DLGPROC)DlgMain);
}
resource.h
#ifndef IDC_STATIC
#define IDC_STATIC(-1)
#endif
#define DLG_MAIN 100
#define IDC_CLICKPOS_OUTPUT 40000
#define IDC_IMAGE_WINDOW 40001
resource.rc
// 由ResEdit 1.6.2生成
// 版权所有(C)2006-2014
// http://www.resedit。 net
#include < windows.h >
#include < commctrl.h >
#include < richedit.h >
#include resource.h
//
// 对话资源
//
LANGUAG E LANG_NEUTRAL,SUBLANG_NEUTRAL
DLG_MAIN对话 0 , 0 , 185 , 166
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION 对话框
FONT 8 , Shell Dlg女士
{
LTEXT ,IDC_CLICKPOS_OUTPUT, 7 , 151 , 171 , 8 ,SS_LEFT, WS_EX_LEFT
CONTROL ,IDC_IMAGE_WINDOW, imgWindow32,0x50020000, 7 , 7 , 171 , 139 ,0x00000000
}
最后,这里是图像显示和clic的肉和骨头k-pos计算。
再次,即使有点冗长也很简单。
imgWindow.h
< pre lang =c ++> #ifndef imgWindow_h
#define imgWindow_h
#include < windows.h >
// 外部可调用函数
//
BOOL IMGWINDOW_Register();
void IMGWINDOW_Unregister();
// 窗口类名定义
//
#define IMGWINDOW_CLASSAimgWindow32
#define IMGWINDOW_CLASSW LimgWindow32
#ifdef UNICODE
#define IMGWINDOW_CLASS IMGWINDOW_CLASSW
#else
#define IMGWINDOW_CLASS IMGWINDOW_CLASSA
#endif // UNICODE
// 此类的可用用户定义消息
//
#define IM_SETIMAGE WM_USER + 1
#define IM_GETCLICKPOS WM_USER + 2
// 用于使用上面定义的消息与控件交互的宏
//
#define ImageWindow_SetImage(hWnd,hBitmap)SendMessage(hWnd,IM_SETIMAGE,0,(LPARAM)hBitmap)
#define ImageWindow_GetClickPos(hWnd)SendMessage(hWnd,IM_GETCLICKPOS,0,0)
#endif // imgWindow_h
imgWindow.cpp
#include imgWindow.h
#ifndef min
#define min(a,b)a< b? a:b
#endif // min
typedef struct
{
HWND self;
短 clickX,点击Y;
BOOL mouseDown;
int xScrollPos,yScrollPos;
int xImgOfs,yImgOfs;
HBITMAP bkg;
HDC memDC;
HBITMAP oldMemBmp;
int bmpWidth,bmpHeight;
RECT clientRect;
} IMGWINDOW_INFO;
#define IMGWINDOW_GetInfoPtr(hWindow)((IMGWINDOW_INFO *)GetWindowLongPtr(hWindow,0))
int onImgWindowCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *)LocalAlloc (LPTR, sizeof (IMGWINDOW_INFO));
if (!infoPtr)
return - 1 跨度>;
ZeroMemory(infoPtr, sizeof (infoPtr));
infoPtr-> self = hwnd;
infoPtr-> clickX = - 1 ;
infoPtr-> clickY = - 1 ;
HDC mDC;
mDC = GetDC(hwnd);
infoPtr-> memDC = CreateCompatibleDC(mDC);
infoPtr-> oldMemBmp =(HBITMAP)GetCurrentObject(infoPtr-> memDC,OBJ_BITMAP);
ReleaseDC(hwnd,mDC);
GetClientRect(hwnd,& infoPtr-> clientRect);
SetWindowLong(hwnd, 0 ,(LONG)infoPtr); // 此处可能出现x64问题//
返回 0 ;
}
int onImgWindowDestroy(HWND hwnd)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *) LocalAlloc(LPTR, sizeof (IMGWINDOW_INFO));
SelectObject(infoPtr-> memDC,infoPtr-> oldMemBmp);
DeleteDC(infoPtr-> memDC);
LocalFree(infoPtr);
return 0 ;
}
int onImgWindowEraseBackground(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
RECT clientRect ;
HBRUSH bkBrush;
IMGWINDOW_INFO * infoPtr = IMGWINDOW_GetInfoPtr(hwnd);
bkBrush = CreateSolidBrush(RGB( 255 , 0 , 255 ));
GetClientRect(hwnd,& clientRect);
FillRect((HDC)wParam,& clientRect,bkBrush);
DeleteObject(bkBrush);
return 1 ;
}
int doImgWindowScroll(HWND hwnd,WPARAM wParam, int orientation, int windowMin, int windowMax)
{
int windowSize = windowMax - windowMin + 1 ;
switch (LOWORD(wParam))
{
case SB_THUMBTRACK :
SetScrollPos(hwnd,orientation,HIWORD(wParam), true );
break ;
case SB_PAGERIGHT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation)+ windowSize,真跨度>);
break ;
case SB_PAGELEFT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation)-windowSize,真跨度>);
break ;
case SB_LINELEFT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation) - 16 , true );
break ;
case SB_LINERIGHT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation)+16,真跨度>);
break ;
}
IMGWINDOW_INFO * mData = IMGWINDOW_GetInfoPtr(hwnd);
int scrollPos = GetScrollPos(hwnd,orientation);
if (orientation == SB_HORZ)
mData-> xScrollPos = scrollPos;
else if (orientation == SB_VERT)
mData-> yScrollPos = scrollPos;
InvalidateRect(hwnd,NULL, true );
return 0 ;
}
int onImgWindowHscroll(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
RECT clientRect;
GetClientRect(hwnd,& clientRect);
return doImgWindowScroll(hwnd,wParam,SB_HORZ,clientRect.left,clientRect.right);
}
int onImgWindowVscroll(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
RECT clientRect ;
GetClientRect(hwnd,& clientRect);
return doImgWindowScroll(hwnd,wParam,SB_VERT,clientRect.top,clientRect.bottom);
}
void imgWindowSetScrollInfo(HWND hwnd)
{
int mWidth;
RECT mRect;
SCROLLINFO si = {};
IMGWINDOW_INFO * infoPtr = IMGWINDOW_GetInfoPtr(hwnd);
GetClientRect(hwnd,& mRect);
mWidth = mRect.right - mRect.left + 1 ;
si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0 ;
si.nMax = infoPtr-> bmpWidth; // - mWidth; // - mWidth;
si.nPage = mWidth;
si.nPos = 0 ;
infoPtr-> xScrollPos = 0 ;
SetScrollInfo(hwnd,SB_HORZ,& si, false );
int mHeight;
mHeight = mRect.bottom-mRect.top + 1 ;
si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0 ;
si.nMax = infoPtr-> bmpHeight; // - mHeight;
si.nPage = mHeight;
si.nPos = 0 ;
infoPtr-> yScrollPos = 0 ;
SetScrollInfo(hwnd,SB_VERT,& si, true );
}
LRESULT onImgWindowSetImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0 跨度>);
HBITMAP oldImg;
oldImg = infoPtr-> bkg;
infoPtr-> bkg =(HBITMAP)lParam;
BITMAP bm;
GetObject(infoPtr-> bkg, sizeof (bm),& bm);
infoPtr-> bmpWidth = bm.bmWidth;
infoPtr-> bmpHeight = bm.bmHeight;
if (infoPtr-> bmpWidth>(infoPtr-> clientRect.right-infoPtr-> clientRect.left))
ShowScrollBar(hwnd,SB_HORZ, true );
else
ShowScrollBar(hwnd,SB_HORZ, false );
if (infoPtr-> bmpHeight>(infoPtr-> clientRect.bottom-infoPtr-> clientRect.top))
ShowScrollBar(hwnd,SB_VERT, true );
else
ShowScrollBar(hwnd,SB_VERT, false );
imgWindowSetScrollInfo(hwnd);
SelectObject(infoPtr-> memDC,infoPtr-> bkg);
InvalidateRect(infoPtr-> self,NULL, true );
return (LRESULT)oldImg;
}
// 窗口的背景淡入淡出
LRESULT CALLBACK IMGWINDOW_WindowProc(HWND hwnd,UINT消息,WPARAM wParam,LPARAM lParam)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0 跨度>);
switch (消息) // 处理消息
{
case WM_CREATE:
return onImgWindowCreate(hwnd,wParam,lParam);
case WM_DESTROY:
return onImgWindowDestroy(hwnd);
// lParam =(HBITMAP)img
case IM_SETIMAGE:
return onImgWindowSetImage(hwnd,wParam,lParam);
case WM_ERASEBKGND:
return onImgWindowEraseBackground(hwnd,wParam, LPARAM);
case WM_PAINT:
HDC hdc;
PAINTSTRUCT ps;
int mWidth,mHeight;
RECT mRect;
GetClientRect(hwnd,& mRect);
mWidth = mRect.right-mRect.left + 1 ;
mHeight = mRect.bottom-mRect.top + 1 ;
hdc = BeginPaint(hwnd,& ps);
int xOfs,yOfs;
xOfs = yOfs = 0 ;
if (infoPtr-> bmpWidth< mWidth)
xOfs =(mWidth-infoPtr-> bmpWidth)/ 2 ;
if (infoPtr-> bmpHeight< mHeight)
yOfs =(mHeight-infoPtr-> bmpHeight)/ 2 ;
infoPtr-> xImgOfs = xOfs;
infoPtr-> yImgOfs = yOfs;
int drawWidth,drawHeight;
drawWidth = min(infoPtr-> bmpWidth,mWidth);
drawHeight = min(infoPtr-> bmpHeight,mHeight);
int imgXofs,imgYofs;
imgXofs = infoPtr-> xScrollPos;
imgYofs = infoPtr-> yScrollPos;
BitBlt(
hdc,
xOfs,yOfs,
drawWidth,drawHeight,
infoPtr-> memDC,
imgXofs,imgYofs,
SRCCOPY);
EndPaint(hwnd,& ps);
return 0 ;
case WM_HSCROLL:
return onImgWindowHscroll(hwnd,wParam, LPARAM);
case WM_VSCROLL:
return onImgWindowVscroll(hwnd,wParam, LPARAM);
case WM_SIZE:
GetClientRect(hwnd,& infoPtr-> clientRect);
InvalidateRect(hwnd,NULL, true );
return 0 ;
case WM_GETDLGCODE:
return DLGC_STATIC;
case WM_LBUTTONDOWN:
infoPtr-> mouseDown = true ;
return 0 ;
case WM_LBUTTONUP:
{
// 保存准备使用的点以响应IM_GETCLICKPOS消息
infoPtr-> clickX =( short )(LOWORD(lParam)+ infoPtr-> xScrollPos - infoPtr-> xImgOfs);
infoPtr-> clickY =( short )(HIWORD(lParam)+ infoPtr-> yScrollPos - infoPtr-> yImgOfs);
// 告诉paent窗口我们点击了WM_COMMAND消息
short myNotifIdCode = 0 ;
if (infoPtr-> mouseDown == true )
SendMessage(GetParent (infoPtr-> self),WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(infoPtr-> self),myNotifIdCode),(LPARAM)infoPtr-> self);
}
infoPtr-> mouseDown = false ;
break ;
case IM_GETCLICKPOS:
return MAKELPARAM(infoPtr-> clickX,infoPtr-> clickY);
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
BOOL IMGWINDOW_Register( void )
{
WNDCLASS wndClass;
ZeroMemory(& wndClass, sizeof (WNDCLASS));
wndClass.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_OWNDC; // CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
wndClass.lpfnWndProc = IMGWINDOW_WindowProc;
wndClass.cbClsExtra = 0 ;
wndClass.cbWndExtra = sizeof (IMGWINDOW_INFO *); // 通过getwindowlong(hWnd,nIndex)访问
wndClass.hCursor = LoadCursor( 0 ,IDC_ARROW);
wndClass.hbrBackground = 0 ;
wndClass.lpszClassName = IMGWINDOW_CLASS;
if (RegisterClass(& wndClass)!= 0 )
返回 true ;
else
return false < /跨度>;
}
void IMGWINDOW_Unregister( void )
{
UnregisterClass(IMGWINDOW_CLASS,NULL);
}
感谢您的澄清。这里有一切都很好描述: https:// msdn。 microsoft.com/en-us/library/windows/desktop/ms645533%28v=vs.85%29.aspx [ ^ ]。
样品?这不会太难,但谁会花这么多时间?我们谁会浪费这么多时间用纯粹的C.写作。为什么?很少有简单的练习可以用来学习,但是仔细地将所有大象联系起来...... :-)
怎么样:你阅读文档并尝试编写代码,询问遇到问题时会另外提出问题吗?
-SA
在Visual Basic中它太容易了。
将来我会在VB中编写windows元素,并且代码必须更快。在C中作为dll
。我从谷歌获得的所有信息。
公共 类 MyCalcHelp
公共 allstr 作为 字符串 =
公开 tmpstr 作为 字符串 =
公开 mytext As 字符串 =
公共计数器作为 整数 = < span class =code-digit> 0
私人 Sub MyCalcHelp_KeyUp( ByVal sender As Object , ByVal e As System.Windows.Forms.KeyEventArgs)句柄 我 .KeyUp
如果 e .KeyValue = Keys.Escape 然后
应用程序。退出()
结束 如果
如果 e.KeyValue = Keys.Enter 和 tmpstr<> \"\" Then
allstr = allstr & tmpstr
'MessageBox.Show(Me.Top.ToString)
tmpstr = \"\"
If counter = 0 Then
mytext = \"question1\"
TextBox1.Text = mytext
counter += 1
ElseIf counter = 1 Then
mytext = \"question2\"
TextBox1.Text = mytext
counter += 1
ElseIf c ounter = 2 Then
mytext = \"question3\"
TextBox1.Text = mytext
counter += 1
ElseIf counter = 3 Then
mytext = \"question4\"
TextBox1.Text = mytext
counter += 1
End If
End If
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each argument As String In My.Application.CommandLineArgs
PictureBox1.ImageLocation = argument
Exit For
Next
Me.WindowState = FormWindowState.Maximized
Panel1.Width = Me.Width
Panel1.Top = Me.Top + 12
Panel1.Height = Me.Height
Panel1.Left = Me.Left + 12
TextBox1.Text = \"Starting...\"
If counter = 0 Then
mytext = \"question1\"
TextBox1.Text = mytext
counter += 1
End If
End Sub
Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
Dim ScreenPos As Point = PictureBox1.PointToScreen(New Point(0, 0))
tmpstr = Control.MousePosition().X.ToString & \" \" & Control.MousePosition().Y.ToString & vbCrLf
TextBox1.Text = mytext & & tmpstr
MessageBox.Show(ScreenPos.X.ToString & \" \" & ScreenPos.Y.ToString)
End Sub
Private Sub TextBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove
If TextBox1.Location.Y = 0 Then
TextBox1.Location = New Point(10, 200)
Else
TextBox1.Location = New Point(10, 0)
End If
End Sub
End Class
I need some help with window api 32 bit programming in C with Visual C++ 2008.
Load a picture path/filename from command line in a window.
But if it is bigger with working scrollbars.
A mouseclick give the xy of the picture not from the window client area.
Has anyone an advice or example ?
I had a bit of spare time this evening while waiting for someone, so decided to have a bit of a play. I haven't bothered with error checking, you should add that yourself. I've also elected to program in a style similar to the one MS used when programming many of the different window-classes, as found in portions of the (re-engineered) Wine project. (https://github.com/wine-mirror/wine/tree/master/dlls/comctl32[^])
I've tried to make it very simple to interact with.
First, you must register the class - you can do this during program startup, before anything is shown on the screen.
Next, the two messages I've defined. IM_SETIMAGE and IM_GETCLICKPOS. You can send these messages explicitly, or you can use the supplied macros.
If you elect to send these messages yourself, you need only know:
IM_SETIMAGE expects the lParam to hold the HBITMAP of the new image. The return value is the previous image (if any, NULL otherwise)
IM_GETCLICKPOS takes no parameters and returns the position within the image of the last click pos (you get notified of clicks through a WM_COMMAND message). The lo-order word contains the X position and the hi-order word contains the Y position. Positions to the left/above the image return negative values.
The background colour isn't customizable from within the containing application, though you could easily add code to handle this situation, or more simply, edit the function onImgWindowEraseBackground.
The code's far from perfect, but should help provide a good starting point. You'll still have a bit of work. While you mention passing the name of a file to the program in order to choose the image, I'd suggest that you approach this with a little more sophistication and create a 'config' file of sorts. In this file, you could include things like (1) the name of the image file (2) the number of areas of interest (3) co-ordinate pairs for the points of a polygon that enclose these areas.
Perhaps something like this:
------------config.txt------------
Image: image.bmp
Poly Count: 3
Apple: 10,10, 20,10, 20,20, 10,20
Water Melon: 100,100, 200,100, 200,200, 100,200
Triangle: 50,50, 75,75, 25,75
----------------------------------
For a basic example of use, I've thrown-together the following dialog app. (written with Code::Blocks, built with MinGW)
main.cpp
#include <windows.h> #include <commctrl.h> #include <stdio.h> #include "resource.h" #include "../scrollImage/imgWindow.h" HINSTANCE hInst; BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: { HBITMAP img; img = (HBITMAP)LoadImage(hInst, "image.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE); ImageWindow_SetImage( GetDlgItem(hwndDlg, IDC_IMAGE_WINDOW), img); } return TRUE; case WM_CLOSE: { EndDialog(hwndDlg, 0); } return TRUE; case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_IMAGE_WINDOW: LPARAM clickPos = ImageWindow_GetClickPos( (HWND)lParam ); short xPos = LOWORD(clickPos); short yPos = HIWORD(clickPos); char msg[32]; sprintf(msg, "Click pos: %d,%d\n", xPos, yPos); SetDlgItemText(hwndDlg, IDC_CLICKPOS_OUTPUT, msg); break; } } return TRUE; } return FALSE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { hInst=hInstance; InitCommonControls(); IMGWINDOW_Register(); return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain); }
resource.h
#ifndef IDC_STATIC #define IDC_STATIC (-1) #endif #define DLG_MAIN 100 #define IDC_CLICKPOS_OUTPUT 40000 #define IDC_IMAGE_WINDOW 40001
resource.rc
// Generated by ResEdit 1.6.2 // Copyright (C) 2006-2014 // http://www.resedit.net #include <windows.h> #include <commctrl.h> #include <richedit.h> #include "resource.h" // // Dialog resources // LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL DLG_MAIN DIALOG 0, 0, 185, 166 STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU CAPTION "Dialog" FONT 8, "Ms Shell Dlg" { LTEXT "", IDC_CLICKPOS_OUTPUT, 7, 151, 171, 8, SS_LEFT, WS_EX_LEFT CONTROL "", IDC_IMAGE_WINDOW, "imgWindow32", 0x50020000, 7, 7, 171, 139, 0x00000000 }
Finally, here's the meat and bones of the image display and click-pos calculation.
Again, quite simple even if a little lengthy.
imgWindow.h
#ifndef imgWindow_h #define imgWindow_h #include <windows.h> // externably callable functions // BOOL IMGWINDOW_Register(); void IMGWINDOW_Unregister(); // window class-name definitions // #define IMGWINDOW_CLASSA "imgWindow32" #define IMGWINDOW_CLASSW L"imgWindow32" #ifdef UNICODE #define IMGWINDOW_CLASS IMGWINDOW_CLASSW #else #define IMGWINDOW_CLASS IMGWINDOW_CLASSA #endif // UNICODE // available user-defined messages for this class // #define IM_SETIMAGE WM_USER + 1 #define IM_GETCLICKPOS WM_USER + 2 // macros for interacting with the control using the above-defined messages // #define ImageWindow_SetImage(hWnd, hBitmap) SendMessage(hWnd, IM_SETIMAGE, 0, (LPARAM)hBitmap) #define ImageWindow_GetClickPos(hWnd) SendMessage(hWnd, IM_GETCLICKPOS, 0, 0) #endif // imgWindow_h
imgWindow.cpp
#include "imgWindow.h" #ifndef min #define min(a,b) a < b ? a : b #endif // min typedef struct { HWND self; short clickX, clickY; BOOL mouseDown; int xScrollPos, yScrollPos; int xImgOfs, yImgOfs; HBITMAP bkg; HDC memDC; HBITMAP oldMemBmp; int bmpWidth, bmpHeight; RECT clientRect; } IMGWINDOW_INFO; #define IMGWINDOW_GetInfoPtr(hWindow) ((IMGWINDOW_INFO *)GetWindowLongPtr (hWindow, 0)) int onImgWindowCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) { IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO*)LocalAlloc(LPTR, sizeof(IMGWINDOW_INFO)); if (!infoPtr) return -1; ZeroMemory(infoPtr, sizeof(infoPtr)); infoPtr->self = hwnd; infoPtr->clickX = -1; infoPtr->clickY = -1; HDC mDC; mDC = GetDC(hwnd); infoPtr->memDC = CreateCompatibleDC(mDC); infoPtr->oldMemBmp = (HBITMAP) GetCurrentObject(infoPtr->memDC, OBJ_BITMAP); ReleaseDC(hwnd, mDC); GetClientRect(hwnd, &infoPtr->clientRect); SetWindowLong(hwnd, 0, (LONG)infoPtr); // possible x64 problem here // return 0; } int onImgWindowDestroy(HWND hwnd) { IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO*)LocalAlloc(LPTR, sizeof(IMGWINDOW_INFO)); SelectObject(infoPtr->memDC, infoPtr->oldMemBmp); DeleteDC( infoPtr->memDC ); LocalFree(infoPtr); return 0; } int onImgWindowEraseBackground(HWND hwnd, WPARAM wParam, LPARAM lParam) { RECT clientRect; HBRUSH bkBrush; IMGWINDOW_INFO *infoPtr = IMGWINDOW_GetInfoPtr(hwnd); bkBrush = CreateSolidBrush( RGB(255,0,255) ); GetClientRect(hwnd, &clientRect); FillRect( (HDC)wParam, &clientRect, bkBrush); DeleteObject(bkBrush); return 1; } int doImgWindowScroll(HWND hwnd, WPARAM wParam, int orientation, int windowMin, int windowMax) { int windowSize = windowMax - windowMin + 1; switch (LOWORD(wParam)) { case SB_THUMBTRACK: SetScrollPos(hwnd, orientation, HIWORD(wParam), true); break; case SB_PAGERIGHT: SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)+windowSize, true); break; case SB_PAGELEFT: SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)-windowSize, true); break; case SB_LINELEFT: SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)-16, true); break; case SB_LINERIGHT: SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)+16, true); break; } IMGWINDOW_INFO *mData = IMGWINDOW_GetInfoPtr(hwnd); int scrollPos = GetScrollPos(hwnd, orientation); if (orientation == SB_HORZ) mData->xScrollPos = scrollPos; else if (orientation == SB_VERT) mData->yScrollPos = scrollPos; InvalidateRect(hwnd, NULL, true); return 0; } int onImgWindowHscroll(HWND hwnd, WPARAM wParam, LPARAM lParam) { RECT clientRect; GetClientRect(hwnd, &clientRect); return doImgWindowScroll(hwnd, wParam, SB_HORZ, clientRect.left, clientRect.right); } int onImgWindowVscroll(HWND hwnd, WPARAM wParam, LPARAM lParam) { RECT clientRect; GetClientRect(hwnd, &clientRect); return doImgWindowScroll(hwnd, wParam, SB_VERT, clientRect.top, clientRect.bottom); } void imgWindowSetScrollInfo(HWND hwnd) { int mWidth; RECT mRect; SCROLLINFO si = {}; IMGWINDOW_INFO *infoPtr = IMGWINDOW_GetInfoPtr(hwnd); GetClientRect(hwnd, &mRect); mWidth = mRect.right - mRect.left + 1; si.cbSize = sizeof(si); si.fMask = SIF_ALL; si.nMin = 0; si.nMax = infoPtr->bmpWidth;// - mWidth;// - mWidth; si.nPage = mWidth; si.nPos = 0; infoPtr->xScrollPos = 0; SetScrollInfo(hwnd, SB_HORZ, &si, false); int mHeight; mHeight = mRect.bottom-mRect.top + 1; si.cbSize = sizeof(si); si.fMask = SIF_ALL; si.nMin = 0; si.nMax = infoPtr->bmpHeight;// - mHeight; si.nPage = mHeight; si.nPos = 0; infoPtr->yScrollPos = 0; SetScrollInfo(hwnd, SB_VERT, &si, true); } LRESULT onImgWindowSetImage(HWND hwnd, WPARAM wParam, LPARAM lParam) { IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0); HBITMAP oldImg; oldImg = infoPtr->bkg; infoPtr->bkg = (HBITMAP) lParam; BITMAP bm; GetObject(infoPtr->bkg, sizeof(bm), &bm); infoPtr->bmpWidth = bm.bmWidth; infoPtr->bmpHeight = bm.bmHeight; if (infoPtr->bmpWidth > (infoPtr->clientRect.right-infoPtr->clientRect.left) ) ShowScrollBar(hwnd, SB_HORZ, true); else ShowScrollBar(hwnd, SB_HORZ, false); if (infoPtr->bmpHeight > (infoPtr->clientRect.bottom-infoPtr->clientRect.top) ) ShowScrollBar(hwnd, SB_VERT, true); else ShowScrollBar(hwnd, SB_VERT, false); imgWindowSetScrollInfo(hwnd); SelectObject(infoPtr->memDC, infoPtr->bkg); InvalidateRect(infoPtr->self, NULL, true); return (LRESULT)oldImg; } // window's background fades-in when hovered LRESULT CALLBACK IMGWINDOW_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0); switch (message) // handle the messages { case WM_CREATE: return onImgWindowCreate(hwnd, wParam, lParam); case WM_DESTROY: return onImgWindowDestroy(hwnd); // lParam = (HBITMAP) img case IM_SETIMAGE: return onImgWindowSetImage(hwnd, wParam, lParam); case WM_ERASEBKGND: return onImgWindowEraseBackground(hwnd, wParam, lParam); case WM_PAINT: HDC hdc; PAINTSTRUCT ps; int mWidth, mHeight; RECT mRect; GetClientRect(hwnd, &mRect); mWidth = mRect.right-mRect.left + 1; mHeight = mRect.bottom-mRect.top + 1; hdc = BeginPaint(hwnd, &ps); int xOfs,yOfs; xOfs = yOfs = 0; if (infoPtr->bmpWidth < mWidth) xOfs = (mWidth-infoPtr->bmpWidth)/2; if (infoPtr->bmpHeight < mHeight) yOfs = (mHeight-infoPtr->bmpHeight)/2; infoPtr->xImgOfs = xOfs; infoPtr->yImgOfs = yOfs; int drawWidth, drawHeight; drawWidth = min(infoPtr->bmpWidth, mWidth); drawHeight = min(infoPtr->bmpHeight, mHeight); int imgXofs, imgYofs; imgXofs = infoPtr->xScrollPos; imgYofs = infoPtr->yScrollPos; BitBlt( hdc, xOfs, yOfs, drawWidth,drawHeight, infoPtr->memDC, imgXofs,imgYofs, SRCCOPY); EndPaint(hwnd, &ps); return 0; case WM_HSCROLL: return onImgWindowHscroll(hwnd, wParam, lParam); case WM_VSCROLL: return onImgWindowVscroll(hwnd, wParam, lParam); case WM_SIZE: GetClientRect(hwnd, &infoPtr->clientRect); InvalidateRect(hwnd, NULL, true); return 0; case WM_GETDLGCODE: return DLGC_STATIC; case WM_LBUTTONDOWN: infoPtr->mouseDown = true; return 0; case WM_LBUTTONUP: { // save the point ready to use in response to the IM_GETCLICKPOS message infoPtr->clickX = (short)(LOWORD(lParam) + infoPtr->xScrollPos - infoPtr->xImgOfs); infoPtr->clickY = (short)(HIWORD(lParam) + infoPtr->yScrollPos - infoPtr->yImgOfs); // tell the paent window that we were clicked with a WM_COMMAND message short myNotifIdCode = 0; if (infoPtr->mouseDown == true) SendMessage(GetParent(infoPtr->self), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(infoPtr->self),myNotifIdCode), (LPARAM)infoPtr->self); } infoPtr->mouseDown = false; break; case IM_GETCLICKPOS: return MAKELPARAM(infoPtr->clickX, infoPtr->clickY); } return DefWindowProc (hwnd, message, wParam, lParam); } BOOL IMGWINDOW_Register(void) { WNDCLASS wndClass; ZeroMemory (&wndClass, sizeof(WNDCLASS)); wndClass.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_OWNDC;//CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS; wndClass.lpfnWndProc = IMGWINDOW_WindowProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = sizeof(IMGWINDOW_INFO *); // accessed via getwindowlong(hWnd, nIndex) wndClass.hCursor = LoadCursor(0, IDC_ARROW); wndClass.hbrBackground = 0; wndClass.lpszClassName = IMGWINDOW_CLASS; if (RegisterClass(&wndClass) != 0) return true; else return false; } void IMGWINDOW_Unregister(void) { UnregisterClass(IMGWINDOW_CLASS, NULL); }
Thank you for the clarification. Everything is well described here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645533%28v=vs.85%29.aspx[^].
Samples? It would not be too hard, but who will spend so much time? Who of us would waste so much time for writing it all in pure C. Why? Few simple exercises could be useful for learning, but meticulously baying all those elephants… :-)
How about this: you read the documentation and try to write code, ask separate questions when you face problems?
—SA
In Visual Basic it is sooooo easy.
In future I will write windows elements in VB and code that must be faster
in C as dll. All infos I get from google.
Public Class MyCalcHelp Public allstr As String = "" Public tmpstr As String = "" Public mytext As String = "" Public counter As Integer = 0 Private Sub MyCalcHelp_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp If e.KeyValue = Keys.Escape Then Application.Exit() End If If e.KeyValue = Keys.Enter And tmpstr <> "" Then allstr = allstr & tmpstr 'MessageBox.Show(Me.Top.ToString) tmpstr = "" If counter = 0 Then mytext = "question1" TextBox1.Text = mytext counter += 1 ElseIf counter = 1 Then mytext = "question2" TextBox1.Text = mytext counter += 1 ElseIf counter = 2 Then mytext = "question3" TextBox1.Text = mytext counter += 1 ElseIf counter = 3 Then mytext = "question4" TextBox1.Text = mytext counter += 1 End If End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For Each argument As String In My.Application.CommandLineArgs PictureBox1.ImageLocation = argument Exit For Next Me.WindowState = FormWindowState.Maximized Panel1.Width = Me.Width Panel1.Top = Me.Top + 12 Panel1.Height = Me.Height Panel1.Left = Me.Left + 12 TextBox1.Text = "Starting..." If counter = 0 Then mytext = "question1" TextBox1.Text = mytext counter += 1 End If End Sub Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click Dim ScreenPos As Point = PictureBox1.PointToScreen(New Point(0, 0)) tmpstr = Control.MousePosition().X.ToString & " " & Control.MousePosition().Y.ToString & vbCrLf TextBox1.Text = mytext & " " & tmpstr MessageBox.Show(ScreenPos.X.ToString & " " & ScreenPos.Y.ToString) End Sub Private Sub TextBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove If TextBox1.Location.Y = 0 Then TextBox1.Location = New Point(10, 200) Else TextBox1.Location = New Point(10, 0) End If End Sub End Class
这篇关于加载图片可滚动&鼠标点击时获取x,y的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!