| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 1088 人关注过本帖, 1 人收藏
标题:希望实现将指定jpg文件载入win10系统粘贴板,并进行诸如旋转180度,高度缩小 ...
只看楼主 加入收藏
shschy
Rank: 2
等 级:论坛游民
帖 子:142
专家分:48
注 册:2022-3-13
收藏(1)
已结贴  问题点数:10 回复次数:9 
希望实现将指定jpg文件载入win10系统粘贴板,并进行诸如旋转180度,高度缩小xx,宽度缩小xx,再旋转180度
希望实现将指定jpg文件载入win10系统粘贴板,并进行诸如旋转180度,高度缩小xx,宽度缩小xx,再旋转180度
(1)以下第一步载入到win10系统粘贴板就报错,
(2)后面旋转180度,高度缩小xx,宽度缩小xx,再旋转180度,保存操作查到的代码各种报错。
下面是将"D:\01\clipboard_001.jpg"载入操作系统粘贴板的代码,其余代码因为也报错,暂不张贴。
谢谢!

LOCAL lcImagePath
lcImagePath = "D:\01\clipboard_001.jpg"

IF NOT FILE(lcImagePath)
    MESSAGEBOX("图片不存在:" + lcImagePath, 16, "错误")
    RETURN
ENDIF

* 声明API
DECLARE INTEGER OpenClipboard IN user32.dll INTEGER hwnd
DECLARE INTEGER EmptyClipboard IN user32.dll
DECLARE INTEGER CloseClipboard IN user32.dll
DECLARE INTEGER SetClipboardData IN user32.dll INTEGER uFormat, INTEGER hMem
DECLARE INTEGER GlobalAlloc IN kernel32.dll INTEGER uFlags, INTEGER dwBytes
DECLARE INTEGER GlobalLock IN kernel32.dll INTEGER hMem
DECLARE INTEGER GlobalUnlock IN kernel32.dll INTEGER hMem
DECLARE INTEGER GetFileSize IN kernel32.dll INTEGER hFile, INTEGER lpFileSizeHigh
DECLARE INTEGER CreateFile IN kernel32.dll STRING lpFileName, INTEGER dwDesiredAccess, ;
    INTEGER dwShareMode, INTEGER lpSecurityAttributes, INTEGER dwCreationDisposition, ;
    INTEGER dwFlagsAndAttributes, INTEGER hTemplateFile
DECLARE INTEGER ReadFile IN kernel32.dll INTEGER hFile, STRING @lpBuffer, INTEGER nNumberOfBytesToRead, ;
    INTEGER @lpNumberOfBytesRead, INTEGER lpOverlapped
DECLARE INTEGER CloseHandle IN kernel32.dll INTEGER hObject

* 打开剪贴板
IF OpenClipboard(0) = 0
    MESSAGEBOX("打开剪贴板失败", 16)
    RETURN
ENDIF
EmptyClipboard()

* 读取图片文件
hFile = CreateFile(lcImagePath, 1, 3, 0, 3, 128, 0)
IF hFile = -1
    MESSAGEBOX("打开文件失败", 16)
    CloseClipboard()
    RETURN
ENDIF

nFileSize = GetFileSize(hFile, 0)
cBuffer = REPLICATE(CHR(0), nFileSize)
ReadFile(hFile, @cBuffer, nFileSize, @nReadBytes, 0)
CloseHandle(hFile)

* 写入剪贴板
hGlobal = GlobalAlloc(64, nFileSize)
lpGlobal = GlobalLock(hGlobal)
SYS(2600, lpGlobal, nFileSize, cBuffer)
GlobalUnlock(hGlobal)
SetClipboardData(8, hGlobal)

* 关闭剪贴板
CloseClipboard()

