Skip to content

Instantly share code, notes, and snippets.

@CalebWhiting
Last active November 24, 2016 22:32
Show Gist options
  • Select an option

  • Save CalebWhiting/af5de7db973f37ded205ff0256bac94b to your computer and use it in GitHub Desktop.

Select an option

Save CalebWhiting/af5de7db973f37ded205ff0256bac94b to your computer and use it in GitHub Desktop.
/*
* WindowHandle.cpp
*
* Author: Caleb Whiting
*/
#include "jni/org_jscrape_internal_WindowHandle.h"
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std;
#define JAVA_WRAPPER "org/jscrape/internal/WindowHandle"
struct JNI_ENUM_WINDOWS_PARAM {
vector<jobject>* vect;
JNIEnv* env;
};
template<typename T>
void invoke(JNIEnv* env, jobject o, jclass cls, const char* methodName,
const char* signature, T arguments, ...) {
jmethodID mid = env->GetMethodID(cls, methodName, signature);
env->CallVoidMethod(o, mid, arguments);
}
void setBounds(JNIEnv* env, jobject o, jclass cls, const char* methodName,
RECT b) {
invoke(env, o, cls, methodName, "(IIII)V", b.top, b.right, b.bottom,
b.left);
}
BOOL CALLBACK AddWindowToVector(HWND h, LPARAM ptr) {
// Variables
JNI_ENUM_WINDOWS_PARAM* param = reinterpret_cast<JNI_ENUM_WINDOWS_PARAM*>(ptr);
JNIEnv* env = param->env;
vector<jobject>* vect = param->vect;
HDC hdc = GetDC(h);
RECT windowRect;
RECT clientRect;
TITLEBARINFO ti;
jclass cls = env->FindClass(JAVA_WRAPPER);
// Check that the vector doesn't contain this process already
DWORD pid;
GetWindowThreadProcessId(h, &pid);
for (vector<jobject>::size_type i = 0; i != vect->size(); i++) {
jobject o = vect->at(i);
int ppid = env->CallIntMethod(o, env -> GetMethodID(cls, "hashCode", "()I"));
if (ppid == pid) {
goto cleanup;
}
}
// Create instance
jmethodID construct = env->GetMethodID(cls, "<init>", "(I)V");
jobject o = env->NewObject(cls, construct, pid);
// Set properties
GetWindowRect(h, &windowRect);
setBounds(env, o, cls, "setWindowRect", windowRect);
GetClientRect(h, &clientRect);
setBounds(env, o, cls, "setClientRect", clientRect);
// Set Title
int titleLength = GetWindowTextLength(h) + 1;
TCHAR* titleText = new TCHAR[titleLength];
titleLength = GetWindowText(h, titleText, titleLength);
jchar* title = new jchar[titleLength];
for (int i = 0; i < titleLength; i++) {
title[i] = titleText[i];
}
invoke(env, o, cls, "setTitle", "(Ljava/lang/String;)V",
env->NewString(title, titleLength));
// Get TitleBarInfo
if (GetTitleBarInfo(h, &ti)) {
RECT tb = ti.rcTitleBar;
setBounds(env, o, cls, "setTitleRect", tb);
}
// Push
vect->push_back(o);
// Cleanup
cleanup: {
ReleaseDC(h, hdc);
DeleteDC(hdc);
return true;
}
}
/*
* Class: org_jscrape_internal_WindowHandle
* Method: getHandles
* Signature: ()[Lorg/jscrape/internal/WindowHandle;
*/
JNIEXPORT jobjectArray JNICALL
Java_org_jscrape_internal_WindowHandle_getHandles(JNIEnv * env, jclass c) {
// Set environment for the callback
// Iterate windows and add to vector
vector<jobject>* vect = new vector<jobject>();
JNI_ENUM_WINDOWS_PARAM param;
param.vect = vect;
param.env = env;
EnumWindows(&AddWindowToVector, reinterpret_cast<LPARAM>(&param));
// Copy to JNI array
jobjectArray arr = env->NewObjectArray(vect->size(), c, nullptr);
for (vector<jobject>::size_type i = 0; i != vect->size(); i++) {
jobject o = vect->at(i);
env->SetObjectArrayElement(arr, i, o);
}
// Cleanup
vect->clear();
delete vect;
// Return
return arr;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment