用c++生成了个通用的标准USB摄像头dll,包含上下左右镜像+亮度对比度调节功能

By admin at 2 小时前 • 0人收藏 • 6人看过

屏幕截图 2026-06-08 182515.png

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

#include <windows.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <mferror.h>
#include <unordered_map>
#include <thread>
#include <atomic>
#include <mutex>
#include <strmif.h> // 包含 IAMVideoProcAmp 硬件控制接口
#pragma comment(lib, "strmiids.lib") // 链接对应的静态库
// 链接 Media Foundation 和 COM 必要的系统静态库
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfreadwrite.lib")
#pragma comment(lib, "mfuuid.lib")
#pragma comment(lib, "mf.lib")       // <--- 解决 MFEnumDeviceSources 报错的关键
#pragma comment(lib, "ole32.lib")    // <--- 解决 CoInitializeEx 等 COM 内存管理函数


// --- 内部数据结构,用于管理每个摄像头的状态 ---
struct CameraContext {
    IMFSourceReader* pReader = nullptr;
    HWND hwnd = nullptr;
    int mirrorType = 0;
    std::thread captureThread;
    std::atomic<bool> isRunning{ false };
    LONG width = 0;
    LONG height = 0;
    // 【新增】:硬件属性控制器
    IAMVideoProcAmp* pProcAmp = nullptr;
};

// 全局变量:管理所有激活的摄像头
std::unordered_map<int, CameraContext*> g_Cameras;
std::mutex g_Mutex;
bool g_MfInitialized = false;

// --- 内部辅助函数:寻找并设置最高分辨率 ---
void SetMaxResolution(IMFSourceReader* pReader, LONG& outWidth, LONG& outHeight) {
    DWORD bestIndex = 0;
    LONG maxPixels = 0;
    double maxFps = 0.0; // 新增:用于记录当前最高帧率
    outWidth = 640; outHeight = 480; // 默认兜底

    IMFMediaType* pType = nullptr;
    for (DWORD i = 0; ; i++) {
        HRESULT hr = pReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, i, &pType);
        if (FAILED(hr)) break; // 遍历结束

        UINT32 w = 0, h = 0;
        UINT32 fpsNumerator = 0, fpsDenominator = 1;

        // 1. 获取分辨率
        MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &w, &h);

        // 2. 获取帧率 (分母不能为0的保护)
        if (SUCCEEDED(MFGetAttributeRatio(pType, MF_MT_FRAME_RATE, &fpsNumerator, &fpsDenominator)) && fpsDenominator > 0) {
            // 计算实际的浮点帧率
            double currentFps = (double)fpsNumerator / fpsDenominator;
            LONG currentPixels = w * h;

            // 3. 核心筛选逻辑:
            // 条件A: 如果像素更高,直接替换
            // 条件B: 如果像素一样高,但帧率更高,也替换
            if (currentPixels > maxPixels || (currentPixels == maxPixels && currentFps > maxFps)) {
                maxPixels = currentPixels;
                maxFps = currentFps;
                bestIndex = i;
                outWidth = w;
                outHeight = h;
            }
        }
        pType->Release();
    }

    // 应用筛选出的最高分辨率和帧率
    if (maxPixels > 0) {
        pReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, bestIndex, &pType);
        pReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pType);

        // 如果你在 aardio 开了控制台,可以用这句打印出来确认一下:
        // printf("已锁定最高画质: %d x %d @ %.2f FPS\n", outWidth, outHeight, maxFps);

        pType->Release();
    }
}