* 清理
CLEAR DLLS
MESSAGEBOX("图片已载入剪贴板!", 64)
SET SAFETY ON
RETURN
搜索更多相关主题的帖子: 缩小 旋转 INTEGER dll 载入 
2025-12-11 02:45
sych
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:636
专家分:761
注 册:2019-10-11
收藏
得分:4 
Public Declare Function GdipImageRotateFlip Lib "gdiplus" (ByVal Image As Long, ByVal rfType As RotateFlipType) As GpStatus
    RotateNoneFlipNone = 0, // 不旋转不翻转
    Rotate90FlipNone = 1, // 旋转90度不翻转
    Rotate180FlipNone = 2, // 旋转180度不翻转
    Rotate270FlipNone = 3, // 旋转270度不翻转
    RotateNoneFlipX = 4, // 不旋转x向翻转
    Rotate90FlipX = 5, // 旋转90度x向翻转
    Rotate180FlipX = 6, // 旋转180度x向翻转
    Rotate270FlipX = 7, // 旋转270度x向翻转
Declare Long GdipDrawImageRectI in GdiPlus.dll Long graphics, Long image, long x, long y, long width, long height
    把原图变化到多大(后两个参数),复制到新图哪个位置(前两个参数)
2025-12-11 10:12
schtg
Rank: 13Rank: 13Rank: 13Rank: 13
来 自:USA
等 级:贵宾
威 望:67
帖 子:2715
专家分:4967
注 册:2012-2-29
收藏
得分:4 
回复 2楼 sych
学习啦,谢谢!
2025-12-12 07:17
shschy
Rank: 2
等 级:论坛游民
帖 子:142
专家分:48
注 册:2022-3-13
收藏
得分:0 
打开画图工具后,执行ctrl+v,提示“剪贴板上的信息无法插入画图”
在VFP9表单的command控件click事件里写如下代码,提示“截图已旋转成功并写回剪贴板”,但打开画图工具后,执行ctrl+v,提示“剪贴板上的信息无法插入画图”
LOCAL nGdiplusToken, hImage, nStatus, oClipboard
LOCAL Rotate180FlipNone, GP_OK, GDIP_S_OK
LOCAL lcGdiplusInput, nVersion

* -------------------------- 1. 修正API声明和常量 --------------------------
* GDI+初始化/终止函数(补充结构体参数的正确定义)
DECLARE INTEGER GdiplusStartup IN gdiplus;
    INTEGER @token, STRING @input, STRING @output
DECLARE INTEGER GdiplusShutdown IN gdiplus INTEGER token

* 图像旋转函数
DECLARE INTEGER GdipImageRotateFlip IN gdiplus;
    INTEGER hImage, INTEGER rfType

* 剪贴板/位图相关API
DECLARE INTEGER OpenClipboard IN user32 INTEGER hwnd
DECLARE INTEGER GetClipboardData IN user32 INTEGER uFormat
DECLARE INTEGER CloseClipboard IN user32
DECLARE INTEGER DeleteObject IN gdi32 INTEGER hObject
DECLARE INTEGER EmptyClipboard IN user32
DECLARE INTEGER SetClipboardData IN user32 INTEGER uFormat, INTEGER hMem

* GDI+位图转换API
DECLARE INTEGER GdipCreateBitmapFromHBITMAP IN gdiplus;
    INTEGER hBitmap, INTEGER hPalette, INTEGER @hImage
DECLARE INTEGER GdipDisposeImage IN gdiplus INTEGER hImage
DECLARE INTEGER GdipCreateHBITMAPFromBitmap IN gdiplus;
    INTEGER hImage, INTEGER @hBitmap, INTEGER BackgroundColor

* 常量定义
#DEFINE CF_BITMAP 2          && 剪贴板位图格式
#DEFINE GDIP_S_OK 0         && GDI+操作成功返回值
Rotate180FlipNone = 2       && 旋转180度不翻转

* -------------------------- 2. 正确初始化GdiplusStartupInput结构体 --------------------------
* GdiplusStartupInput结构体结构(共16字节):
* 偏移0-3:GdiplusVersion(UINT32,必须=1)
* 偏移4-7:DebugEventCallback(DWORD,=0)
* 偏移8-11:SuppressBackgroundThread(BOOL,=0)
* 偏移12-15:SuppressExternalCodecs(BOOL,=0)
nVersion = 1
lcGdiplusInput = ;
    BINTOC(nVersion, "4RS") + ;  && 版本号设为1(4字节,小端序)
    REPLICATE(CHR(0), 12)        && 其余字段填0

