Skip to content

Commit a5ebc65

Browse files
Initial Commit
0 parents  commit a5ebc65

File tree

12 files changed

+2409
-0
lines changed

12 files changed

+2409
-0
lines changed

.gitignore

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
### Node ###
2+
# Logs
3+
logs
4+
*.log
5+
npm-debug.log*
6+
yarn-debug.log*
7+
yarn-error.log*
8+
lerna-debug.log*
9+
10+
# Diagnostic reports (https://nodejs.org/api/report.html)
11+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12+
13+
# Runtime data
14+
pids
15+
*.pid
16+
*.seed
17+
*.pid.lock
18+
19+
# Directory for instrumented libs generated by jscoverage/JSCover
20+
lib-cov
21+
22+
# Coverage directory used by tools like istanbul
23+
coverage
24+
*.lcov
25+
26+
# nyc test coverage
27+
.nyc_output
28+
29+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30+
.grunt
31+
32+
# Bower dependency directory (https://bower.io/)
33+
bower_components
34+
35+
# node-waf configuration
36+
.lock-wscript
37+
38+
# Compiled binary addons (https://nodejs.org/api/addons.html)
39+
build/Release
40+
41+
build/
42+
# Dependency directories
43+
node_modules/
44+
jspm_packages/
45+
46+
# TypeScript v1 declaration files
47+
typings/
48+
49+
# TypeScript cache
50+
*.tsbuildinfo
51+
52+
# Optional npm cache directory
53+
.npm
54+
55+
# Optional eslint cache
56+
.eslintcache
57+
58+
# Optional REPL history
59+
.node_repl_history
60+
61+
# Output of 'npm pack'
62+
*.tgz
63+
64+
# Yarn Integrity file
65+
.yarn-integrity
66+
67+
# dotenv environment variables file
68+
.env
69+
.env.test
70+
71+
# parcel-bundler cache (https://parceljs.org/)
72+
.cache
73+
74+
# next.js build output
75+
.next
76+
77+
# nuxt.js build output
78+
.nuxt
79+
80+
# vuepress build output
81+
.vuepress/dist
82+
83+
# Serverless directories
84+
.serverless/
85+
86+
# FuseBox cache
87+
.fusebox/
88+
89+
# DynamoDB Local files
90+
.dynamodb/
91+
92+
### VisualStudioCode ###
93+
.vscode/*
94+
!.vscode/settings.json
95+
!.vscode/tasks.json
96+
!.vscode/launch.json
97+
!.vscode/extensions.json
98+
99+
### VisualStudioCode Patch ###
100+
# Ignore all local history of files
101+
.history

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"C_Cpp.errorSquiggles": "Disabled"
3+
}

License

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Soundofdarkness
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Readme.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Window Position (window-pos)
2+
3+
A small native library to get the size and position of a window on windows.
4+
5+
## Installing
6+
7+
```
8+
npm install git+https://github.com/Soundofdarkness/window-pos.git
9+
```
10+
11+
## Usage
12+
13+
```js
14+
const windowPos = require("window-pos");
15+
16+
// Rect: {top: 0, bottom: 0, left: 0, right: 0} or null if the window is not found.
17+
const rect = windowPos.getWindowCoords("Window Title");
18+
19+
// Size: {width: 0, height: 0}
20+
const size = windowPos.getWindowSize("Window Title")
21+
```
22+
23+
## Dependencies
24+
25+
- [Lodash.Clone](https://www.npmjs.com/package/lodash.clone) [MIT](https://github.com/lodash/lodash/blob/master/LICENSE)
26+
- [Node-Addon-Api](https://www.npmjs.com/package/node-addon-api) [MIT](https://github.com/nodejs/node-addon-api/blob/master/LICENSE.md)
27+
28+
Dev Dependencies:
29+
30+
- [Node-Gyp](https://www.npmjs.com/package/node-gyp) [MIT](https://github.com/nodejs/node-gyp/blob/master/LICENSE)
31+
- [Mocha](https://www.npmjs.com/package/mocha) [MIT](https://github.com/mochajs/mocha/blob/master/LICENSE)
32+
33+
## License
34+
35+
This project is licensed under the terms of the MIT License.
36+
See [License](/License)
37+

binding.gyp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "addon",
5+
"cflags!": [ "-fno-exceptions" ],
6+
"cflags_cc!": [ "-fno-exceptions" ],
7+
"sources": [ "src/addon.cc" ],
8+
"include_dirs": [
9+
"<!@(node -p \"require('node-addon-api').include\")"
10+
],
11+
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
12+
}
13+
]
14+
}

index.d.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Type definitions for window-pos 0.0.1
2+
// Definitions by: Soundofdarkness https://github.com/Soundofdarkness
3+
4+
export interface Rectangle {
5+
top: number;
6+
bottom: number;
7+
right: number;
8+
left: number;
9+
}
10+
11+
export interface WindowSize {
12+
width: number;
13+
height: number;
14+
}
15+
16+
export function getWindowCoords(name: string): Rectangle|null;
17+
18+
export function getWindowSize(name: string): WindowSize|null;

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("./lib/index");

lib/index.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use strict';
2+
3+
const internalapi = require("../build/Release/addon");
4+
const clone = require("lodash.clone");
5+
6+
7+
/**
8+
* Rectangle
9+
*
10+
* @typedef {Object} Rectangle
11+
* @property {number} top
12+
* @property {number} bottom
13+
* @property {number} right
14+
* @property {number} left
15+
*/
16+
17+
/**
18+
* Window Size
19+
* @typedef {Object} WindowSize
20+
* @property {number} width Window width
21+
* @property {number} height Window height
22+
*/
23+
24+
/**
25+
* Gets the Windows Bounds for a given Window Name.
26+
* Returns null if window not found.
27+
*
28+
* @param {string} name - Window name
29+
* @returns {Rectangle|null} Rectangle
30+
*
31+
* @throws {TypeError} Wrong Number of Arguments
32+
* @throws {TypeError} Window name is not a string
33+
* @throws {Error} Failed to get Window Bounds
34+
*/
35+
function getWindowCoords(name){
36+
const rect_internal = internalapi.getWindowCoords(name);
37+
38+
// Hopefully prevent the object from not being garbage collected ...
39+
const rect = clone(rect_internal);
40+
41+
return rect;
42+
}
43+
44+
/**
45+
* Gets the size of a specific Window
46+
* @param {string} name Window name
47+
* @throws {TypeError} Window name is not a string
48+
* @throws {Error} Failed to get Window Bounds
49+
* @returns {WindowSize|null} Size of the Window
50+
*/
51+
function getWindowSize(name){
52+
const rect = getWindowCoords(name);
53+
54+
if(rect === null){
55+
return null;
56+
}
57+
58+
const size = {
59+
width: rect.right - rect.left,
60+
height: rect.bottom - rect.top,
61+
}
62+
63+
return size;
64+
}
65+
66+
67+
module.exports = {
68+
getWindowCoords,
69+
getWindowSize
70+
}