// --- 内部后台线程:负责不断抓帧并渲染 ---
void CaptureThreadFunc(int deviceIndex) {
    CoInitializeEx(NULL, COINIT_MULTITHREADED); // 线程初始化 COM

    CameraContext* ctx = nullptr;
    {
        std::lock_guard<std::mutex> lock(g_Mutex);
        if (g_Cameras.find(deviceIndex) != g_Cameras.end()) {
            ctx = g_Cameras[deviceIndex];
        }
    }
    if (!ctx) return;

    // 准备 GDI 绘制所需的 BITMAP 信息 (RGB32 格式)
    BITMAPINFO bmi = { 0 };
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = ctx->width;
    bmi.bmiHeader.biHeight = -ctx->height; // 负数表示自顶向下的 DIB
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;

    while (ctx->isRunning) {
        IMFSample* pSample = nullptr;
        DWORD streamIndex, flags;
        LONGLONG llTimeStamp;

        // 读取一帧 (阻塞调用)
        HRESULT hr = ctx->pReader->ReadSample(
            (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
            0, &streamIndex, &flags, &llTimeStamp, &pSample);

        if (FAILED(hr) || !pSample) {
            Sleep(10); // 避免 CPU 空转
            continue;
        }

        // 提取图像数据
        IMFMediaBuffer* pBuffer = nullptr;
        if (SUCCEEDED(pSample->ConvertToContiguousBuffer(&pBuffer))) {
            BYTE* pData = nullptr;
            DWORD cbData = 0;
            if (SUCCEEDED(pBuffer->Lock(&pData, nullptr, &cbData))) {

                // 开始向目标句柄绘制
                HDC hdc = GetDC(ctx->hwnd);
                if (hdc) {
                    // 获取容器大小
                    RECT rect;
                    GetClientRect(ctx->hwnd, &rect);
                    int targetW = rect.right - rect.left;
                    int targetH = rect.bottom - rect.top;

                    // ==========================================================
                    // 【终极修复:1像素边缘溢出补偿 (Overscan)】
                    // 专门解决 Windows GDI 拉伸算法导致的 1 像素舍入黑边问题
                    // 故意让坐标向外扩张 1 像素,强制覆盖所有底色缝隙
                    // ==========================================================
                    int destX = 0, destY = 0;
                    int destW = 0, destH = 0;

                    switch (ctx->mirrorType) {
                    case 0: // 正常 (左上起点 -1, -1,宽高各加 2)
        
                        destX = -1; destY = -1;
                        destW = targetW + 2; destH = targetH + 2;
                        break;
                    case 1: // 上下翻转
                    case -1:
                        destX = -1; destY = targetH + 1;
                        destW = targetW + 2; destH = -(targetH + 2);
                        break;
                    case 2: // 左右翻转
                    case -2:
                        destX = targetW + 1; destY = -1;
                        destW = -(targetW + 2); destH = targetH + 2;
                        break;
                    case 3: // 全翻转
                    case -3:
                        destX = targetW + 1; destY = targetH + 1;
                        destW = -(targetW + 2); destH = -(targetH + 2);
                        break;
                    }

                    // 开启高质量平滑渲染,并重置画刷原点
                    SetStretchBltMode(hdc, HALFTONE);
                    SetBrushOrgEx(hdc, 0, 0, NULL);

                    // 执行绘制
                    StretchDIBits(hdc,
                        destX, destY, destW, destH, // 带有补偿的目标坐标
                        0, 0, ctx->width, ctx->height, // 源图像坐标
                        pData, &bmi, DIB_RGB_COLORS, SRCCOPY);

                    ReleaseDC(ctx->hwnd, hdc);
                }
                pBuffer->Unlock();
            }
            pBuffer->Release();
        }
        pSample->Release();
    }
    CoUninitialize();
}

// ==========================================================
//                     向外导出的标准 API
// ==========================================================

// 注意开头的 void 改成了 bool
BOOL InitCamera(int deviceIndex, int mirrorType, int placeholderHWnd) {
    std::lock_guard<std::mutex> lock(g_Mutex);

    if (mirrorType < -3 || mirrorType > 3)
    {
        mirrorType = 0;
    }

    if (!g_MfInitialized) {
        if (FAILED(MFStartup(MF_VERSION))) return FALSE; // 初始化底层失败
        g_MfInitialized = true;
    }

    if (g_Cameras.find(deviceIndex) != g_Cameras.end()) {
        g_Cameras[deviceIndex]->isRunning = false;
        if (g_Cameras[deviceIndex]->captureThread.joinable()) {
            g_Cameras[deviceIndex]->captureThread.join();
        }
        g_Cameras[deviceIndex]->pReader->Release();
        delete g_Cameras[deviceIndex];
        g_Cameras.erase(deviceIndex);
    }

    IMFAttributes* pConfig = nullptr;
    MFCreateAttributes(&pConfig, 1);
    pConfig->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);

    IMFActivate** ppDevices = nullptr;
    UINT32 count = 0;
    HRESULT hrEnum = MFEnumDeviceSources(pConfig, &ppDevices, &count);
    pConfig->Release();

    // 检查:枚举失败、设备数为0、或者请求的索引越界,统统返回 false
    if (FAILED(hrEnum) || count == 0 || deviceIndex < 0 || deviceIndex >= (int)count) {
        if (ppDevices) {
            for (UINT32 i = 0; i < count; i++) ppDevices[i]->Release();
            CoTaskMemFree(ppDevices);
        }
        return FALSE;
    }

    IMFMediaSource* pSource = nullptr;
    HRESULT hrAct = ppDevices[deviceIndex]->ActivateObject(IID_PPV_ARGS(&pSource));

    for (UINT32 i = 0; i < count; i++) ppDevices[i]->Release();
    CoTaskMemFree(ppDevices);

    if (FAILED(hrAct) || !pSource) return FALSE;

    // ==========================================================
    // 【新增】:向摄像头索要硬件控制权限 (IAMVideoProcAmp)
    // ==========================================================
    IAMVideoProcAmp* pProcAmp = nullptr;
    pSource->QueryInterface(IID_PPV_ARGS(&pProcAmp));
    // 注意:哪怕拿不到(有些极其便宜的山寨摄像头不支持),pProcAmp 也是 null,不影响主流程


    IMFAttributes* pReaderConfig = nullptr;
    MFCreateAttributes(&pReaderConfig, 1);
    pReaderConfig->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE);

    IMFSourceReader* pReader = nullptr;
    HRESULT hrRead = MFCreateSourceReaderFromMediaSource(pSource, pReaderConfig, &pReader);
    pReaderConfig->Release();
    pSource->Release();

    if (FAILED(hrRead) || !pReader) return FALSE; // 视频流读取器创建失败

    LONG width = 0, height = 0;
    SetMaxResolution(pReader, width, height);

    IMFMediaType* pOutputFormat = nullptr;
    MFCreateMediaType(&pOutputFormat);
    pOutputFormat->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
    pOutputFormat->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
    pReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pOutputFormat);
    pOutputFormat->Release();

    CameraContext* ctx = new CameraContext();
    ctx->pReader = pReader;
    ctx->hwnd = (HWND)(LONG_PTR)placeholderHWnd;
    ctx->mirrorType = mirrorType;
    ctx->width = width;
    ctx->height = height;
    ctx->isRunning = true;
    ctx->pProcAmp = pProcAmp; // 存入上下文
    g_Cameras[deviceIndex] = ctx;

    ctx->captureThread = std::thread(CaptureThreadFunc, deviceIndex);

    // 一切顺利,成功启动!
    return TRUE;
}
// ==========================================================
// 动态设置摄像头镜像模式 (运行时即时生效)
// deviceIndex: 摄像头索引
// mirrorType: 0=正常, 1=上下, 2=左右, 3=全翻转
// 返回值: 成功返回 TRUE,失败返回 FALSE (例如该摄像头未启动)
// ==========================================================
BOOL CameraMirror(int deviceIndex, int mirrorType) {
    // 加锁以保证线程安全
    std::lock_guard<std::mutex> lock(g_Mutex);

    if (mirrorType < -3 || mirrorType > 3)
    {
        mirrorType = 0;
    }
    // 查找指定索引的摄像头是否存在
    auto it = g_Cameras.find(deviceIndex);
    if (it != g_Cameras.end()) {
        // 直接修改上下文中的镜像标记
        // 后台抓图线程在绘制下一帧时,会自动应用新的翻转坐标
        it->second->mirrorType = mirrorType;
        return TRUE;
    }

    return FALSE;
}