nGdiplusToken = 0
nStatus = GdiplusStartup(@nGdiplusToken, @lcGdiplusInput, 0)
IF nStatus <> GDIP_S_OK
    MESSAGEBOX("GDI+初始化失败!错误码:" + ALLTRIM(STR(nStatus)), 16, "错误")
    * 额外排查:检查gdiplus.dll是否存在
    IF !FILE("C:\Windows\SysWOW64\gdiplus.dll") AND !FILE("C:\Windows\System32\gdiplus.dll")
        MESSAGEBOX("未找到gdiplus.dll!请确认系统已安装GDI+组件", 16, "提示")
    ENDIF
    RETURN
ENDIF

* -------------------------- 3. 读取剪贴板中的截图 --------------------------
hImage = 0
hBitmap = 0
IF OpenClipboard(Thisform.HWnd) = 1
    hBitmap = GetClipboardData(CF_BITMAP)
    IF hBitmap <> 0
        nStatus = GdipCreateBitmapFromHBITMAP(hBitmap, 0, @hImage)
        IF nStatus <> GDIP_S_OK
            MESSAGEBOX("剪贴板无有效截图!错误码:" + ALLTRIM(STR(nStatus)), 16, "提示")
            CloseClipboard()
            GdiplusShutdown(nGdiplusToken)
            RETURN
        ENDIF
    ELSE
        MESSAGEBOX("剪贴板无位图数据!", 16, "提示")
        CloseClipboard()
        GdiplusShutdown(nGdiplusToken)
        RETURN
    ENDIF
    CloseClipboard()
ELSE
    MESSAGEBOX("无法打开剪贴板!", 16, "错误")
    GdiplusShutdown(nGdiplusToken)
    RETURN
ENDIF

* -------------------------- 4. 执行180度旋转 --------------------------
nStatus = GdipImageRotateFlip(hImage, Rotate180FlipNone)
IF nStatus <> GDIP_S_OK
    MESSAGEBOX("图像旋转失败!错误码:" + ALLTRIM(STR(nStatus)), 16, "错误")
    GdipDisposeImage(hImage)
    DeleteObject(hBitmap)
    GdiplusShutdown(nGdiplusToken)
    RETURN
ENDIF

* -------------------------- 5. 将旋转后的图像写回剪贴板 --------------------------
hNewBitmap = 0
nStatus = GdipCreateHBITMAPFromBitmap(hImage, @hNewBitmap, 0xFFFFFFFF)  && 白色背景
IF nStatus = GDIP_S_OK
    OpenClipboard(Thisform.HWnd)
    EmptyClipboard()  
    SetClipboardData(CF_BITMAP, hNewBitmap)  
    CloseClipboard()
    DeleteObject(hNewBitmap)
ENDIF

* -------------------------- 6. 释放资源 --------------------------
GdipDisposeImage(hImage)      
DeleteObject(hBitmap)         
GdiplusShutdown(nGdiplusToken)

MESSAGEBOX("截图已旋转180度并写回剪贴板!", 64, "成功")

以下是引用sych在2025-12-11 10:12:32的发言:

Public Declare Function GdipImageRotateFlip Lib "gdiplus" (ByVal Image As Long, ByVal rfType As RotateFlipType) As GpStatus
    RotateNoneFlipNone = 0, // 不旋转不翻转
    Rotate90FlipNone = 1, // 旋转90度不翻转
    Rotate180FlipNone = 2, // 旋转180度不翻转
    Rotate270FlipNone = 3, // 旋转270度不翻转
    RotateNoneFlipX = 4, // 不旋转x向翻转
    Rotate90FlipX = 5, // 旋转90度x向翻转
    Rotate180FlipX = 6, // 旋转180度x向翻转
    Rotate270FlipX = 7, // 旋转270度x向翻转