package.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "window-pos",
3+
"version": "1.0.0",
4+
"description": "Gets the position of a Window in Windows",
5+
"main": "index.js",
6+
"types": "./index.d.ts",
7+
"scripts": {
8+
"test": "mocha",
9+
"test:ci": "SET CI=TRUE && mocha"
10+
},
11+
"keywords": [
12+
"Win32",
13+
"Windows"
14+
],
15+
"author": "Soundofdarkness",
16+
"license": "MIT",
17+
"gypfile": true,
18+
"os": ["win32"],
19+
"dependencies": {
20+
"lodash.clone": "^4.5.0",
21+
"node-addon-api": "^1.7.1"
22+
},
23+
"devDependencies": {
24+
"mocha": "^6.2.0",
25+
"node-gyp": "^5.0.3"
26+
}
27+
}

src/addon.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <napi.h>
2+
#include <windows.h>
3+
#include <dwmapi.h>
4+
5+
#pragma comment(lib, "dwmapi.lib")
6+
7+
// https://stackoverflow.com/questions/27220/how-to-convert-stdstring-to-lpcwstr-in-c-unicode
8+
std::wstring s2ws(const std::string& s){
9+
int len;
10+
int slength = (int)s.length() + 1;
11+
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
12+
wchar_t* buf = new wchar_t[len];
13+
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
14+
std::wstring r(buf);
15+
delete[] buf;
16+
return r;
17+
}
18+
19+
Napi::Value GetWindowCoords(const Napi::CallbackInfo& info){
20+
Napi::Env env = info.Env();
21+
22+
if(info.Length() != 1){
23+
Napi::TypeError::New(env, "Wrong Number of Arguments").ThrowAsJavaScriptException();
24+
return env.Null();
25+
}
26+
27+
if(!info[0].IsString()){
28+
Napi::TypeError::New(env, "Argument is not a string!").ThrowAsJavaScriptException();
29+
return env.Null();
30+
}
31+
32+
std::string windowName = info[0].As<Napi::String>().Utf8Value();
33+
34+
HWND hWnd = FindWindow(0, (LPCSTR)windowName.c_str());
35+
36+
if(hWnd == 0){
37+
return env.Null();
38+
}
39+
40+
RECT r;
41+
HRESULT stat = DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(r));
42+
if(stat != S_OK){
43+
Napi::Error::New(env, "Failed to get Window Bounds").ThrowAsJavaScriptException();
44+
return env.Null();
45+
}
46+
47+
Napi::Object returnObj = Napi::Object::New(env);
48+
returnObj.Set("top", double_t(r.top));
49+
returnObj.Set("bottom", double_t(r.bottom));
50+
returnObj.Set("left", double_t(r.left));
51+
returnObj.Set("right", double_t(r.right));
52+
53+
return returnObj;
54+
}
55+
56+
Napi::Object Init(Napi::Env env, Napi::Object exports){
57+
exports.Set("getWindowCoords", Napi::Function::New(env, GetWindowCoords));
58+
return exports;
59+
}
60+
61+
NODE_API_MODULE(addon, Init);

0 commit comments

Comments
 (0)