// ==========================================================
// 硬件调节接口:亮度(0)、对比度(1)、色调(2)、饱和度(3)、清晰度(4)、白平衡(7)
// ==========================================================

// 1. 获取某个属性的支持范围(如果返回 FALSE,说明该摄像头不支持此功能)
BOOL CameraPropRangeGet(int deviceIndex, int propId, int* pMin, int* pMax, int* pStep, int* pDefault, int* pFlags) {
    std::lock_guard<std::mutex> lock(g_Mutex);
    auto it = g_Cameras.find(deviceIndex);
    if (it != g_Cameras.end() && it->second->pProcAmp) {
        long lMin, lMax, lStep, lDefault, lCapsFlags;
        HRESULT hr = it->second->pProcAmp->GetRange(propId, &lMin, &lMax, &lStep, &lDefault, &lCapsFlags);
        if (SUCCEEDED(hr)) {
            *pMin = lMin; *pMax = lMax; *pStep = lStep; *pDefault = lDefault; *pFlags = lCapsFlags;
            return TRUE;
        }
    }
    return FALSE;
}

// 2. 获取当前属性的数值
BOOL CameraPropGet(int deviceIndex, int propId, int* pValue, int* pFlags) {
    std::lock_guard<std::mutex> lock(g_Mutex);
    auto it = g_Cameras.find(deviceIndex);
    if (it != g_Cameras.end() && it->second->pProcAmp) {
        long lValue, lFlags;
        HRESULT hr = it->second->pProcAmp->Get(propId, &lValue, &lFlags);
        if (SUCCEEDED(hr)) {
            *pValue = lValue; *pFlags = lFlags;
            return TRUE;
        }
    }
    return FALSE;
}