Declare Long GdipDrawImageRectI in GdiPlus.dll Long graphics, Long image, long x, long y, long width, long height
    把原图变化到多大(后两个参数),复制到新图哪个位置(前两个参数)

2025-12-13 03:14
sych
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:7
帖 子:636
专家分:761
注 册:2019-10-11
收藏
得分:0 
* -------------------------- 5. 将旋转后的图像写回剪贴板 --------------------------
DECLARE Long CopyImage IN WIN32API Long hImage, Long, Long, Long , Long
hNewBitmap = 0
nStatus = GdipCreateHBITMAPFromBitmap(hImage, @hNewBitmap, 0xFFFFFFFF)  && 白色背景
IF nStatus = GDIP_S_OK
    hBitmap=copyImage(hNewBitmap,0,0,0,0)
    OpenClipboard(Thisform.HWnd)
    EmptyClipboard()  
    SetClipboardData(CF_BITMAP, hBitmap)  
    CloseClipboard()
    DeleteObject(hNewBitmap)
ENDIF
2025-12-14 07:26
foxfans
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:186
专家分:392
注 册:2021-10-23
收藏
得分:4 
以前玩过类似的功能,OpenClipboard CopyImage SetClipboardData 得判断返回值,特别是SetClipboardData,失败的话hBitmap也得释放,要不有概率发生泄漏问题,甚至会破坏当前剪切板功能。
图片附件: 游客没有浏览图片的权限,请 登录注册



[此贴子已经被作者于2025-12-17 16:56编辑过]

2025-12-14 16:30
shschy
Rank: 2
等 级:论坛游民
帖 子:142
专家分:48
注 册:2022-3-13
收藏
得分:0 
如何在按钮控件的click事件中直接实现将粘贴板里的截图旋转180度?
如何在按钮控件的click事件中直接实现将粘贴板里的截图旋转180度?
以下代码无法实现
以下是引用sych在2025-12-14 07:26:58的发言:

* -------------------------- 5. 将旋转后的图像写回剪贴板 --------------------------
DECLARE Long CopyImage IN WIN32API Long hImage, Long, Long, Long , Long
hNewBitmap = 0
nStatus = GdipCreateHBITMAPFromBitmap(hImage, @hNewBitmap, 0xFFFFFFFF)  && 白色背景
IF nStatus = GDIP_S_OK
    hBitmap=copyImage(hNewBitmap,0,0,0,0)
    OpenClipboard(Thisform.HWnd)
    EmptyClipboard()  
    SetClipboardData(CF_BITMAP, hBitmap)  
    CloseClipboard()
    DeleteObject(hNewBitmap)
ENDIF

2025-12-14 20:20
iswith
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:5
帖 子:803
专家分:753
注 册:2013-5-14
收藏
得分:0 
1. 安装所需库
pip install Pillow pywin32
2. 完整代码实现
import win32clipboard
import win32con
from PIL import Image
import io
import os

def image_to_clipboard(image_path):
    """
    将指定图片文件加载到Windows剪贴板
    """
    try:
        # 打开并处理图片
        img = Image.open(image_path)
        
        # 转换为RGB模式(确保兼容性)
        if img.mode != 'RGB':
            img = img.convert('RGB')
        
        # 将图像数据保存到内存字节流
        output = io.BytesIO()
        img.save(output, format='BMP')
        data = output.getvalue()[14:]  # 去掉BMP文件头
        
        # 打开剪贴板并设置数据
        win32clipboard.OpenClipboard()
        win32clipboard.EmptyClipboard()
        win32clipboard.SetClipboardData(win32con.CF_DIB, data)
        win32clipboard.CloseClipboard()
        
        print(f"图片 '{os.path.basename(image_path)}' 已成功复制到剪贴板")
        return img
        
    except Exception as e:
        print(f"错误: {e}")
        return None