// 3. 设置当前属性的数值 (flags: 1=自动, 2=手动)
BOOL CameraPropSet(int deviceIndex, int propId, int value, int flags) {
    std::lock_guard<std::mutex> lock(g_Mutex);
    auto it = g_Cameras.find(deviceIndex);
    if (it != g_Cameras.end() && it->second->pProcAmp) {
        HRESULT hr = it->second->pProcAmp->Set(propId, value, flags);
        return SUCCEEDED(hr) ? TRUE : FALSE;
    }
    return FALSE;
}

void CloseCamera(int deviceIndex) {
    std::lock_guard<std::mutex> lock(g_Mutex);

    auto it = g_Cameras.find(deviceIndex);
    if (it != g_Cameras.end()) {
        CameraContext* ctx = it->second;

        // 1. 挂出免战牌,通知循环结束
        ctx->isRunning = false;

        // ==========================================================
        // 【核心防卡死修复】:强行踢醒底层卡死的 ReadSample 线程
        // ==========================================================
        if (ctx->pReader) {
            // Flush 指令会强行清空底层的硬件缓冲区。
            // 最神奇的是,它会让一直卡着不动的 ReadSample 瞬间苏醒,
            // 并强行返回一个错误代码(跳出阻塞状态)。
            ctx->pReader->Flush((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM);
        }

        // 2. 此时再等线程下班,就能瞬间等到了,绝对不会再卡死!
        if (ctx->captureThread.joinable()) {
            ctx->captureThread.join();
        }

        if (ctx->pReader) {
            ctx->pReader->Release();
        }

        // 清理残影
        InvalidateRect(ctx->hwnd, NULL, TRUE);
        UpdateWindow(ctx->hwnd);

        if (ctx->pProcAmp) {
            ctx->pProcAmp->Release();
            ctx->pProcAmp = nullptr;
        }

        delete ctx;
        g_Cameras.erase(it);
    }
}

void CloseAllCameras() {
    // 拷贝一份 keys 以免遍历时删除导致迭代器失效
    std::vector<int> keys;
    {
        std::lock_guard<std::mutex> lock(g_Mutex);
        for (auto& pair : g_Cameras) keys.push_back(pair.first);
    }

    for (int k : keys) {
        CloseCamera(k);
    }

    if (g_MfInitialized) {
        MFShutdown();
        g_MfInitialized = false;
    }
}


aardio调用代码:

import win.ui;
import console;
/*DSG{{*/
var mainForm = win.form(text="工业级视觉监控面板 (纯原生 C++ 核心)";right=880;bottom=560)
mainForm.add(
btnStart={cls="button";text="启动设备";left=650;top=30;right=850;bottom=70;z=2};
btnStop={cls="button";text="安全关闭";left=650;top=90;right=850;bottom=130;disabled=1;z=3};
button={cls="button";text="恢复默认";left=650;top=351;right=850;bottom=391;z=11};
comboMirror={cls="combobox";left=730;top=150;right=850;bottom=176;edge=1;items={"正常显示","上下翻转","左右翻转","全翻转"};mode="dropdownlist";z=5};
groupProp={cls="groupbox";text="硬件图像调节 (芯片级)";left=640;top=210;right=860;bottom=411;edge=1;z=6};
lbBright={cls="static";text="亮度:";left=650;top=240;right=690;bottom=260;transparent=1;z=7};
lbContrast={cls="static";text="对比度:";left=650;top=300;right=700;bottom=320;transparent=1;z=9};
lbMirror={cls="static";text="镜像模式:";left=650;top=154;right=730;bottom=178;transparent=1;z=4};
trackBright={cls="trackbar";left=690;top=235;right=850;bottom=265;disabled=1;max=100;min=0;z=8};
trackContrast={cls="trackbar";left=690;top=295;right=850;bottom=325;disabled=1;max=100;min=0;z=10};
videoPanel={cls="custom";text="监控画面就绪";left=20;top=20;right=620;bottom=530;bgcolor=0x0000FF;color=0xFFFFFF;z=1}
)
/*}}*/

// 打开控制台方便查阅底层日志
console.open();
console.log("初始化系统...");

// ==========================================
// 1. 加载动态链接库与 API 声明
// ==========================================
// 请确保 VideoXNative.dll 和编译出的 exe 在同一目录下
var camDll = raw.loadDll("\res\VideoX.dll");

var apiInitCamera    = camDll.api("InitCamera", "bool(int deviceIndex, int mirrorType, int hwnd)");
var apiCloseCamera   = camDll.api("CloseCamera", "void(int deviceIndex)");
var apiCloseAll      = camDll.api("CloseAllCameras", "void()");
var apiSetMirror     = camDll.api("CameraMirror", "bool(int deviceIndex, int mirrorType)");
var apiGetPropRange  = camDll.api("CameraPropRangeGet", "bool(int deviceIndex, int propId, int &pMin, int &pMax, int &pStep, int &pDefault, int &pFlags)");
var apiSetProp       = camDll.api("CameraPropSet", "bool(int deviceIndex, int propId, int value, int flags)");

// 全局状态变量
var currentDeviceIndex = 0; // 默认挂载 0 号摄像头
var isRunning = false;

// DirectShow 硬件属性标准 ID
var PROP_BRIGHTNESS = 0;
var PROP_CONTRAST = 1;

// 初始化镜像下拉框的默认选择
mainForm.comboMirror.selIndex = 1;

// ==========================================
// 2. 硬件参数调节初始化模块
// ==========================================
var initHardwareControls = function(){
    var min=0; var max=0; var step=0; var def=0; var flags=0;
    
    var success, min, max, step, def, flags = apiGetPropRange(currentDeviceIndex, PROP_BRIGHTNESS, 0, 0, 0, 0, 0);
    
    if(success == 1){
        mainForm.trackBright.setRange(min, max);
        mainForm.trackBright.pos = def;
        mainForm.trackBright.disabled = false;
        console.log("✅ 亮度控制激活,范围:", min, "~", max, "默认值:", def);
    } else {
        mainForm.trackBright.disabled = true;
        console.log("❌ 硬件不支持亮度调节");
    }
    
    // 对比度也是同样的接法
    var success2, min2, max2, step2, def2, flags2 = apiGetPropRange(currentDeviceIndex, PROP_CONTRAST, 0, 0, 0, 0, 0);
    
    if(success2 == 1){
        mainForm.trackContrast.setRange(min2, max2);
        mainForm.trackContrast.pos = def2;
        mainForm.trackContrast.disabled = false;
        console.log("✅ 对比度控制激活,范围:", min2, "~", max2, "默认值:", def2);
    } else {
        mainForm.trackContrast.disabled = true;
        console.log("❌ 硬件不支持对比度调节");
    }
    
    
}

// ==========================================
// 3. UI 交互事件绑定
// ==========================================

// 启动摄像头按钮
mainForm.btnStart.oncommand = function(id,event){
    if(isRunning) return;
    
    mainForm.btnStart.disabled = true;
    mainForm.btnStart.text = "正在唤醒硬件...";
    
    // 获取当前用户选择的镜像模式 (combo 索引从 1 开始,需减 1)
    var mirrorMode = mainForm.comboMirror.selIndex - 1;
    
    // 调用 C++ 底层进行硬件启动与句柄嵌套
    var success = apiInitCamera(currentDeviceIndex, mirrorMode, mainForm.videoPanel.hwnd);
    
    if(success == 1){
        isRunning = true;
        console.log("✅ 摄像头启动成功,底层渲染管线已建立。");
        
        mainForm.btnStart.text = "运行中...";
        mainForm.btnStop.disabled = false;
        
        // 尝试探测并开放芯片参数调节
        initHardwareControls();
    } else {
        console.log("❌ 硬件唤醒失败。可能被独占或权限遭拒。");
        mainForm.btnStart.disabled = false;
        mainForm.btnStart.text = "启动设备";
        mainForm.msgboxErr("底层接口返回失败:未能成功开启硬件数据流。");
    }
}

// 关闭摄像头按钮
mainForm.btnStop.oncommand = function(id,event){
    if(!isRunning) return;
    
    console.log("正在向 C++ 发送安全中断信号...");
    apiCloseCamera(currentDeviceIndex);
    
    isRunning = false;
    mainForm.btnStart.disabled = false;
    mainForm.btnStart.text = "启动设备";
    mainForm.btnStop.disabled = true;
    
    // 禁用硬件滑块并重置黑底
    mainForm.trackBright.disabled = true;
    mainForm.trackContrast.disabled = true;
    mainForm.videoPanel.redraw(); 
    console.log("设备已安全下线。");
}

// 动态镜像下拉框切换事件 (无缝热切换)
mainForm.comboMirror.onListChange = function(){
    if(!isRunning) return; // 没启动时不发底层指令
    
    var mirrorMode = mainForm.comboMirror.selIndex - 1;
    var result = apiSetMirror(currentDeviceIndex, mirrorMode);
    
    if(result == 1){
        console.log("内存热写入:镜像模式已切换至 " ++ mirrorMode);
    }
}



mainForm.trackBright.oncommand = function(id,event,pos){ 
	 if(!isRunning) return;
    // 参数 2 代表设为手动调节 (Manual)
    var ret = apiSetProp(currentDeviceIndex, PROP_BRIGHTNESS, owner.pos, 2);
     console.log(ret,owner.pos);
}
mainForm.trackContrast.oncommand = function(id,event,pos){ 
	 if(!isRunning) return;
    var ret = apiSetProp(currentDeviceIndex, PROP_CONTRAST, owner.pos, 2);
     console.log(ret,owner.pos);
}



// 窗口销毁,安全阻断所有硬件释放内存
mainForm.onDestroy = function(){
    console.log("系统退出,正在释放全部系统内存与硬件锁...");
    apiCloseAll();
}

mainForm.button.oncommand = function(id,event){
	if(!isRunning) return;
    
    // 1. 恢复亮度
    // 再次调用 GetPropRange 接口,只为了拿到其中的 def (默认值)
    var successB, minB, maxB, stepB, defB, flagsB = apiGetPropRange(currentDeviceIndex, PROP_BRIGHTNESS, 0, 0, 0, 0, 0);
    if(successB == 1){
        // 向硬件下发默认值 (参数 2 代表手动模式)
        apiSetProp(currentDeviceIndex, PROP_BRIGHTNESS, defB, 2);
        // 同步更新滑动条的 UI 位置
        mainForm.trackBright.pos = defB; 
        console.log("亮度已恢复出厂默认值:", defB);
    }
    
    // 2. 恢复对比度
    var successC, minC, maxC, stepC, defC, flagsC = apiGetPropRange(currentDeviceIndex, PROP_CONTRAST, 0, 0, 0, 0, 0);
    if(successC == 1){
        apiSetProp(currentDeviceIndex, PROP_CONTRAST, defC, 2);
        mainForm.trackContrast.pos = defC;
        console.log("对比度已恢复出厂默认值:", defC);
    }
}

mainForm.show();
return win.loopMessage();


编译生成的dll 和工程代码:

aardio 工程.zip

VideoX.zip


登录后方可回帖

登 录
信息栏
本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网
在线小工具
Pojie.Online

才仁机械


网站地图SiteMap

Loading...