def process_image_and_copy(image_path, scale_factor=0.5):
    """
    处理图片并复制到剪贴板
    处理步骤:旋转180度 -> 缩放 -> 再旋转180度
    """
    try:
        # 1. 打开图片
        img = Image.open(image_path)
        print(f"原始图片尺寸: {img.size}")
        
        # 2. 第一次旋转180度
        img = img.rotate(180, expand=True)
        print("第一次旋转180度完成")
        
        # 3. 缩放图片
        new_width = int(img.width * scale_factor)
        new_height = int(img.height * scale_factor)
        img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
        print(f"缩放完成: {img.size}")
        
        # 4. 第二次旋转180度
        img = img.rotate(180, expand=True)
        print("第二次旋转180度完成")
        
        # 5. 转换为RGB模式以确保兼容性
        if img.mode != 'RGB':
            img = img.convert('RGB')
        
        # 6. 保存处理后的图片(可选)
        processed_path = "processed_image.jpg"
        img.save(processed_path, quality=95)
        print(f"处理后的图片已保存为: {processed_path}")
        
        # 7. 复制到剪贴板
        output = io.BytesIO()
        img.save(output, format='BMP')
        data = output.getvalue()[14:]  # 去掉BMP文件头
        
        win32clipboard.OpenClipboard()
        win32clipboard.EmptyClipboard()
        win32clipboard.SetClipboardData(win32con.CF_DIB, data)
        win32clipboard.CloseClipboard()
        
        print("处理后的图片已复制到剪贴板")
        
        return img
        
    except Exception as e:
        print(f"处理图片时出错: {e}")
        return None

def save_clipboard_image(save_path="clipboard_saved.jpg"):
    """
    从剪贴板读取图片并保存
    """
    try:
        win32clipboard.OpenClipboard()
        
        # 尝试获取DIB格式的数据
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_DIB):
            data = win32clipboard.GetClipboardData(win32con.CF_DIB)
            
            # 添加BMP文件头
            bmp_header = b'BM' + (len(data) + 14).to_bytes(4, 'little') + b'\x00\x00\x00\x00\x36\x00\x00\x00'
            bmp_data = bmp_header + data
            
            # 从内存中读取BMP数据
            img = Image.open(io.BytesIO(bmp_data))
            img.save(save_path)
            print(f"剪贴板图片已保存为: {save_path}")
            return img
        else:
            print("剪贴板中没有图片数据")
            return None
            
    except Exception as e:
        print(f"保存剪贴板图片时出错: {e}")
        return None
    finally:
        win32clipboard.CloseClipboard()

# 使用方法示例
if __name__ == "__main__":
    # 图片路径
    image_path = r"D:\01\clipboard_001.jpg"
   
    # 方法1: 直接将图片复制到剪贴板(不处理)
    print("=" * 50)
    print("方法1: 直接复制图片到剪贴板")
    print("=" * 50)
    image_to_clipboard(image_path)
   
    # 方法2: 处理图片后复制到剪贴板
    print("\n" + "=" * 50)
    print("方法2: 处理图片后复制到剪贴板")
    print("=" * 50)
    process_image_and_copy(image_path, scale_factor=0.5)  # 缩小到50%
   
    # 方法3: 从剪贴板保存图片
    print("\n" + "=" * 50)
    print("方法3: 从剪贴板保存图片")
    print("=" * 50)
    save_clipboard_image("saved_from_clipboard.jpg")

    # 方法4: 把PY图片从内存中直接转成字节数组到vfp,这个见之前发布的netpy模块下的“NetPy_barcode_generator.prg”
2025-12-23 12:50
kmyz_yyl
Rank: 2
等 级:论坛游民
帖 子:73
专家分:35
注 册:2012-11-13
收藏
得分:0 
回复 6楼 foxfans
请教你那个图片旋转任意角度是怎么实现的,能否给一下代码?谢谢!
2026-02-04 09:49
hsfisher
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:311
专家分:142
注 册:2009-4-26
收藏
得分:0 
学习了
2026-02-04 10:44
快速回复:希望实现将指定jpg文件载入win10系统粘贴板,并进行诸如旋转180度,高 ...
数据加载中...
 
   
关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.016226 second(s), 10 queries.
Copyright©2004-2026, BCCN.NET, All Rights Reserved